blob: 9f6323e938ed543542c8a4ceae1258dc2af87f44 [file] [log] [blame]
Kévin Redon69b92d92019-01-24 16:39:20 +01001/**
2 * \file
3 *
4 * \brief USB protocol implementation.
5 *
6 * This file contains the USB definitions and data structures provided by the
7 * USB 2.0 specification.
8 *
9 * Copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
10 *
11 * \asf_license_start
12 *
13 * \page License
14 *
15 * Subject to your compliance with these terms, you may use Microchip
16 * software and any derivatives exclusively with Microchip products.
17 * It is your responsibility to comply with third party license terms applicable
18 * to your use of third party software (including open source software) that
19 * may accompany Microchip software.
20 *
21 * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,
22 * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,
23 * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,
24 * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE
25 * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL
26 * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE
27 * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE
28 * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT
29 * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY
30 * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
31 * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
32 *
33 * \asf_license_stop
34 */
35
36#define CONF_NO_ASSERT_CHECK
37
38#include "usb_protocol.h"
39
40#ifdef CONF_NO_ASSERT_CHECK
41#define _param_error_check(cond)
42#define _desc_len_check() \
43 if (usb_desc_len(desc) < 2) { \
44 /* Encounter an invalid descriptor. */ \
45 return NULL; \
46 }
47#else
48#define _param_error_check(cond) ASSERT(cond)
49#define _desc_len_check() ASSERT(usb_desc_len(desc) >= 2)
50#endif
51
52uint8_t *usb_find_desc(uint8_t *desc, uint8_t *eof, uint8_t type)
53{
54 _param_error_check(desc && eof && (desc < eof));
55
56 while (desc < eof) {
57 _desc_len_check();
58 if (type == usb_desc_type(desc)) {
59 return desc;
60 }
61 desc = usb_desc_next(desc);
62 }
63 return NULL;
64}
65
66uint8_t *usb_find_iface_after(uint8_t *desc, uint8_t *eof, uint8_t iface_n)
67{
68 _param_error_check(desc && eof && (desc < eof));
69
70 while (desc < eof) {
71 _desc_len_check();
72 if (USB_DT_INTERFACE == usb_desc_type(desc)) {
73 if (iface_n != desc[2]) {
74 return desc;
75 }
76 }
77 desc = usb_desc_next(desc);
78 }
79 return eof;
80}
81
82uint8_t *usb_find_ep_desc(uint8_t *desc, uint8_t *eof)
83{
84 _param_error_check(desc && eof && (desc < eof));
85
86 while (desc < eof) {
87 _desc_len_check();
88 if (USB_DT_INTERFACE == usb_desc_type(desc)) {
89 break;
90 }
91 if (USB_DT_ENDPOINT == usb_desc_type(desc)) {
92 return desc;
93 }
94 desc = usb_desc_next(desc);
95 }
96 return NULL;
97}
98
99uint8_t *usb_find_cfg_desc(uint8_t *desc, uint8_t *eof, uint8_t cfg_value)
100{
101 _param_error_check(desc && eof && (desc < eof));
102
103 desc = usb_find_desc(desc, eof, USB_DT_CONFIG);
104 if (!desc) {
105 return NULL;
106 }
107 while (desc < eof) {
108 _desc_len_check();
109 if (desc[1] != USB_DT_CONFIG) {
110 break;
111 }
112 if (desc[5] == cfg_value) {
113 return desc;
114 }
115 desc = usb_cfg_desc_next(desc);
116 }
117 return NULL;
118}
119
120uint8_t *usb_find_othspdcfg_desc(uint8_t *desc, uint8_t *eof, uint8_t cfg_value)
121{
122 _param_error_check(desc && eof && (desc < eof));
123
124 desc = usb_find_desc(desc, eof, USB_DT_OTHER_SPEED_CONFIG);
125 if (!desc) {
126 return NULL;
127 }
128 while (desc < eof) {
129 _desc_len_check();
130 if (desc[1] != USB_DT_OTHER_SPEED_CONFIG) {
131 break;
132 }
133 if (desc[5] == cfg_value) {
134 return desc;
135 }
136 desc = usb_cfg_desc_next(desc);
137 }
138 return NULL;
139}
140
141uint8_t *usb_find_str_desc(uint8_t *desc, uint8_t *eof, uint8_t str_index)
142{
143 uint8_t i;
144
145 _param_error_check(desc && eof && (desc < eof));
146
147 for (i = 0; desc < eof;) {
148 desc = usb_find_desc(desc, eof, USB_DT_STRING);
149 if (desc) {
150 _desc_len_check();
151 if (i == str_index) {
152 return desc;
153 }
154 i++;
155 desc = usb_desc_next(desc);
156 } else {
157 return NULL;
158 }
159 }
160 return NULL;
161}