source: mainline/uspace/lib/usb/src/dp.c@ 3b77628

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 3b77628 was 3b77628, checked in by Vojtech Horky <vojtechhorky@…>, 14 years ago

Doxygen comment fixes

Mainly proper subgrouping and some missing @param comments.

  • Property mode set to 100644
File size: 6.4 KB
Line 
1/*
2 * Copyright (c) 2011 Vojtech Horky
3 * 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 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup libusb
30 * @{
31 */
32/**
33 * @file
34 * @brief USB descriptor parser (implementation).
35 */
36#include <stdio.h>
37#include <str_error.h>
38#include <errno.h>
39#include <usb/usbdrv.h>
40#include <bool.h>
41#include <usb/dp.h>
42
43/** Tells whether pointer points inside descriptor data.
44 *
45 * @param data Parser data.
46 * @param ptr Pointer to be verified.
47 * @return Whether @p ptr points inside <code>data->data</code> field.
48 */
49static bool is_valid_descriptor_pointer(usb_dp_parser_data_t *data,
50 uint8_t *ptr)
51{
52 if (ptr == NULL) {
53 return false;
54 }
55
56 if (ptr < data->data) {
57 return false;
58 }
59
60 if ((size_t)(ptr - data->data) >= data->size) {
61 return false;
62 }
63
64 return true;
65}
66
67/** Get next descriptor regardless of the nesting.
68 *
69 * @param data Parser data.
70 * @param current Pointer to current descriptor.
71 * @return Pointer to start of next descriptor.
72 * @retval NULL Invalid input or no next descriptor.
73 */
74static uint8_t *get_next_descriptor(usb_dp_parser_data_t *data,
75 uint8_t *current)
76{
77 assert(is_valid_descriptor_pointer(data, current));
78
79 uint8_t current_length = *current;
80 uint8_t *next = current + current_length;
81
82 if (!is_valid_descriptor_pointer(data, next)) {
83 return NULL;
84 }
85
86 return next;
87}
88
89/** Get descriptor type.
90 *
91 * @see usb_descriptor_type_t
92 *
93 * @param data Parser data.
94 * @param start Pointer to start of the descriptor.
95 * @return Descriptor type.
96 * @retval -1 Invalid input.
97 */
98static int get_descriptor_type(usb_dp_parser_data_t *data, uint8_t *start)
99{
100 if (start == NULL) {
101 return -1;
102 }
103
104 start++;
105 if (!is_valid_descriptor_pointer(data, start)) {
106 return -1;
107 } else {
108 return (int) (*start);
109 }
110}
111
112/** Tells whether descriptors could be nested.
113 *
114 * @param parser Parser.
115 * @param child Child descriptor type.
116 * @param parent Parent descriptor type.
117 * @return Whether @p child could be child of @p parent.
118 */
119static bool is_nested_descriptor_type(usb_dp_parser_t *parser,
120 int child, int parent)
121{
122 usb_dp_descriptor_nesting_t *nesting = parser->nesting;
123 while ((nesting->child > 0) && (nesting->parent > 0)) {
124 if ((nesting->child == child) && (nesting->parent == parent)) {
125 return true;
126 }
127 nesting++;
128 }
129 return false;
130}
131
132/** Tells whether descriptors could be nested.
133 *
134 * @param parser Parser.
135 * @param data Parser data.
136 * @param child Pointer to child descriptor.
137 * @param parent Pointer to parent descriptor.
138 * @return Whether @p child could be child of @p parent.
139 */
140static bool is_nested_descriptor(usb_dp_parser_t *parser,
141 usb_dp_parser_data_t *data, uint8_t *child, uint8_t *parent)
142{
143 return is_nested_descriptor_type(parser,
144 get_descriptor_type(data, child),
145 get_descriptor_type(data, parent));
146}
147
148/** Find first nested descriptor of given parent.
149 *
150 * @param parser Parser.
151 * @param data Parser data.
152 * @param parent Pointer to the beginning of parent descriptor.
153 * @return Pointer to the beginning of the first nested (child) descriptor.
154 * @retval NULL No child descriptor found.
155 * @retval NULL Invalid input.
156 */
157uint8_t *usb_dp_get_nested_descriptor(usb_dp_parser_t *parser,
158 usb_dp_parser_data_t *data, uint8_t *parent)
159{
160 if (!is_valid_descriptor_pointer(data, parent)) {
161 return NULL;
162 }
163
164 uint8_t *next = get_next_descriptor(data, parent);
165 if (next == NULL) {
166 return NULL;
167 }
168
169 if (is_nested_descriptor(parser, data, next, parent)) {
170 return next;
171 } else {
172 return NULL;
173 }
174}
175
176/** Skip all nested descriptors.
177 *
178 * @param parser Parser.
179 * @param data Parser data.
180 * @param parent Pointer to the beginning of parent descriptor.
181 * @return Pointer to first non-child descriptor.
182 * @retval NULL No next descriptor.
183 * @retval NULL Invalid input.
184 */
185static uint8_t *skip_nested_descriptors(usb_dp_parser_t *parser,
186 usb_dp_parser_data_t *data, uint8_t *parent)
187{
188 uint8_t *child = usb_dp_get_nested_descriptor(parser, data, parent);
189 if (child == NULL) {
190 return get_next_descriptor(data, parent);
191 }
192 uint8_t *next_child = skip_nested_descriptors(parser, data, child);
193 while (is_nested_descriptor(parser, data, next_child, parent)) {
194 next_child = skip_nested_descriptors(parser, data, next_child);
195 }
196
197 return next_child;
198}
199
200/** Get sibling descriptor.
201 *
202 * @param parser Parser.
203 * @param data Parser data.
204 * @param parent Pointer to common parent descriptor.
205 * @param sibling Left sibling.
206 * @return Pointer to first right sibling of @p sibling.
207 * @retval NULL No sibling exist.
208 * @retval NULL Invalid input.
209 */
210uint8_t *usb_dp_get_sibling_descriptor(usb_dp_parser_t *parser,
211 usb_dp_parser_data_t *data, uint8_t *parent, uint8_t *sibling)
212{
213 if (!is_valid_descriptor_pointer(data, parent)
214 || !is_valid_descriptor_pointer(data, sibling)) {
215 return NULL;
216 }
217
218 uint8_t *possible_sibling = skip_nested_descriptors(parser, data, sibling);
219 if (possible_sibling == NULL) {
220 return NULL;
221 }
222
223 int parent_type = get_descriptor_type(data, parent);
224 int possible_sibling_type = get_descriptor_type(data, possible_sibling);
225 if (is_nested_descriptor_type(parser, possible_sibling_type, parent_type)) {
226 return possible_sibling;
227 } else {
228 return NULL;
229 }
230}
231
232
233/** @}
234 */
Note: See TracBrowser for help on using the repository browser.