summaryrefslogtreecommitdiff
path: root/firmware/usbstack/core/epsetup.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/usbstack/core/epsetup.c')
-rw-r--r--firmware/usbstack/core/epsetup.c186
1 files changed, 186 insertions, 0 deletions
diff --git a/firmware/usbstack/core/epsetup.c b/firmware/usbstack/core/epsetup.c
new file mode 100644
index 0000000000..6ae54fb9ac
--- /dev/null
+++ b/firmware/usbstack/core/epsetup.c
@@ -0,0 +1,186 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id: $
9 *
10 * Copyright (C) 2007 by Christian Gmeiner
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19
20#include <string.h>
21#include <ctype.h>
22#include "usbstack/core.h"
23
24/**
25 *
26 * Naming Convention for Endpoint Names
27 *
28 * - ep1, ep2, ... address is fixed, not direction or type
29 * - ep1in, ep2out, ... address and direction are fixed, not type
30 * - ep1-bulk, ep2-bulk, ... address and type are fixed, not direction
31 * - ep1in-bulk, ep2out-iso, ... all three are fixed
32 * - ep-* ... no functionality restrictions
33 *
34 * Type suffixes are "-bulk", "-iso", or "-int". Numbers are decimal.
35 *
36 */
37static int ep_matches(struct usb_ep* ep, struct usb_endpoint_descriptor* desc);
38
39void usb_ep_autoconfig_reset(void) {
40
41 struct usb_ep* ep = NULL;
42 if (usbcore.active_controller == NULL) {
43 return;
44 }
45
46 logf("resetting endpoints");
47 list_for_each_entry(ep, &usbcore.active_controller->endpoints.list, list) {
48 logf("reset %s", ep->name);
49 ep->claimed = false;
50 }
51}
52
53/**
54 * Find a suitable endpoint for the requested endpoint descriptor.
55 * @param desc usb descritpro to use for seraching.
56 * @return NULL or a valid endpoint.
57 */
58struct usb_ep* usb_ep_autoconfig(struct usb_endpoint_descriptor* desc) {
59
60 struct usb_ep* ep = NULL;
61 if (usbcore.active_controller == NULL) {
62 logf("active controller NULL");
63 return NULL;
64 }
65
66 list_for_each_entry(ep, &usbcore.active_controller->endpoints.list, list) {
67 if (ep_matches (ep, desc)) {
68 return ep;
69 }
70 }
71
72 return NULL;
73}
74
75static int ep_matches(struct usb_ep* ep, struct usb_endpoint_descriptor* desc) {
76
77 uint8_t type;
78 const char* tmp;
79 uint16_t max;
80
81 /* endpoint already claimed? */
82 if (ep->claimed) {
83 logf("!! claimed !!");
84 return 0;
85 }
86
87 /* only support ep0 for portable CONTROL traffic */
88 type = desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
89 if (type == USB_ENDPOINT_XFER_CONTROL) {
90 logf("type == control");
91 return 0;
92 }
93
94 /* some other naming convention */
95 if (ep->name[0] != 'e') {
96 logf("wrong name");
97 return 0;
98 }
99
100 /* type-restriction: "-iso", "-bulk", or "-int".
101 * direction-restriction: "in", "out".
102 */
103 if (ep->name[2] != '-' ) {
104 tmp = strrchr (ep->name, '-');
105 if (tmp) {
106 switch (type) {
107 case USB_ENDPOINT_XFER_INT:
108 /* bulk endpoints handle interrupt transfers,
109 * except the toggle-quirky iso-synch kind
110 */
111 if (tmp[2] == 's') { // == "-iso"
112 return 0;
113 }
114 break;
115 case USB_ENDPOINT_XFER_BULK:
116 if (tmp[1] != 'b') { // != "-bulk"
117 return 0;
118 }
119 break;
120 case USB_ENDPOINT_XFER_ISOC:
121 if (tmp[2] != 's') { // != "-iso"
122 return 0;
123 }
124 }
125 } else {
126 tmp = ep->name + strlen (ep->name);
127 }
128
129 /* direction-restriction: "..in-..", "out-.." */
130 tmp--;
131 if (!isdigit(*tmp)) {
132 if (desc->bEndpointAddress & USB_DIR_IN) {
133 if ('n' != *tmp) {
134 return 0;
135 }
136 } else {
137 if ('t' != *tmp) {
138 return 0;
139 }
140 }
141 }
142 }
143
144
145 /* endpoint maxpacket size is an input parameter, except for bulk
146 * where it's an output parameter representing the full speed limit.
147 * the usb spec fixes high speed bulk maxpacket at 512 bytes.
148 */
149 max = 0x7ff & desc->wMaxPacketSize;
150
151 switch (type) {
152 case USB_ENDPOINT_XFER_INT:
153 /* INT: limit 64 bytes full speed, 1024 high speed */
154 if ((usbcore.active_controller->speed != USB_SPEED_HIGH) && (max > 64)) {
155 return 0;
156 }
157 /* FALLTHROUGH */
158
159 case USB_ENDPOINT_XFER_ISOC:
160 if ((usbcore.active_controller->speed != USB_SPEED_HIGH) && (max > 1023)) {
161 return 0;
162 }
163 break;
164 }
165
166 /* MATCH!! */
167
168 /* report address */
169 desc->bEndpointAddress |= ep->ep_num;
170
171 /* report (variable) full speed bulk maxpacket */
172 if (type == USB_ENDPOINT_XFER_BULK) {
173 int size = max;
174
175 /* min() doesn't work on bitfields with gcc-3.5 */
176 if (size > 64) {
177 size = 64;
178 }
179 desc->wMaxPacketSize = size;
180 }
181
182 /* save desc in endpoint */
183 ep->desc = desc;
184
185 return 1;
186}