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