d5fcbb0bb0ae2e203b1bd82b3082c7b8d536dc50
[pub/USBasp.git] / LUFA / Drivers / USB / Class / ConfigDescriptor.h
1 /*
2 LUFA Library
3 Copyright (C) Dean Camera, 2009.
4
5 dean [at] fourwalledcubicle [dot] com
6 www.fourwalledcubicle.com
7 */
8
9 /*
10 Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)
11
12 Permission to use, copy, modify, and distribute this software
13 and its documentation for any purpose and without fee is hereby
14 granted, provided that the above copyright notice appear in all
15 copies and that both that the copyright notice and this
16 permission notice and warranty disclaimer appear in supporting
17 documentation, and that the name of the author not be used in
18 advertising or publicity pertaining to distribution of the
19 software without specific, written prior permission.
20
21 The author disclaim all warranties with regard to this
22 software, including all implied warranties of merchantability
23 and fitness. In no event shall the author be liable for any
24 special, indirect or consequential damages or any damages
25 whatsoever resulting from loss of use, data or profits, whether
26 in an action of contract, negligence or other tortious action,
27 arising out of or in connection with the use or performance of
28 this software.
29 */
30
31 /** \file
32 *
33 * Configuration descriptor parser API. This section of the library gives a friendly API which can be used in
34 * host applications to easily parse an attached device's configuration descriptor so that endpoint, interface
35 * and other descriptor data can be extracted and used as needed.
36 */
37
38 /** \ingroup Group_Descriptors
39 * @defgroup Group_ConfigDescriptorParser Configuration Descriptor Parser
40 *
41 * Functions, macros, variables, enums and types related to the parsing of Configuration Descriptors.
42 *
43 * @{
44 */
45
46 #ifndef __CONFIGDESCRIPTOR_H__
47 #define __CONFIGDESCRIPTOR_H__
48
49 /* Includes: */
50 #include <avr/io.h>
51
52 #include "../../../Common/Common.h"
53 #include "../LowLevel/HostChapter9.h"
54 #include "../HighLevel/StdDescriptors.h"
55
56 /* Enable C linkage for C++ Compilers: */
57 #if defined(__cplusplus)
58 extern "C" {
59 #endif
60
61 /* Public Interface - May be used in end-application: */
62 /* Macros: */
63 /** Mask for determining the type of an endpoint from an endpoint descriptor. This should then be compared
64 * with the EP_TYPE_* masks to determine the exact type of the endpoint.
65 */
66 #define EP_TYPE_MASK 0x03
67
68 /** Casts a pointer to a descriptor inside the configuration descriptor into a pointer to the given
69 * descriptor type.
70 *
71 * Usage Example:
72 * \code
73 * uint8_t* CurrDescriptor = &ConfigDescriptor[0]; // Pointing to the configuration header
74 * USB_Descriptor_Configuration_Header_t* ConfigHeaderPtr = DESCRIPTOR_PCAST(CurrDescriptor,
75 * USB_Descriptor_Configuration_Header_t);
76 *
77 * // Can now access elements of the configuration header struct using the -> indirection operator
78 * \endcode
79 */
80 #define DESCRIPTOR_PCAST(DescriptorPtr, Type) ((Type*)DescriptorPtr)
81
82 /** Casts a pointer to a descriptor inside the configuration descriptor into the given descriptor
83 * type (as an actual struct instance rather than a pointer to a struct).
84 *
85 * Usage Example:
86 * \code
87 * uint8_t* CurrDescriptor = &ConfigDescriptor[0]; // Pointing to the configuration header
88 * USB_Descriptor_Configuration_Header_t ConfigHeader = DESCRIPTOR_CAST(CurrDescriptor,
89 * USB_Descriptor_Configuration_Header_t);
90 *
91 * // Can now access elements of the configuration header struct using the . operator
92 * \endcode
93 */
94 #define DESCRIPTOR_CAST(DescriptorPtr, Type) (*DESCRIPTOR_PCAST(DescriptorPtr, Type))
95
96 /** Returns the descriptor's type, expressed as the 8-bit type value in the header of the descriptor.
97 * This value's meaning depends on the descriptor's placement in the descriptor, but standard type
98 * values can be accessed in the DescriptorTypes_t enum located in USB/HighLevel/StdDescriptors.h.
99 */
100 #if defined(USE_NONSTANDARD_DESCRIPTOR_NAMES) || defined(__DOXYGEN__)
101 #define DESCRIPTOR_TYPE(DescriptorPtr) DESCRIPTOR_CAST(DescriptorPtr, USB_Descriptor_Header_t).Type
102 #else
103 #define DESCRIPTOR_TYPE(DescriptorPtr) DESCRIPTOR_CAST(DescriptorPtr, USB_Descriptor_Header_t).bDescriptorType
104 #endif
105
106 /** Returns the descriptor's size, expressed as the 8-bit value indicating the number of bytes. */
107 #if defined(USE_NONSTANDARD_DESCRIPTOR_NAMES) || defined(__DOXYGEN__)
108 #define DESCRIPTOR_SIZE(DescriptorPtr) DESCRIPTOR_CAST(DescriptorPtr, USB_Descriptor_Header_t).Size
109 #else
110 #define DESCRIPTOR_SIZE(DescriptorPtr) DESCRIPTOR_CAST(DescriptorPtr, USB_Descriptor_Header_t).bLength
111 #endif
112
113 /** Creates a prototype for or begins a descriptor comparator routine. Descriptor comparator routines are
114 * small search routines which are passed a pointer to the current sub descriptor in the configuration
115 * descriptor, and which analyse the sub descriptor to determine whether or not it matches the routine's
116 * search parameters. Comparator routines provide a powerful way to scan through the config descriptor
117 * for certain descriptors matching unique criteria.
118 *
119 * Comparator routines are passed in a single pointer named CurrentDescriptor, and should return a value
120 * of a member of the DSearch_Return_ErrorCodes_t enum.
121 */
122 #define DESCRIPTOR_COMPARATOR(name) uint8_t DCOMP_##name (void* const CurrentDescriptor)
123
124 /** Searches for the next descriptor in the given configuration descriptor using a premade comparator
125 * function. The routine updates the position and remaining configuration descriptor bytes values
126 * automatically. If a comparator routine fails a search, the descriptor pointer is retreated back
127 * so that the next descriptor search invocation will start from the descriptor which first caused the
128 * original search to fail. This behaviour allows for one comparator to be used immediately after another
129 * has failed, starting the second search from the descriptor which failed the first.
130 *
131 * \param DSize Pointer to an int storing the remaining bytes in the configuration descriptor
132 * \param DPos Pointer to the current position in the configuration descriptor
133 * \param DSearch Name of the comparator search function to use on the configuration descriptor
134 *
135 * \return Value of one of the members of the DSearch_Comp_Return_ErrorCodes_t enum
136 *
137 * Usage Example:
138 * \code
139 * DESCRIPTOR_COMPARATOR(EndpointSearcher); // Comparator Prototype
140 *
141 * DESCRIPTOR_COMPARATOR(EndpointSearcher)
142 * {
143 * if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Endpoint)
144 * return Descriptor_Search_Found;
145 * else
146 * return Descriptor_Search_NotFound;
147 * }
148 *
149 * //...
150 * // After retrieving configuration descriptor:
151 * if (USB_Host_GetNextDescriptorComp(&BytesRemaining, &ConfigDescriptorData, EndpointSearcher) ==
152 * Descriptor_Search_Comp_Found)
153 * {
154 * // Do something with the endpoint descriptor
155 * }
156 * \endcode
157 */
158 #define USB_Host_GetNextDescriptorComp(DSize, DPos, DSearch) \
159 USB_Host_GetNextDescriptorComp_P(DSize, DPos, DCOMP_##DSearch)
160 /* Enums: */
161 /** Enum for return values of a descriptor comparator made with DESCRIPTOR_COMPARATOR. */
162 enum DSearch_Return_ErrorCodes_t
163 {
164 Descriptor_Search_Found = 0, /**< Current descriptor matches comparator criteria. */
165 Descriptor_Search_Fail = 1, /**< No further descriptor could possibly match criteria, fail the search. */
166 Descriptor_Search_NotFound = 2, /**< Current descriptor does not match comparator criteria. */
167 };
168
169 /** Enum for return values of USB_Host_GetNextDescriptorComp() */
170 enum DSearch_Comp_Return_ErrorCodes_t
171 {
172 Descriptor_Search_Comp_Found = 0, /**< Configuration descriptor now points to descriptor which matches
173 * search criteria of the given comparator function. */
174 Descriptor_Search_Comp_Fail = 1, /**< Comparator function returned Descriptor_Search_Fail. */
175 Descriptor_Search_Comp_EndOfDescriptor = 2, /**< End of configuration descriptor reached before match found. */
176 };
177
178 /* Function Prototypes: */
179 /** Retrieves the configuration descriptor data or size from an attached device via a standard request.
180 *
181 * \param ConfigSizePtr Pointer to a uint16_t for either storing or retrieving the configuration
182 * descriptor size
183 *
184 * \param BufferPtr Pointer to the buffer for storing the configuration descriptor data. If this is
185 * NULL, the size of the configuration descriptor will be retrieved instead and
186 * placed in the variable pointed to by ConfigSizePtr. If this is non-NULL, the number
187 * of bytes indicated by ConfigSizePtr of the configuration descriptor will be loaded
188 * into the buffer
189 */
190 uint8_t USB_Host_GetDeviceConfigDescriptor(uint16_t* const ConfigSizePtr, void* BufferPtr)
191 ATTR_NON_NULL_PTR_ARG(1);
192
193 /* Inline Functions: */
194 /** Skips over the current sub-descriptor inside the configuration descriptor, so that the pointer then
195 points to the next sub-descriptor. The bytes remaining value is automatically decremented.
196 *
197 * \param BytesRem Pointer to the number of bytes remaining of the configuration descriptor
198 * \param CurrConfigLoc Pointer to the current descriptor inside the configuration descriptor
199 */
200 static inline void USB_Host_GetNextDescriptor(uint16_t* const BytesRem,
201 uint8_t** const CurrConfigLoc)
202 ATTR_NON_NULL_PTR_ARG(1, 2);
203 static inline void USB_Host_GetNextDescriptor(uint16_t* const BytesRem,
204 uint8_t** const CurrConfigLoc)
205 {
206 #if defined(USE_NONSTANDARD_DESCRIPTOR_NAMES)
207 uint16_t CurrDescriptorSize = DESCRIPTOR_CAST(*CurrConfigLoc, USB_Descriptor_Header_t).Size;
208 #else
209 uint16_t CurrDescriptorSize = DESCRIPTOR_CAST(*CurrConfigLoc, USB_Descriptor_Header_t).bLength;
210 #endif
211
212 *CurrConfigLoc += CurrDescriptorSize;
213 *BytesRem -= CurrDescriptorSize;
214 }
215
216 /** Skips to the next sub-descriptor inside the configuration descriptor of the specified type value.
217 * The bytes remaining value is automatically decremented.
218 *
219 * \param BytesRem Pointer to the number of bytes remaining of the configuration descriptor
220 * \param CurrConfigLoc Pointer to the current descriptor inside the configuration descriptor
221 * \param Type Descriptor type value to search for
222 */
223 void USB_Host_GetNextDescriptorOfType(uint16_t* const BytesRem,
224 uint8_t** const CurrConfigLoc,
225 const uint8_t Type)
226 ATTR_NON_NULL_PTR_ARG(1, 2);
227
228 /** Skips to the next sub-descriptor inside the configuration descriptor of the specified type value,
229 * which must come before a descriptor of the second given type value. If the BeforeType type
230 * descriptor is reached first, the number of bytes remaining to process is set to zero and the
231 * function exits. The bytes remaining value is automatically decremented.
232 *
233 * \param BytesRem Pointer to the number of bytes remaining of the configuration descriptor
234 * \param CurrConfigLoc Pointer to the current descriptor inside the configuration descriptor
235 * \param Type Descriptor type value to search for
236 * \param BeforeType Descriptor type value which must not be reached before the given Type descriptor
237 */
238 void USB_Host_GetNextDescriptorOfTypeBefore(uint16_t* const BytesRem,
239 uint8_t** const CurrConfigLoc,
240 const uint8_t Type,
241 const uint8_t BeforeType)
242 ATTR_NON_NULL_PTR_ARG(1, 2);
243
244 /** Skips to the next sub-descriptor inside the configuration descriptor of the specified type value,
245 * which must come after a descriptor of the second given type value. The bytes remaining value is
246 * automatically decremented.
247 *
248 * \param BytesRem Pointer to the number of bytes remaining of the configuration descriptor
249 * \param CurrConfigLoc Pointer to the current descriptor inside the configuration descriptor
250 * \param Type Descriptor type value to search for
251 * \param AfterType Descriptor type value which must be reached before the given Type descriptor
252 */
253 void USB_Host_GetNextDescriptorOfTypeAfter(uint16_t* const BytesRem,
254 uint8_t** const CurrConfigLoc,
255 const uint8_t Type,
256 const uint8_t AfterType)
257 ATTR_NON_NULL_PTR_ARG(1, 2);
258
259 /* Private Interface - For use in library only: */
260 #if !defined(__DOXYGEN__)
261 /* Function Prototypes: */
262 uint8_t USB_Host_GetNextDescriptorComp_P(uint16_t* BytesRem, uint8_t** CurrConfigLoc,
263 uint8_t (* const ComparatorRoutine)(void* const));
264 #endif
265
266 /* Disable C linkage for C++ Compilers: */
267 #if defined(__cplusplus)
268 }
269 #endif
270
271 #endif
272
273 /** @} */