1 /* $FreeBSD$ */ 2 /*- 3 * Copyright (c) 2008 Hans Petter Selasky. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27 #include <sys/queue.h> 28 29 #include <stdio.h> 30 #include <stdlib.h> 31 #include <string.h> 32 33 #include "libusb20.h" 34 #include "libusb20_desc.h" 35 #include "libusb20_int.h" 36 37 static const uint32_t libusb20_me_encode_empty[2]; /* dummy */ 38 39 LIBUSB20_MAKE_STRUCT_FORMAT(LIBUSB20_DEVICE_DESC); 40 LIBUSB20_MAKE_STRUCT_FORMAT(LIBUSB20_ENDPOINT_DESC); 41 LIBUSB20_MAKE_STRUCT_FORMAT(LIBUSB20_INTERFACE_DESC); 42 LIBUSB20_MAKE_STRUCT_FORMAT(LIBUSB20_CONFIG_DESC); 43 LIBUSB20_MAKE_STRUCT_FORMAT(LIBUSB20_CONTROL_SETUP); 44 45 /*------------------------------------------------------------------------* 46 * libusb20_parse_config_desc 47 * 48 * Return values: 49 * NULL: Out of memory. 50 * Else: A valid config structure pointer which must be passed to "free()" 51 *------------------------------------------------------------------------*/ 52 struct libusb20_config * 53 libusb20_parse_config_desc(const void *config_desc) 54 { 55 struct libusb20_config *lub_config; 56 struct libusb20_interface *lub_interface; 57 struct libusb20_interface *lub_alt_interface; 58 struct libusb20_interface *last_if; 59 struct libusb20_endpoint *lub_endpoint; 60 struct libusb20_endpoint *last_ep; 61 62 struct libusb20_me_struct pcdesc; 63 const uint8_t *ptr; 64 uint32_t size; 65 uint16_t niface_no_alt; 66 uint16_t niface; 67 uint16_t nendpoint; 68 uint8_t iface_no; 69 70 ptr = config_desc; 71 if (ptr[1] != LIBUSB20_DT_CONFIG) { 72 return (NULL); /* not config descriptor */ 73 } 74 /* 75 * The first "bInterfaceNumber" should never have the value 0xff. 76 * Then it is corrupt. 77 */ 78 niface_no_alt = 0; 79 nendpoint = 0; 80 niface = 0; 81 iface_no = 0 - 1; 82 ptr = NULL; 83 84 /* get "wTotalLength" and setup "pcdesc" */ 85 pcdesc.ptr = LIBUSB20_ADD_BYTES(config_desc, 0); 86 pcdesc.len = 87 ((const uint8_t *)config_desc)[2] | 88 (((const uint8_t *)config_desc)[3] << 8); 89 pcdesc.type = LIBUSB20_ME_IS_RAW; 90 91 /* descriptor pre-scan */ 92 while ((ptr = libusb20_desc_foreach(&pcdesc, ptr))) { 93 if (ptr[1] == LIBUSB20_DT_ENDPOINT) { 94 nendpoint++; 95 } else if ((ptr[1] == LIBUSB20_DT_INTERFACE) && (ptr[0] >= 4)) { 96 niface++; 97 /* check "bInterfaceNumber" */ 98 if (ptr[2] != iface_no) { 99 iface_no = ptr[2]; 100 niface_no_alt++; 101 } 102 } 103 } 104 105 /* sanity checking */ 106 if (niface >= 256) { 107 return (NULL); /* corrupt */ 108 } 109 if (nendpoint >= 256) { 110 return (NULL); /* corrupt */ 111 } 112 size = sizeof(*lub_config) + 113 (niface * sizeof(*lub_interface)) + 114 (nendpoint * sizeof(*lub_endpoint)) + 115 pcdesc.len; 116 117 lub_config = malloc(size); 118 if (lub_config == NULL) { 119 return (NULL); /* out of memory */ 120 } 121 /* make sure memory is initialised */ 122 memset(lub_config, 0, size); 123 124 lub_interface = (void *)(lub_config + 1); 125 lub_alt_interface = (void *)(lub_interface + niface_no_alt); 126 lub_endpoint = (void *)(lub_interface + niface); 127 128 /* 129 * Make a copy of the config descriptor, so that the caller can free 130 * the inital config descriptor pointer! 131 */ 132 ptr = (void *)(lub_endpoint + nendpoint); 133 memcpy(LIBUSB20_ADD_BYTES(ptr, 0), config_desc, pcdesc.len); 134 pcdesc.ptr = LIBUSB20_ADD_BYTES(ptr, 0); 135 config_desc = LIBUSB20_ADD_BYTES(ptr, 0); 136 137 /* init config structure */ 138 139 ptr = config_desc; 140 141 LIBUSB20_INIT(LIBUSB20_CONFIG_DESC, &lub_config->desc); 142 143 if (libusb20_me_decode(ptr, ptr[0], &lub_config->desc)) { 144 /* ignore */ 145 } 146 lub_config->num_interface = 0; 147 lub_config->interface = lub_interface; 148 lub_config->extra.ptr = LIBUSB20_ADD_BYTES(ptr, ptr[0]); 149 lub_config->extra.len = -ptr[0]; 150 lub_config->extra.type = LIBUSB20_ME_IS_RAW; 151 152 /* reset states */ 153 niface = 0; 154 iface_no = 0 - 1; 155 ptr = NULL; 156 lub_interface--; 157 lub_endpoint--; 158 last_if = NULL; 159 last_ep = NULL; 160 161 /* descriptor pre-scan */ 162 while ((ptr = libusb20_desc_foreach(&pcdesc, ptr))) { 163 if (ptr[1] == LIBUSB20_DT_ENDPOINT) { 164 if (last_if) { 165 lub_endpoint++; 166 last_ep = lub_endpoint; 167 last_if->num_endpoints++; 168 169 LIBUSB20_INIT(LIBUSB20_ENDPOINT_DESC, &last_ep->desc); 170 171 if (libusb20_me_decode(ptr, ptr[0], &last_ep->desc)) { 172 /* ignore */ 173 } 174 last_ep->extra.ptr = LIBUSB20_ADD_BYTES(ptr, ptr[0]); 175 last_ep->extra.len = 0; 176 last_ep->extra.type = LIBUSB20_ME_IS_RAW; 177 } else { 178 lub_config->extra.len += ptr[0]; 179 } 180 181 } else if ((ptr[1] == LIBUSB20_DT_INTERFACE) && (ptr[0] >= 4)) { 182 if (ptr[2] != iface_no) { 183 /* new interface */ 184 iface_no = ptr[2]; 185 lub_interface++; 186 lub_config->num_interface++; 187 last_if = lub_interface; 188 niface++; 189 } else { 190 /* one more alternate setting */ 191 lub_interface->num_altsetting++; 192 last_if = lub_alt_interface; 193 lub_alt_interface++; 194 } 195 196 LIBUSB20_INIT(LIBUSB20_INTERFACE_DESC, &last_if->desc); 197 198 if (libusb20_me_decode(ptr, ptr[0], &last_if->desc)) { 199 /* ignore */ 200 } 201 /* 202 * Sometimes USB devices have corrupt interface 203 * descriptors and we need to overwrite the provided 204 * interface number! 205 */ 206 last_if->desc.bInterfaceNumber = niface - 1; 207 last_if->extra.ptr = LIBUSB20_ADD_BYTES(ptr, ptr[0]); 208 last_if->extra.len = 0; 209 last_if->extra.type = LIBUSB20_ME_IS_RAW; 210 last_if->endpoints = lub_endpoint + 1; 211 last_if->altsetting = lub_alt_interface; 212 last_if->num_altsetting = 0; 213 last_if->num_endpoints = 0; 214 last_ep = NULL; 215 } else { 216 /* unknown descriptor */ 217 if (last_if) { 218 if (last_ep) { 219 last_ep->extra.len += ptr[0]; 220 } else { 221 last_if->extra.len += ptr[0]; 222 } 223 } else { 224 lub_config->extra.len += ptr[0]; 225 } 226 } 227 } 228 return (lub_config); 229 } 230 231 /*------------------------------------------------------------------------* 232 * libusb20_desc_foreach 233 * 234 * Safe traversal of USB descriptors. 235 * 236 * Return values: 237 * NULL: End of descriptors 238 * Else: Pointer to next descriptor 239 *------------------------------------------------------------------------*/ 240 const uint8_t * 241 libusb20_desc_foreach(const struct libusb20_me_struct *pdesc, 242 const uint8_t *psubdesc) 243 { 244 const uint8_t *start; 245 const uint8_t *end; 246 const uint8_t *desc_next; 247 248 /* be NULL safe */ 249 if (pdesc == NULL) 250 return (NULL); 251 252 start = (const uint8_t *)pdesc->ptr; 253 end = LIBUSB20_ADD_BYTES(start, pdesc->len); 254 255 /* get start of next descriptor */ 256 if (psubdesc == NULL) 257 psubdesc = start; 258 else 259 psubdesc = psubdesc + psubdesc[0]; 260 261 /* check that the next USB descriptor is within the range */ 262 if ((psubdesc < start) || (psubdesc >= end)) 263 return (NULL); /* out of range, or EOD */ 264 265 /* check start of the second next USB descriptor, if any */ 266 desc_next = psubdesc + psubdesc[0]; 267 if ((desc_next < start) || (desc_next > end)) 268 return (NULL); /* out of range */ 269 270 /* check minimum descriptor length */ 271 if (psubdesc[0] < 3) 272 return (NULL); /* too short descriptor */ 273 274 return (psubdesc); /* return start of next descriptor */ 275 } 276 277 /*------------------------------------------------------------------------* 278 * libusb20_me_get_1 - safety wrapper to read out one byte 279 *------------------------------------------------------------------------*/ 280 uint8_t 281 libusb20_me_get_1(const struct libusb20_me_struct *ie, uint16_t offset) 282 { 283 if (offset < ie->len) { 284 return (*((uint8_t *)LIBUSB20_ADD_BYTES(ie->ptr, offset))); 285 } 286 return (0); 287 } 288 289 /*------------------------------------------------------------------------* 290 * libusb20_me_get_2 - safety wrapper to read out one word 291 *------------------------------------------------------------------------*/ 292 uint16_t 293 libusb20_me_get_2(const struct libusb20_me_struct *ie, uint16_t offset) 294 { 295 return (libusb20_me_get_1(ie, offset) | 296 (libusb20_me_get_1(ie, offset + 1) << 8)); 297 } 298 299 /*------------------------------------------------------------------------* 300 * libusb20_me_encode - encode a message structure 301 * 302 * Description of parameters: 303 * "len" - maximum length of output buffer 304 * "ptr" - pointer to output buffer. If NULL, no data will be written 305 * "pd" - source structure 306 * 307 * Return values: 308 * 0..65535 - Number of bytes used, limited by the "len" input parameter. 309 *------------------------------------------------------------------------*/ 310 uint16_t 311 libusb20_me_encode(void *ptr, uint16_t len, const void *pd) 312 { 313 const uint8_t *pf; /* pointer to format data */ 314 uint8_t *buf; /* pointer to output buffer */ 315 316 uint32_t pd_offset; /* decoded structure offset */ 317 uint16_t len_old; /* old length */ 318 uint16_t pd_count; /* decoded element count */ 319 uint8_t me; /* message element */ 320 321 /* initialise */ 322 323 len_old = len; 324 buf = ptr; 325 pd_offset = sizeof(void *); 326 pf = (*((struct libusb20_me_format *const *)pd))->format; 327 328 /* scan */ 329 330 while (1) { 331 332 /* get information element */ 333 334 me = (pf[0]) & LIBUSB20_ME_MASK; 335 pd_count = pf[1] | (pf[2] << 8); 336 pf += 3; 337 338 /* encode the message element */ 339 340 switch (me) { 341 case LIBUSB20_ME_INT8: 342 while (pd_count--) { 343 uint8_t temp; 344 345 if (len < 1) /* overflow */ 346 goto done; 347 if (buf) { 348 temp = *((const uint8_t *) 349 LIBUSB20_ADD_BYTES(pd, pd_offset)); 350 buf[0] = temp; 351 buf += 1; 352 } 353 pd_offset += 1; 354 len -= 1; 355 } 356 break; 357 358 case LIBUSB20_ME_INT16: 359 pd_offset = -((-pd_offset) & ~1); /* align */ 360 while (pd_count--) { 361 uint16_t temp; 362 363 if (len < 2) /* overflow */ 364 goto done; 365 366 if (buf) { 367 temp = *((const uint16_t *) 368 LIBUSB20_ADD_BYTES(pd, pd_offset)); 369 buf[1] = (temp >> 8) & 0xFF; 370 buf[0] = temp & 0xFF; 371 buf += 2; 372 } 373 pd_offset += 2; 374 len -= 2; 375 } 376 break; 377 378 case LIBUSB20_ME_INT32: 379 pd_offset = -((-pd_offset) & ~3); /* align */ 380 while (pd_count--) { 381 uint32_t temp; 382 383 if (len < 4) /* overflow */ 384 goto done; 385 if (buf) { 386 temp = *((const uint32_t *) 387 LIBUSB20_ADD_BYTES(pd, pd_offset)); 388 buf[3] = (temp >> 24) & 0xFF; 389 buf[2] = (temp >> 16) & 0xFF; 390 buf[1] = (temp >> 8) & 0xFF; 391 buf[0] = temp & 0xFF; 392 buf += 4; 393 } 394 pd_offset += 4; 395 len -= 4; 396 } 397 break; 398 399 case LIBUSB20_ME_INT64: 400 pd_offset = -((-pd_offset) & ~7); /* align */ 401 while (pd_count--) { 402 uint64_t temp; 403 404 if (len < 8) /* overflow */ 405 goto done; 406 if (buf) { 407 408 temp = *((const uint64_t *) 409 LIBUSB20_ADD_BYTES(pd, pd_offset)); 410 buf[7] = (temp >> 56) & 0xFF; 411 buf[6] = (temp >> 48) & 0xFF; 412 buf[5] = (temp >> 40) & 0xFF; 413 buf[4] = (temp >> 32) & 0xFF; 414 buf[3] = (temp >> 24) & 0xFF; 415 buf[2] = (temp >> 16) & 0xFF; 416 buf[1] = (temp >> 8) & 0xFF; 417 buf[0] = temp & 0xFF; 418 buf += 8; 419 } 420 pd_offset += 8; 421 len -= 8; 422 } 423 break; 424 425 case LIBUSB20_ME_STRUCT: 426 pd_offset = -((-pd_offset) & 427 ~(LIBUSB20_ME_STRUCT_ALIGN - 1)); /* align */ 428 while (pd_count--) { 429 void *src_ptr; 430 uint16_t src_len; 431 struct libusb20_me_struct *ps; 432 433 ps = LIBUSB20_ADD_BYTES(pd, pd_offset); 434 435 switch (ps->type) { 436 case LIBUSB20_ME_IS_RAW: 437 src_len = ps->len; 438 src_ptr = ps->ptr; 439 break; 440 441 case LIBUSB20_ME_IS_ENCODED: 442 if (ps->len == 0) { 443 /* 444 * Length is encoded 445 * in the data itself 446 * and should be 447 * correct: 448 */ 449 ps->len = 0 - 1; 450 } 451 src_len = libusb20_me_get_1(pd, 0); 452 src_ptr = LIBUSB20_ADD_BYTES(ps->ptr, 1); 453 if (src_len == 0xFF) { 454 /* length is escaped */ 455 src_len = libusb20_me_get_2(pd, 1); 456 src_ptr = 457 LIBUSB20_ADD_BYTES(ps->ptr, 3); 458 } 459 break; 460 461 case LIBUSB20_ME_IS_DECODED: 462 /* reserve 3 length bytes */ 463 src_len = libusb20_me_encode(NULL, 464 0 - 1 - 3, ps->ptr); 465 src_ptr = NULL; 466 break; 467 468 default: /* empty structure */ 469 src_len = 0; 470 src_ptr = NULL; 471 break; 472 } 473 474 if (src_len > 0xFE) { 475 if (src_len > (uint16_t)(0 - 1 - 3)) 476 /* overflow */ 477 goto done; 478 479 if (len < (src_len + 3)) 480 /* overflow */ 481 goto done; 482 483 if (buf) { 484 buf[0] = 0xFF; 485 buf[1] = (src_len & 0xFF); 486 buf[2] = (src_len >> 8) & 0xFF; 487 buf += 3; 488 } 489 len -= (src_len + 3); 490 } else { 491 if (len < (src_len + 1)) 492 /* overflow */ 493 goto done; 494 495 if (buf) { 496 buf[0] = (src_len & 0xFF); 497 buf += 1; 498 } 499 len -= (src_len + 1); 500 } 501 502 /* check for buffer and non-zero length */ 503 504 if (buf && src_len) { 505 if (ps->type == LIBUSB20_ME_IS_DECODED) { 506 /* 507 * Repeat encode 508 * procedure - we have 509 * room for the 510 * complete structure: 511 */ 512 uint16_t dummy; 513 514 dummy = libusb20_me_encode(buf, 515 0 - 1 - 3, ps->ptr); 516 } else { 517 bcopy(src_ptr, buf, src_len); 518 } 519 buf += src_len; 520 } 521 pd_offset += sizeof(struct libusb20_me_struct); 522 } 523 break; 524 525 default: 526 goto done; 527 } 528 } 529 done: 530 return (len_old - len); 531 } 532 533 /*------------------------------------------------------------------------* 534 * libusb20_me_decode - decode a message into a decoded structure 535 * 536 * Description of parameters: 537 * "ptr" - message pointer 538 * "len" - message length 539 * "pd" - pointer to decoded structure 540 * 541 * Returns: 542 * "0..65535" - number of bytes decoded, limited by "len" 543 *------------------------------------------------------------------------*/ 544 uint16_t 545 libusb20_me_decode(const void *ptr, uint16_t len, void *pd) 546 { 547 const uint8_t *pf; /* pointer to format data */ 548 const uint8_t *buf; /* pointer to input buffer */ 549 550 uint32_t pd_offset; /* decoded structure offset */ 551 uint16_t len_old; /* old length */ 552 uint16_t pd_count; /* decoded element count */ 553 uint8_t me; /* message element */ 554 555 /* initialise */ 556 557 len_old = len; 558 buf = ptr; 559 pd_offset = sizeof(void *); 560 pf = (*((struct libusb20_me_format **)pd))->format; 561 562 /* scan */ 563 564 while (1) { 565 566 /* get information element */ 567 568 me = (pf[0]) & LIBUSB20_ME_MASK; 569 pd_count = pf[1] | (pf[2] << 8); 570 pf += 3; 571 572 /* decode the message element by type */ 573 574 switch (me) { 575 case LIBUSB20_ME_INT8: 576 while (pd_count--) { 577 uint8_t temp; 578 579 if (len < 1) { 580 len = 0; 581 temp = 0; 582 } else { 583 len -= 1; 584 temp = buf[0]; 585 buf++; 586 } 587 *((uint8_t *)LIBUSB20_ADD_BYTES(pd, 588 pd_offset)) = temp; 589 pd_offset += 1; 590 } 591 break; 592 593 case LIBUSB20_ME_INT16: 594 pd_offset = -((-pd_offset) & ~1); /* align */ 595 while (pd_count--) { 596 uint16_t temp; 597 598 if (len < 2) { 599 len = 0; 600 temp = 0; 601 } else { 602 len -= 2; 603 temp = buf[1] << 8; 604 temp |= buf[0]; 605 buf += 2; 606 } 607 *((uint16_t *)LIBUSB20_ADD_BYTES(pd, 608 pd_offset)) = temp; 609 pd_offset += 2; 610 } 611 break; 612 613 case LIBUSB20_ME_INT32: 614 pd_offset = -((-pd_offset) & ~3); /* align */ 615 while (pd_count--) { 616 uint32_t temp; 617 618 if (len < 4) { 619 len = 0; 620 temp = 0; 621 } else { 622 len -= 4; 623 temp = buf[3] << 24; 624 temp |= buf[2] << 16; 625 temp |= buf[1] << 8; 626 temp |= buf[0]; 627 buf += 4; 628 } 629 630 *((uint32_t *)LIBUSB20_ADD_BYTES(pd, 631 pd_offset)) = temp; 632 pd_offset += 4; 633 } 634 break; 635 636 case LIBUSB20_ME_INT64: 637 pd_offset = -((-pd_offset) & ~7); /* align */ 638 while (pd_count--) { 639 uint64_t temp; 640 641 if (len < 8) { 642 len = 0; 643 temp = 0; 644 } else { 645 len -= 8; 646 temp = ((uint64_t)buf[7]) << 56; 647 temp |= ((uint64_t)buf[6]) << 48; 648 temp |= ((uint64_t)buf[5]) << 40; 649 temp |= ((uint64_t)buf[4]) << 32; 650 temp |= buf[3] << 24; 651 temp |= buf[2] << 16; 652 temp |= buf[1] << 8; 653 temp |= buf[0]; 654 buf += 8; 655 } 656 657 *((uint64_t *)LIBUSB20_ADD_BYTES(pd, 658 pd_offset)) = temp; 659 pd_offset += 8; 660 } 661 break; 662 663 case LIBUSB20_ME_STRUCT: 664 pd_offset = -((-pd_offset) & 665 ~(LIBUSB20_ME_STRUCT_ALIGN - 1)); /* align */ 666 while (pd_count--) { 667 uint16_t temp; 668 uint16_t dummy; 669 struct libusb20_me_struct *ps; 670 671 ps = LIBUSB20_ADD_BYTES(pd, pd_offset); 672 673 if (ps->type == LIBUSB20_ME_IS_ENCODED) { 674 /* 675 * Pre-store a de-constified 676 * pointer to the raw 677 * structure: 678 */ 679 ps->ptr = LIBUSB20_ADD_BYTES(buf, 0); 680 681 /* 682 * Get the correct number of 683 * length bytes: 684 */ 685 if (len != 0) { 686 if (buf[0] == 0xFF) { 687 ps->len = 3; 688 } else { 689 ps->len = 1; 690 } 691 } else { 692 ps->len = 0; 693 } 694 } 695 /* get the structure length */ 696 697 if (len != 0) { 698 if (buf[0] == 0xFF) { 699 if (len < 3) { 700 len = 0; 701 temp = 0; 702 } else { 703 len -= 3; 704 temp = buf[1] | 705 (buf[2] << 8); 706 buf += 3; 707 } 708 } else { 709 len -= 1; 710 temp = buf[0]; 711 buf += 1; 712 } 713 } else { 714 len = 0; 715 temp = 0; 716 } 717 /* check for invalid length */ 718 719 if (temp > len) { 720 len = 0; 721 temp = 0; 722 } 723 /* check wanted structure type */ 724 725 switch (ps->type) { 726 case LIBUSB20_ME_IS_ENCODED: 727 /* check for zero length */ 728 if (temp == 0) { 729 /* 730 * The pointer must 731 * be valid: 732 */ 733 ps->ptr = LIBUSB20_ADD_BYTES( 734 libusb20_me_encode_empty, 0); 735 ps->len = 1; 736 } else { 737 ps->len += temp; 738 } 739 break; 740 741 case LIBUSB20_ME_IS_RAW: 742 /* update length and pointer */ 743 ps->len = temp; 744 ps->ptr = LIBUSB20_ADD_BYTES(buf, 0); 745 break; 746 747 case LIBUSB20_ME_IS_EMPTY: 748 case LIBUSB20_ME_IS_DECODED: 749 /* check for non-zero length */ 750 if (temp != 0) { 751 /* update type */ 752 ps->type = LIBUSB20_ME_IS_DECODED; 753 ps->len = 0; 754 /* 755 * Recursivly decode 756 * the next structure 757 */ 758 dummy = libusb20_me_decode(buf, 759 temp, ps->ptr); 760 } else { 761 /* update type */ 762 ps->type = LIBUSB20_ME_IS_EMPTY; 763 ps->len = 0; 764 } 765 break; 766 767 default: 768 /* 769 * nothing to do - should 770 * not happen 771 */ 772 ps->ptr = NULL; 773 ps->len = 0; 774 break; 775 } 776 buf += temp; 777 len -= temp; 778 pd_offset += sizeof(struct libusb20_me_struct); 779 } 780 break; 781 782 default: 783 goto done; 784 } 785 } 786 done: 787 return (len_old - len); 788 } 789