1 /*
2 * Copyright (c) 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 <dev/usb/class/bulktest.h>
24
25 #include <debug.h>
26 #include <trace.h>
27 #include <err.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <assert.h>
31 #include <list.h>
32 #include <dev/usbc.h>
33 #include <dev/usb.h>
34 #include <lk/init.h>
35
36 /* a simple demo usb class device that reflects data written to
37 * one endpoint to the other.
38 */
39
40 #define LOCAL_TRACE 0
41
42 #define W(w) (w & 0xff), (w >> 8)
43 #define W3(w) (w & 0xff), ((w >> 8) & 0xff), ((w >> 16) & 0xff)
44
45 static status_t ep_cb_rx(ep_t endpoint, usbc_transfer_t *t);
46 static status_t ep_cb_tx(ep_t endpoint, usbc_transfer_t *t);
47
48 #define TRANSFER_SIZE 512
49
queue_rx(void)50 static void queue_rx(void)
51 {
52 static usbc_transfer_t transfer;
53 static uint8_t buf[TRANSFER_SIZE];
54
55 transfer.callback = &ep_cb_rx;
56 transfer.result = 0;
57 transfer.buf = &buf;
58 transfer.buflen = sizeof(buf);
59 transfer.bufpos = 0;
60 transfer.extra = 0;
61
62 usbc_queue_rx(1, &transfer);
63 }
64
queue_tx(void)65 static void queue_tx(void)
66 {
67 static usbc_transfer_t transfer;
68 static uint8_t buf[TRANSFER_SIZE];
69
70 for (uint i = 0; i < sizeof(buf); i++) {
71 buf[i] = ~i;
72 }
73
74 transfer.callback = &ep_cb_tx;
75 transfer.result = 0;
76 transfer.buf = &buf;
77 transfer.buflen = sizeof(buf);
78 transfer.bufpos = 0;
79 transfer.extra = 0;
80
81 usbc_queue_tx(1, &transfer);
82 }
83
84
ep_cb_rx(ep_t endpoint,usbc_transfer_t * t)85 static status_t ep_cb_rx(ep_t endpoint, usbc_transfer_t *t)
86 {
87 #if LOCAL_TRACE
88 LTRACEF("ep %u transfer %p\n", endpoint, t);
89 usbc_dump_transfer(t);
90
91 if (t->result >= 0) {
92 hexdump8(t->buf, t->bufpos);
93 }
94 #endif
95
96 if (t->result >= 0)
97 queue_rx();
98
99 return NO_ERROR;
100 }
101
ep_cb_tx(ep_t endpoint,usbc_transfer_t * t)102 static status_t ep_cb_tx(ep_t endpoint, usbc_transfer_t *t)
103 {
104 #if LOCAL_TRACE
105 LTRACEF("ep %u transfer %p\n", endpoint, t);
106 usbc_dump_transfer(t);
107 #endif
108
109 if (t->result >= 0)
110 queue_tx();
111
112 return NO_ERROR;
113 }
114
bulktest_usb_cb(void * cookie,usb_callback_op_t op,const union usb_callback_args * args)115 static status_t bulktest_usb_cb(void *cookie, usb_callback_op_t op, const union usb_callback_args *args)
116 {
117 LTRACEF("cookie %p, op %u, args %p\n", cookie, op, args);
118
119 if (op == USB_CB_ONLINE) {
120 usbc_setup_endpoint(1, USB_IN, 0x40, USB_BULK);
121 usbc_setup_endpoint(1, USB_OUT, 0x40, USB_BULK);
122
123 queue_rx();
124 queue_tx();
125 }
126 return NO_ERROR;
127 }
128
usb_class_bulktest_init(uint interface_num,ep_t epin,ep_t epout)129 status_t usb_class_bulktest_init(uint interface_num, ep_t epin, ep_t epout)
130 {
131 LTRACEF("epin %u, epout %u\n", epin, epout);
132
133 /* build a descriptor for it */
134 uint8_t if_descriptor[] = {
135 0x09, /* length */
136 INTERFACE, /* type */
137 interface_num, /* interface num */
138 0x00, /* alternates */
139 0x02, /* endpoint count */
140 0xff, /* interface class */
141 0xff, /* interface subclass */
142 0x00, /* interface protocol */
143 0x00, /* string index */
144
145 /* endpoint 1 IN */
146 0x07, /* length */
147 ENDPOINT, /* type */
148 epin | 0x80, /* address: 1 IN */
149 0x02, /* type: bulk */
150 W(64), /* max packet size: 64 */
151 00, /* interval */
152
153 /* endpoint 1 OUT */
154 0x07, /* length */
155 ENDPOINT, /* type */
156 epout, /* address: 1 OUT */
157 0x02, /* type: bulk */
158 W(64), /* max packet size: 64 */
159 00, /* interval */
160 };
161
162 usb_append_interface_lowspeed(if_descriptor, sizeof(if_descriptor));
163 usb_append_interface_highspeed(if_descriptor, sizeof(if_descriptor));
164
165 usb_register_callback(&bulktest_usb_cb, NULL);
166
167 return NO_ERROR;
168 }
169
170