Deleted Added
sdiff udiff text old ( 185087 ) new ( 186730 )
full compact
1/* $FreeBSD: head/lib/libusb20/libusb20_desc.c 185087 2008-11-19 08:56:35Z alfred $ */
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 <stdio.h>
28#include <stdlib.h>
29#include <string.h>
30#include <poll.h>
31#include <sys/queue.h>
32
33#include "libusb20.h"
34#include "libusb20_desc.h"
35#include "libusb20_int.h"
36
37static const uint32_t libusb20_me_encode_empty[2]; /* dummy */
38
39LIBUSB20_MAKE_STRUCT_FORMAT(LIBUSB20_DEVICE_DESC);
40LIBUSB20_MAKE_STRUCT_FORMAT(LIBUSB20_ENDPOINT_DESC);
41LIBUSB20_MAKE_STRUCT_FORMAT(LIBUSB20_INTERFACE_DESC);
42LIBUSB20_MAKE_STRUCT_FORMAT(LIBUSB20_CONFIG_DESC);
43LIBUSB20_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 *------------------------------------------------------------------------*/
52struct libusb20_config *
53libusb20_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 lub_interface = (void *)(lub_config + 1);
122 lub_alt_interface = (void *)(lub_interface + niface_no_alt);
123 lub_endpoint = (void *)(lub_interface + niface);
124
125 /*
126 * Make a copy of the config descriptor, so that the caller can free
127 * the inital config descriptor pointer!
128 */
129 ptr = (void *)(lub_endpoint + nendpoint);
130 memcpy(LIBUSB20_ADD_BYTES(ptr, 0), config_desc, pcdesc.len);
131 pcdesc.ptr = LIBUSB20_ADD_BYTES(ptr, 0);
132 config_desc = LIBUSB20_ADD_BYTES(ptr, 0);
133
134 /* init config structure */
135
136 ptr = config_desc;
137
138 LIBUSB20_INIT(LIBUSB20_CONFIG_DESC, &lub_config->desc);
139
140 if (libusb20_me_decode(ptr, ptr[0], &lub_config->desc)) {
141 /* ignore */
142 }
143 lub_config->num_interface = 0;
144 lub_config->interface = lub_interface;
145 lub_config->extra.ptr = LIBUSB20_ADD_BYTES(ptr, ptr[0]);
146 lub_config->extra.len = -ptr[0];
147 lub_config->extra.type = LIBUSB20_ME_IS_RAW;
148
149 /* reset states */
150 niface = 0;
151 iface_no = 0 - 1;
152 ptr = NULL;
153 lub_interface--;
154 lub_endpoint--;
155 last_if = NULL;
156 last_ep = NULL;
157
158 /* descriptor pre-scan */
159 while ((ptr = libusb20_desc_foreach(&pcdesc, ptr))) {
160 if (ptr[1] == LIBUSB20_DT_ENDPOINT) {
161 if (last_if) {
162 lub_endpoint++;
163 last_ep = lub_endpoint;
164 last_if->num_endpoints++;
165
166 LIBUSB20_INIT(LIBUSB20_ENDPOINT_DESC, &last_ep->desc);
167
168 if (libusb20_me_decode(ptr, ptr[0], &last_ep->desc)) {
169 /* ignore */
170 }
171 last_ep->extra.ptr = LIBUSB20_ADD_BYTES(ptr, ptr[0]);
172 last_ep->extra.len = 0;
173 last_ep->extra.type = LIBUSB20_ME_IS_RAW;
174 } else {
175 lub_config->extra.len += ptr[0];
176 }
177
178 } else if ((ptr[1] == LIBUSB20_DT_INTERFACE) && (ptr[0] >= 4)) {
179 if (ptr[2] != iface_no) {
180 /* new interface */
181 iface_no = ptr[2];
182 lub_interface++;
183 lub_config->num_interface++;
184 last_if = lub_interface;
185 niface++;
186 } else {
187 /* one more alternate setting */
188 lub_interface->num_altsetting++;
189 last_if = lub_alt_interface;
190 lub_alt_interface++;
191 }
192
193 LIBUSB20_INIT(LIBUSB20_INTERFACE_DESC, &last_if->desc);
194
195 if (libusb20_me_decode(ptr, ptr[0], &last_if->desc)) {
196 /* ignore */
197 }
198 /*
199 * Sometimes USB devices have corrupt interface
200 * descriptors and we need to overwrite the provided
201 * interface number!
202 */
203 last_if->desc.bInterfaceNumber = niface - 1;
204 last_if->extra.ptr = LIBUSB20_ADD_BYTES(ptr, ptr[0]);
205 last_if->extra.len = 0;
206 last_if->extra.type = LIBUSB20_ME_IS_RAW;
207 last_if->endpoints = lub_endpoint + 1;
208 last_if->altsetting = lub_alt_interface;
209 last_if->num_altsetting = 0;
210 last_if->num_endpoints = 0;
211 last_ep = NULL;
212 } else {
213 /* unknown descriptor */
214 if (last_if) {
215 if (last_ep) {
216 last_ep->extra.len += ptr[0];
217 } else {
218 last_if->extra.len += ptr[0];
219 }
220 } else {
221 lub_config->extra.len += ptr[0];
222 }
223 }
224 }
225 return (lub_config);
226}
227
228/*------------------------------------------------------------------------*
229 * libusb20_desc_foreach
230 *
231 * Safe traversal of USB descriptors.
232 *
233 * Return values:
234 * NULL: End of descriptors
235 * Else: Pointer to next descriptor
236 *------------------------------------------------------------------------*/
237const uint8_t *
238libusb20_desc_foreach(const struct libusb20_me_struct *pdesc,
239 const uint8_t *psubdesc)
240{
241 const void *end;
242
243 if (pdesc == NULL) {
244 return (NULL);
245 }
246 end = LIBUSB20_ADD_BYTES(pdesc->ptr, pdesc->len);
247
248 if (psubdesc == NULL) {
249 psubdesc = LIBUSB20_ADD_BYTES(pdesc->ptr, 0);
250 } else {
251 psubdesc = LIBUSB20_ADD_BYTES(psubdesc, psubdesc[0]);
252 }
253 return (((((const void *)psubdesc) >= ((void *)(pdesc->ptr))) &&
254 (((const void *)psubdesc) < end) &&
255 (LIBUSB20_ADD_BYTES(psubdesc, psubdesc[0]) >= ((void *)(pdesc->ptr))) &&
256 (LIBUSB20_ADD_BYTES(psubdesc, psubdesc[0]) <= end) &&
257 (psubdesc[0] >= 3)) ? psubdesc : NULL);
258}
259
260/*------------------------------------------------------------------------*
261 * libusb20_me_get_1 - safety wrapper to read out one byte
262 *------------------------------------------------------------------------*/
263uint8_t
264libusb20_me_get_1(const struct libusb20_me_struct *ie, uint16_t offset)
265{
266 if (offset < ie->len) {
267 return (*((uint8_t *)LIBUSB20_ADD_BYTES(ie->ptr, offset)));
268 }
269 return (0);
270}
271
272/*------------------------------------------------------------------------*
273 * libusb20_me_get_2 - safety wrapper to read out one word
274 *------------------------------------------------------------------------*/
275uint16_t
276libusb20_me_get_2(const struct libusb20_me_struct *ie, uint16_t offset)
277{
278 return (libusb20_me_get_1(ie, offset) |
279 (libusb20_me_get_1(ie, offset + 1) << 8));
280}
281
282/*------------------------------------------------------------------------*
283 * libusb20_me_encode - encode a message structure
284 *
285 * Description of parameters:
286 * "len" - maximum length of output buffer
287 * "ptr" - pointer to output buffer. If NULL, no data will be written
288 * "pd" - source structure
289 *
290 * Return values:
291 * 0..65535 - Number of bytes used, limited by the "len" input parameter.
292 *------------------------------------------------------------------------*/
293uint16_t
294libusb20_me_encode(void *ptr, uint16_t len, const void *pd)
295{
296 const uint8_t *pf; /* pointer to format data */
297 uint8_t *buf; /* pointer to output buffer */
298
299 uint32_t pd_offset; /* decoded structure offset */
300 uint16_t len_old; /* old length */
301 uint16_t pd_count; /* decoded element count */
302 uint8_t me; /* message element */
303
304 /* initialise */
305
306 len_old = len;
307 buf = ptr;
308 pd_offset = sizeof(void *);
309 pf = (*((struct libusb20_me_format *const *)pd))->format;
310
311 /* scan */
312
313 while (1) {
314
315 /* get information element */
316
317 me = (pf[0]) & LIBUSB20_ME_MASK;
318 pd_count = pf[1] | (pf[2] << 8);
319 pf += 3;
320
321 /* encode the message element */
322
323 switch (me) {
324 case LIBUSB20_ME_INT8:
325 while (pd_count--) {
326 uint8_t temp;
327
328 if (len < 1) /* overflow */
329 goto done;
330 if (buf) {
331 temp = *((const uint8_t *)
332 LIBUSB20_ADD_BYTES(pd, pd_offset));
333 buf[0] = temp;
334 buf += 1;
335 }
336 pd_offset += 1;
337 len -= 1;
338 }
339 break;
340
341 case LIBUSB20_ME_INT16:
342 pd_offset = -((-pd_offset) & ~1); /* align */
343 while (pd_count--) {
344 uint16_t temp;
345
346 if (len < 2) /* overflow */
347 goto done;
348
349 if (buf) {
350 temp = *((const uint16_t *)
351 LIBUSB20_ADD_BYTES(pd, pd_offset));
352 buf[1] = (temp >> 8) & 0xFF;
353 buf[0] = temp & 0xFF;
354 buf += 2;
355 }
356 pd_offset += 2;
357 len -= 2;
358 }
359 break;
360
361 case LIBUSB20_ME_INT32:
362 pd_offset = -((-pd_offset) & ~3); /* align */
363 while (pd_count--) {
364 uint32_t temp;
365
366 if (len < 4) /* overflow */
367 goto done;
368 if (buf) {
369 temp = *((const uint32_t *)
370 LIBUSB20_ADD_BYTES(pd, pd_offset));
371 buf[3] = (temp >> 24) & 0xFF;
372 buf[2] = (temp >> 16) & 0xFF;
373 buf[1] = (temp >> 8) & 0xFF;
374 buf[0] = temp & 0xFF;
375 buf += 4;
376 }
377 pd_offset += 4;
378 len -= 4;
379 }
380 break;
381
382 case LIBUSB20_ME_INT64:
383 pd_offset = -((-pd_offset) & ~7); /* align */
384 while (pd_count--) {
385 uint64_t temp;
386
387 if (len < 8) /* overflow */
388 goto done;
389 if (buf) {
390
391 temp = *((const uint64_t *)
392 LIBUSB20_ADD_BYTES(pd, pd_offset));
393 buf[7] = (temp >> 56) & 0xFF;
394 buf[6] = (temp >> 48) & 0xFF;
395 buf[5] = (temp >> 40) & 0xFF;
396 buf[4] = (temp >> 32) & 0xFF;
397 buf[3] = (temp >> 24) & 0xFF;
398 buf[2] = (temp >> 16) & 0xFF;
399 buf[1] = (temp >> 8) & 0xFF;
400 buf[0] = temp & 0xFF;
401 buf += 8;
402 }
403 pd_offset += 8;
404 len -= 8;
405 }
406 break;
407
408 case LIBUSB20_ME_STRUCT:
409 pd_offset = -((-pd_offset) &
410 ~(LIBUSB20_ME_STRUCT_ALIGN - 1)); /* align */
411 while (pd_count--) {
412 void *src_ptr;
413 uint16_t src_len;
414 struct libusb20_me_struct *ps;
415
416 ps = LIBUSB20_ADD_BYTES(pd, pd_offset);
417
418 switch (ps->type) {
419 case LIBUSB20_ME_IS_RAW:
420 src_len = ps->len;
421 src_ptr = ps->ptr;
422 break;
423
424 case LIBUSB20_ME_IS_ENCODED:
425 if (ps->len == 0) {
426 /*
427 * Length is encoded
428 * in the data itself
429 * and should be
430 * correct:
431 */
432 ps->len = 0 - 1;
433 }
434 src_len = libusb20_me_get_1(pd, 0);
435 src_ptr = LIBUSB20_ADD_BYTES(ps->ptr, 1);
436 if (src_len == 0xFF) {
437 /* length is escaped */
438 src_len = libusb20_me_get_2(pd, 1);
439 src_ptr =
440 LIBUSB20_ADD_BYTES(ps->ptr, 3);
441 }
442 break;
443
444 case LIBUSB20_ME_IS_DECODED:
445 /* reserve 3 length bytes */
446 src_len = libusb20_me_encode(NULL,
447 0 - 1 - 3, ps->ptr);
448 src_ptr = NULL;
449 break;
450
451 default: /* empty structure */
452 src_len = 0;
453 src_ptr = NULL;
454 break;
455 }
456
457 if (src_len > 0xFE) {
458 if (src_len > (uint16_t)(0 - 1 - 3))
459 /* overflow */
460 goto done;
461
462 if (len < (src_len + 3))
463 /* overflow */
464 goto done;
465
466 if (buf) {
467 buf[0] = 0xFF;
468 buf[1] = (src_len & 0xFF);
469 buf[2] = (src_len >> 8) & 0xFF;
470 buf += 3;
471 }
472 len -= (src_len + 3);
473 } else {
474 if (len < (src_len + 1))
475 /* overflow */
476 goto done;
477
478 if (buf) {
479 buf[0] = (src_len & 0xFF);
480 buf += 1;
481 }
482 len -= (src_len + 1);
483 }
484
485 /* check for buffer and non-zero length */
486
487 if (buf && src_len) {
488 if (ps->type == LIBUSB20_ME_IS_DECODED) {
489 /*
490 * Repeat encode
491 * procedure - we have
492 * room for the
493 * complete structure:
494 */
495 uint16_t dummy;
496
497 dummy = libusb20_me_encode(buf,
498 0 - 1 - 3, ps->ptr);
499 } else {
500 bcopy(src_ptr, buf, src_len);
501 }
502 buf += src_len;
503 }
504 pd_offset += sizeof(struct libusb20_me_struct);
505 }
506 break;
507
508 default:
509 goto done;
510 }
511 }
512done:
513 return (len_old - len);
514}
515
516/*------------------------------------------------------------------------*
517 * libusb20_me_decode - decode a message into a decoded structure
518 *
519 * Description of parameters:
520 * "ptr" - message pointer
521 * "len" - message length
522 * "pd" - pointer to decoded structure
523 *
524 * Returns:
525 * "0..65535" - number of bytes decoded, limited by "len"
526 *------------------------------------------------------------------------*/
527uint16_t
528libusb20_me_decode(const void *ptr, uint16_t len, void *pd)
529{
530 const uint8_t *pf; /* pointer to format data */
531 const uint8_t *buf; /* pointer to input buffer */
532
533 uint32_t pd_offset; /* decoded structure offset */
534 uint16_t len_old; /* old length */
535 uint16_t pd_count; /* decoded element count */
536 uint8_t me; /* message element */
537
538 /* initialise */
539
540 len_old = len;
541 buf = ptr;
542 pd_offset = sizeof(void *);
543 pf = (*((struct libusb20_me_format **)pd))->format;
544
545 /* scan */
546
547 while (1) {
548
549 /* get information element */
550
551 me = (pf[0]) & LIBUSB20_ME_MASK;
552 pd_count = pf[1] | (pf[2] << 8);
553 pf += 3;
554
555 /* decode the message element by type */
556
557 switch (me) {
558 case LIBUSB20_ME_INT8:
559 while (pd_count--) {
560 uint8_t temp;
561
562 if (len < 1) {
563 len = 0;
564 temp = 0;
565 } else {
566 len -= 1;
567 temp = buf[0];
568 buf++;
569 }
570 *((uint8_t *)LIBUSB20_ADD_BYTES(pd,
571 pd_offset)) = temp;
572 pd_offset += 1;
573 }
574 break;
575
576 case LIBUSB20_ME_INT16:
577 pd_offset = -((-pd_offset) & ~1); /* align */
578 while (pd_count--) {
579 uint16_t temp;
580
581 if (len < 2) {
582 len = 0;
583 temp = 0;
584 } else {
585 len -= 2;
586 temp = buf[1] << 8;
587 temp |= buf[0];
588 buf += 2;
589 }
590 *((uint16_t *)LIBUSB20_ADD_BYTES(pd,
591 pd_offset)) = temp;
592 pd_offset += 2;
593 }
594 break;
595
596 case LIBUSB20_ME_INT32:
597 pd_offset = -((-pd_offset) & ~3); /* align */
598 while (pd_count--) {
599 uint32_t temp;
600
601 if (len < 4) {
602 len = 0;
603 temp = 0;
604 } else {
605 len -= 4;
606 temp = buf[3] << 24;
607 temp |= buf[2] << 16;
608 temp |= buf[1] << 8;
609 temp |= buf[0];
610 buf += 4;
611 }
612
613 *((uint32_t *)LIBUSB20_ADD_BYTES(pd,
614 pd_offset)) = temp;
615 pd_offset += 4;
616 }
617 break;
618
619 case LIBUSB20_ME_INT64:
620 pd_offset = -((-pd_offset) & ~7); /* align */
621 while (pd_count--) {
622 uint64_t temp;
623
624 if (len < 8) {
625 len = 0;
626 temp = 0;
627 } else {
628 len -= 8;
629 temp = ((uint64_t)buf[7]) << 56;
630 temp |= ((uint64_t)buf[6]) << 48;
631 temp |= ((uint64_t)buf[5]) << 40;
632 temp |= ((uint64_t)buf[4]) << 32;
633 temp |= buf[3] << 24;
634 temp |= buf[2] << 16;
635 temp |= buf[1] << 8;
636 temp |= buf[0];
637 buf += 8;
638 }
639
640 *((uint64_t *)LIBUSB20_ADD_BYTES(pd,
641 pd_offset)) = temp;
642 pd_offset += 8;
643 }
644 break;
645
646 case LIBUSB20_ME_STRUCT:
647 pd_offset = -((-pd_offset) &
648 ~(LIBUSB20_ME_STRUCT_ALIGN - 1)); /* align */
649 while (pd_count--) {
650 uint16_t temp;
651 uint16_t dummy;
652 struct libusb20_me_struct *ps;
653
654 ps = LIBUSB20_ADD_BYTES(pd, pd_offset);
655
656 if (ps->type == LIBUSB20_ME_IS_ENCODED) {
657 /*
658 * Pre-store a de-constified
659 * pointer to the raw
660 * structure:
661 */
662 ps->ptr = LIBUSB20_ADD_BYTES(buf, 0);
663
664 /*
665 * Get the correct number of
666 * length bytes:
667 */
668 if (len != 0) {
669 if (buf[0] == 0xFF) {
670 ps->len = 3;
671 } else {
672 ps->len = 1;
673 }
674 } else {
675 ps->len = 0;
676 }
677 }
678 /* get the structure length */
679
680 if (len != 0) {
681 if (buf[0] == 0xFF) {
682 if (len < 3) {
683 len = 0;
684 temp = 0;
685 } else {
686 len -= 3;
687 temp = buf[1] |
688 (buf[2] << 8);
689 buf += 3;
690 }
691 } else {
692 len -= 1;
693 temp = buf[0];
694 buf += 1;
695 }
696 } else {
697 len = 0;
698 temp = 0;
699 }
700 /* check for invalid length */
701
702 if (temp > len) {
703 len = 0;
704 temp = 0;
705 }
706 /* check wanted structure type */
707
708 switch (ps->type) {
709 case LIBUSB20_ME_IS_ENCODED:
710 /* check for zero length */
711 if (temp == 0) {
712 /*
713 * The pointer must
714 * be valid:
715 */
716 ps->ptr = LIBUSB20_ADD_BYTES(
717 libusb20_me_encode_empty, 0);
718 ps->len = 1;
719 } else {
720 ps->len += temp;
721 }
722 break;
723
724 case LIBUSB20_ME_IS_RAW:
725 /* update length and pointer */
726 ps->len = temp;
727 ps->ptr = LIBUSB20_ADD_BYTES(buf, 0);
728 break;
729
730 case LIBUSB20_ME_IS_EMPTY:
731 case LIBUSB20_ME_IS_DECODED:
732 /* check for non-zero length */
733 if (temp != 0) {
734 /* update type */
735 ps->type = LIBUSB20_ME_IS_DECODED;
736 ps->len = 0;
737 /*
738 * Recursivly decode
739 * the next structure
740 */
741 dummy = libusb20_me_decode(buf,
742 temp, ps->ptr);
743 } else {
744 /* update type */
745 ps->type = LIBUSB20_ME_IS_EMPTY;
746 ps->len = 0;
747 }
748 break;
749
750 default:
751 /*
752 * nothing to do - should
753 * not happen
754 */
755 ps->ptr = NULL;
756 ps->len = 0;
757 break;
758 }
759 buf += temp;
760 len -= temp;
761 pd_offset += sizeof(struct libusb20_me_struct);
762 }
763 break;
764
765 default:
766 goto done;
767 }
768 }
769done:
770 return (len_old - len);
771}