d1f8927f8f336b901ad3ad80728fec7c441c7808
[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 #ifndef __CONFIGDESCRIPTOR_H__
39 #define __CONFIGDESCRIPTOR_H__
40
41 /* Includes: */
42 #include <avr/io.h>
43
44 #include "../../../Common/Common.h"
45 #include "../LowLevel/HostChapter9.h"
46 #include "../HighLevel/StdDescriptors.h"
47
48 /* Enable C linkage for C++ Compilers: */
49 #if defined(__cplusplus)
50 extern "C" {
51 #endif
52
53 /* Public Interface - May be used in end-application: */
54 /* Macros: */
55 /** Casts a pointer to a descriptor inside the configuration descriptor into a pointer to the given
56 * descriptor type.
57 *
58 * Usage Example:
59 * \code
60 * uint8_t* CurrDescriptor = &ConfigDescriptor[0]; // Pointing to the configuration header
61 * USB_Descriptor_Configuration_Header_t* ConfigHeaderPtr = DESCRIPTOR_PCAST(CurrDescriptor,
62 * USB_Descriptor_Configuration_Header_t);
63 *
64 * // Can now access elements of the configuration header struct using the -> indirection operator
65 * \endcode
66 */
67 #define DESCRIPTOR_PCAST(DescriptorPtr, Type) ((Type*)DescriptorPtr)
68
69 /** Casts a pointer to a descriptor inside the configuration descriptor into the given descriptor
70 * type (as an actual struct instance rather than a pointer to a struct).
71 *
72 * Usage Example:
73 * \code
74 * uint8_t* CurrDescriptor = &ConfigDescriptor[0]; // Pointing to the configuration header
75 * USB_Descriptor_Configuration_Header_t ConfigHeader = DESCRIPTOR_CAST(CurrDescriptor,
76 * USB_Descriptor_Configuration_Header_t);
77 *
78 * // Can now access elements of the configuration header struct using the . operator
79 * \endcode
80 */
81 #define DESCRIPTOR_CAST(DescriptorPtr, Type) (*DESCRIPTOR_PCAST(DescriptorPtr, Type))
82
83 /** Returns the descriptor's type, expressed as the 8-bit type value in the header of the descriptor.
84 * This value's meaning depends on the descriptor's placement in the descriptor, but standard type
85 * values can be accessed in the DescriptorTypes_t enum located in USB/HighLevel/StdDescriptors.h.
86 */
87 #if defined(USE_NONSTANDARD_DESCRIPTOR_NAMES) || defined(__DOXYGEN__)
88 #define DESCRIPTOR_TYPE(DescriptorPtr) DESCRIPTOR_CAST(DescriptorPtr, USB_Descriptor_Header_t).Type
89 #else
90 #define DESCRIPTOR_TYPE(DescriptorPtr) DESCRIPTOR_CAST(DescriptorPtr, USB_Descriptor_Header_t).bDescriptorType
91 #endif
92
93 /** Returns the descriptor's size, expressed as the 8-bit value indicating the number of bytes. */
94 #if defined(USE_NONSTANDARD_DESCRIPTOR_NAMES) || defined(__DOXYGEN__)
95 #define DESCRIPTOR_SIZE(DescriptorPtr) DESCRIPTOR_CAST(DescriptorPtr, USB_Descriptor_Header_t).Size
96 #else
97 #define DESCRIPTOR_SIZE(DescriptorPtr) DESCRIPTOR_CAST(DescriptorPtr, USB_Descriptor_Header_t).bLength
98 #endif
99
100 /** Creates a prototype for or begins a descriptor comparitor routine. Descriptor comparitor routines are
101 * small search routines which are passed a pointer to the current sub descriptor in the configuration
102 * descriptor, and which analyse the sub descriptor to determine whether or not it matches the routine's
103 * search parameters. Comparitor routines provide a powerful way to scan through the config descriptor
104 * for certain descriptors matching unique criteria.
105 *
106 * Comparitor routines are passed in a single pointer named CurrentDescriptor, and should return a value
107 * of a member of the DSEARCH_Return_ErrorCodes_t enum.
108 */
109 #define DESCRIPTOR_COMPARATOR(name) uint8_t DCOMP_##name (void* const CurrentDescriptor)
110
111 /** Searches for the next descriptor in the given configuration descriptor using a premade comparator
112 * function. The routine updates the position and remaining configuration descriptor bytes values
113 * automatically. If a comparator routine fails a search, the descriptor pointer is retreated back
114 * so that the next descriptor search invocation will start from the descriptor which first caused the
115 * original search to fail. This behaviour allows for one comparator to be used immediately after another
116 * has failed, starting the second search from the descriptor which failed the first.
117 *
118 * \param DSize Pointer to an int storing the remaining bytes in the configuration descriptor
119 * \param DPos Pointer to the current position in the configuration descriptor
120 * \param DSearch Name of the comparitor search function to use on the configuration descriptor
121 *
122 * \return Value of one of the members of the DSEARCH_Comp_Return_ErrorCodes_t enum
123 *
124 * Usage Example:
125 * \code
126 * DESCRIPTOR_COMPARATOR(EndpointSearcher); // Comparator Prototype
127 *
128 * DESCRIPTOR_COMPARATOR(EndpointSearcher)
129 * {
130 * if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Endpoint)
131 * return Descriptor_Search_Found;
132 * else
133 * return Descriptor_Search_NotFound;
134 * }
135 *
136 * //...
137 * // After retrieving configuration descriptor:
138 * if (USB_Host_GetNextDescriptorComp(&BytesRemaining, &ConfigDescriptorData, EndpointSearcher) ==
139 * Descriptor_Search_Comp_Found)
140 * {
141 * // Do something with the endpoint descriptor
142 * }
143 * \endcode
144 */
145 #define USB_Host_GetNextDescriptorComp(DSize, DPos, DSearch) \
146 USB_Host_GetNextDescriptorComp_P(DSize, DPos, DCOMP_##DSearch)
147 /* Enums: */
148 /** Enum for return values of a descriptor comparator made with DESCRIPTOR_COMPARATOR. */
149 enum DSEARCH_Return_ErrorCodes_t
150 {
151 Descriptor_Search_Found = 0, /**< Current descriptor matches comparator criteria. */
152 Descriptor_Search_Fail = 1, /**< No further descriptor could possibly match criteria, fail the search. */
153 Descriptor_Search_NotFound = 2, /**< Current descriptor does not match comparator criteria. */
154 };
155
156 /** Enum for return values of USB_Host_GetNextDescriptorComp() */
157 enum DSEARCH_Comp_Return_ErrorCodes_t
158 {
159 Descriptor_Search_Comp_Found = 0, /**< Configuration descriptor now points to decriptor which matches
160 * search criteria of the given comparator function. */
161 Descriptor_Search_Comp_Fail = 1, /**< Comparator function returned Descriptor_Search_Fail. */
162 Descriptor_Search_Comp_EndOfDescriptor = 2, /**< End of configuration descriptor reached before match found. */
163 };
164
165 /* Function Prototypes: */
166 /** Retrieves the configuration descriptor data or size from an attached device via a standard request.
167 *
168 * \param ConfigSizePtr Pointer to a uint16_t for either storing or retrieving the configuration
169 * descriptor size
170 *
171 * \param BufferPtr Pointer to the buffer for storing the configuration descriptor data. If this is
172 * NULL, the size of the configuration descriptor will be retrieved instead and
173 * placed in the variable pointed to by ConfigSizePtr. If this is non-NULL, the number
174 * of bytes indicated by ConfigSizePtr of the configuration descriptor will be loaded
175 * into the buffer
176 */
177 uint8_t USB_Host_GetDeviceConfigDescriptor(uint16_t* const ConfigSizePtr, void* BufferPtr)
178 ATTR_NON_NULL_PTR_ARG(1);
179
180 /* Inline Functions: */
181 /** Skips over the current sub-descriptor inside the configuration descriptor, so that the pointer then
182 points to the next sub-descriptor. The bytes remaining value is automatically decremented.
183 *
184 * \param BytesRem Pointer to the number of bytes remaining of the configuration descriptor
185 * \param CurrConfigLoc Pointer to the current descriptor inside the configuration descriptor
186 */
187 static inline void USB_Host_GetNextDescriptor(uint16_t* const BytesRem,
188 uint8_t** const CurrConfigLoc)
189 ATTR_NON_NULL_PTR_ARG(1, 2);
190 static inline void USB_Host_GetNextDescriptor(uint16_t* const BytesRem,
191 uint8_t** const CurrConfigLoc)
192 {
193 #if defined(USE_NONSTANDARD_DESCRIPTOR_NAMES)
194 uint16_t CurrDescriptorSize = DESCRIPTOR_CAST(*CurrConfigLoc, USB_Descriptor_Header_t).Size;
195 #else
196 uint16_t CurrDescriptorSize = DESCRIPTOR_CAST(*CurrConfigLoc, USB_Descriptor_Header_t).bLength;
197 #endif
198
199 *CurrConfigLoc += CurrDescriptorSize;
200 *BytesRem -= CurrDescriptorSize;
201 }
202
203 /** Skips to the next sub-descriptor inside the configuration descriptor of the specified type value.
204 * The bytes remaining value is automatically decremented.
205 *
206 * \param BytesRem Pointer to the number of bytes remaining of the configuration descriptor
207 * \param CurrConfigLoc Pointer to the current descriptor inside the configuration descriptor
208 * \param Type Descriptor type value to search for
209 */
210 void USB_Host_GetNextDescriptorOfType(uint16_t* const BytesRem,
211 uint8_t** const CurrConfigLoc,
212 const uint8_t Type)
213 ATTR_NON_NULL_PTR_ARG(1, 2);
214
215 /** Skips to the next sub-descriptor inside the configuration descriptor of the specified type value,
216 * which must come before a descriptor of the second given type value. If the BeforeType type
217 * descriptor is reached first, the number of bytes remaining to process is set to zero and the
218 * function exits. The bytes remaining value is automatically decremented.
219 *
220 * \param BytesRem Pointer to the number of bytes remaining of the configuration descriptor
221 * \param CurrConfigLoc Pointer to the current descriptor inside the configuration descriptor
222 * \param Type Descriptor type value to search for
223 * \param BeforeType Descriptor type value which must not be reached before the given Type descriptor
224 */
225 void USB_Host_GetNextDescriptorOfTypeBefore(uint16_t* const BytesRem,
226 uint8_t** const CurrConfigLoc,
227 const uint8_t Type,
228 const uint8_t BeforeType)
229 ATTR_NON_NULL_PTR_ARG(1, 2);
230
231 /** Skips to the next sub-descriptor inside the configuration descriptor of the specified type value,
232 * which must come after a descriptor of the second given type value. The bytes remaining value is
233 * automatically decremented.
234 *
235 * \param BytesRem Pointer to the number of bytes remaining of the configuration descriptor
236 * \param CurrConfigLoc Pointer to the current descriptor inside the configuration descriptor
237 * \param Type Descriptor type value to search for
238 * \param AfterType Descriptor type value which must be reached before the given Type descriptor
239 */
240 void USB_Host_GetNextDescriptorOfTypeAfter(uint16_t* const BytesRem,
241 uint8_t** const CurrConfigLoc,
242 const uint8_t Type,
243 const uint8_t AfterType)
244 ATTR_NON_NULL_PTR_ARG(1, 2);
245
246 /* Private Interface - For use in library only: */
247 #if !defined(__DOXYGEN__)
248 /* Function Prototypes: */
249 uint8_t USB_Host_GetNextDescriptorComp_P(uint16_t* BytesRem, uint8_t** CurrConfigLoc,
250 uint8_t (* const ComparatorRoutine)(void* const));
251 #endif
252
253 /* Disable C linkage for C++ Compilers: */
254 #if defined(__cplusplus)
255 }
256 #endif
257
258 #endif