blob: 2689b448dfdbf96ed063b01ceaf7a8aef3cbcb38 [file] [log] [blame]
rjw1f884582022-01-06 17:20:42 +08001/*
2 * Copyright (c) 2013-2015 Travis Geiselbrecht
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files
6 * (the "Software"), to deal in the Software without restriction,
7 * including without limitation the rights to use, copy, modify, merge,
8 * publish, distribute, sublicense, and/or sell copies of the Software,
9 * and to permit persons to whom the Software is furnished to do so,
10 * subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 */
23#include <err.h>
24#include <debug.h>
25#include <stdio.h>
26#include <trace.h>
27#include <target.h>
28#include <compiler.h>
29#include <dev/usb.h>
30#include <dev/usbc.h>
31#include <hw/usb.h>
32#include <lk/init.h>
33
34#define LOCAL_TRACE 0
35
36#define W(w) (w & 0xff), (w >> 8)
37#define W3(w) (w & 0xff), ((w >> 8) & 0xff), ((w >> 16) & 0xff)
38
39/* top level device descriptor */
40static const uint8_t dev_descr[] = {
41 0x12, /* descriptor length */
42 DEVICE, /* Device Descriptor type */
43 W(0x0200), /* USB Version */
44 0xff, /* class */
45 0xff, /* subclass */
46 0xff, /* protocol */
47 64, /* max packet size, ept0 */
48 W(0x9999), /* vendor */
49 W(0x9999), /* product */
50 W(0x9999), /* release */
51 0x2, /* manufacturer string */
52 0x1, /* product string */
53 0x0, /* serialno string */
54 0x1, /* num configs */
55};
56
57/* high/low speed device qualifier */
58static const uint8_t devqual_descr[] = {
59 0x0a, /* len */
60 DEVICE_QUALIFIER, /* Device Qualifier type */
61 W(0x0200), /* USB version */
62 0x00, /* class */
63 0x00, /* subclass */
64 0x00, /* protocol */
65 64, /* max packet size, ept0 */
66 0x01, /* num configs */
67 0x00 /* reserved */
68};
69
70static const uint8_t cfg_descr[] = {
71 0x09, /* Length of Cfg Descr */
72 CONFIGURATION, /* Type of Cfg Descr */
73 W(0x09), /* Total Length (incl ifc, ept) */
74 0x00, /* # Interfaces */
75 0x01, /* Cfg Value */
76 0x00, /* Cfg String */
77 0xc0, /* Attributes -- self powered */
78 250, /* Power Consumption - 500mA */
79};
80
81static const uchar langid[] = { 0x04, 0x03, 0x09, 0x04 };
82
83static const uint8_t if_descriptor_lowspeed[] = {
84 0x09, /* length */
85 INTERFACE, /* type */
86 0x01, /* interface num */
87 0x00, /* alternates */
88 0x02, /* endpoint count */
89 0xff, /* interface class */
90 0xff, /* interface subclass */
91 0x00, /* interface protocol */
92 0x00, /* string index */
93
94 /* endpoint 1 IN */
95 0x07, /* length */
96 ENDPOINT, /* type */
97 0x81, /* address: 1 IN */
98 0x02, /* type: bulk */
99 W(64), /* max packet size: 64 */
100 00, /* interval */
101
102 /* endpoint 1 OUT */
103 0x07, /* length */
104 ENDPOINT, /* type */
105 0x01, /* address: 1 OUT */
106 0x02, /* type: bulk */
107 W(64), /* max packet size: 64 */
108 00, /* interval */
109};
110
111usb_config config = {
112 .lowspeed = {
113 .device = USB_DESC_STATIC(dev_descr),
114 .device_qual = USB_DESC_STATIC(devqual_descr),
115 .config = USB_DESC_STATIC(cfg_descr),
116 },
117 .highspeed = {
118 .device = USB_DESC_STATIC(dev_descr),
119 .device_qual = USB_DESC_STATIC(devqual_descr),
120 .config = USB_DESC_STATIC(cfg_descr),
121 },
122
123 .langid = USB_DESC_STATIC(langid),
124};
125
126static status_t ep_cb_rx(ep_t endpoint, usbc_transfer_t *t);
127static status_t ep_cb_tx(ep_t endpoint, usbc_transfer_t *t);
128
129static void queue_rx(void)
130{
131 static usbc_transfer_t transfer;
132 static uint8_t buf[512];
133
134 transfer.callback = &ep_cb_rx;
135 transfer.result = 0;
136 transfer.buf = &buf;
137 transfer.buflen = sizeof(buf);
138 transfer.bufpos = 0;
139 transfer.extra = 0;
140
141 usbc_queue_rx(1, &transfer);
142}
143
144static void queue_tx(void)
145{
146 static usbc_transfer_t transfer;
147 static uint8_t buf[512];
148
149 for (uint i = 0; i < sizeof(buf); i++) {
150 buf[i] = ~i;
151 }
152
153 transfer.callback = &ep_cb_tx;
154 transfer.result = 0;
155 transfer.buf = &buf;
156 transfer.buflen = sizeof(buf);
157 transfer.bufpos = 0;
158 transfer.extra = 0;
159
160 usbc_queue_tx(1, &transfer);
161}
162
163static status_t ep_cb_rx(ep_t endpoint, usbc_transfer_t *t)
164{
165#if LOCAL_TRACE
166 LTRACEF("ep %u transfer %p\n", endpoint, t);
167 usbc_dump_transfer(t);
168
169 if (t->result >= 0) {
170 hexdump8(t->buf, t->bufpos);
171 }
172#endif
173
174 if (t->result >= 0)
175 queue_rx();
176
177 return NO_ERROR;
178}
179
180static status_t ep_cb_tx(ep_t endpoint, usbc_transfer_t *t)
181{
182#if LOCAL_TRACE
183 LTRACEF("ep %u transfer %p\n", endpoint, t);
184 usbc_dump_transfer(t);
185#endif
186
187 if (t->result >= 0)
188 queue_tx();
189
190 return NO_ERROR;
191}
192
193static status_t usb_cb(void *cookie, usb_callback_op_t op, const union usb_callback_args *args)
194{
195 LTRACEF("cookie %p, op %u, args %p\n", cookie, op, args);
196
197 if (op == USB_CB_ONLINE) {
198 usbc_setup_endpoint(1, USB_IN, 0x40);
199 usbc_setup_endpoint(1, USB_OUT, 0x40);
200
201 queue_rx();
202 queue_tx();
203 }
204 return NO_ERROR;
205}
206
207void target_usb_setup(void)
208{
209 usb_setup(&config);
210 printf("appending interfaces\n");
211 usb_append_interface_lowspeed(if_descriptor_lowspeed, sizeof(if_descriptor_lowspeed));
212 usb_append_interface_highspeed(if_descriptor_lowspeed, sizeof(if_descriptor_lowspeed));
213
214 usb_add_string("LK", 1);
215 usb_add_string("LK Industries", 2);
216
217 usb_register_callback(&usb_cb, NULL);
218 usb_start();
219}