1
+ /*
2
+ * The MIT License (MIT)
3
+ *
4
+ * Copyright (c) 2022 Nathaniel Brough
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ * of this software and associated documentation files (the "Software"), to deal
8
+ * in the Software without restriction, including without limitation the rights
9
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ * copies of the Software, and to permit persons to whom the Software is
11
+ * furnished to do so, subject to the following conditions:
12
+ *
13
+ * The above copyright notice and this permission notice shall be included in
14
+ * all copies or substantial portions of the Software.
15
+ *
16
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
+ * THE SOFTWARE.
23
+ *
24
+ */
25
+ #include " device/dcd.h"
26
+ #include " fuzz/fuzz_private.h"
27
+ #include < assert.h>
28
+ #include < cstdint>
29
+ #include < limits>
30
+
31
+ #define UNUSED (x ) (void )(x)
32
+
33
+ // --------------------------------------------------------------------+
34
+ // State tracker
35
+ // --------------------------------------------------------------------+
36
+ struct State {
37
+ bool interrupts_enabled;
38
+ bool sof_enabled;
39
+ uint8_t address;
40
+ };
41
+
42
+ static State state = {false , 0 , 0 };
43
+
44
+ // --------------------------------------------------------------------+
45
+ // Controller API
46
+ // All no-ops as we are fuzzing.
47
+ // --------------------------------------------------------------------+
48
+ extern " C" {
49
+ void dcd_init (uint8_t rhport) {
50
+ UNUSED (rhport);
51
+ return ;
52
+ }
53
+
54
+ void dcd_int_handler (uint8_t rhport) {
55
+ assert (_fuzz_data_provider.has_value ());
56
+
57
+ if (!state.interrupts_enabled ) {
58
+ return ;
59
+ }
60
+
61
+ // Choose if we want to generate a signal based on the fuzzed data.
62
+ if (_fuzz_data_provider->ConsumeBool ()) {
63
+ dcd_event_bus_signal (
64
+ rhport,
65
+ // Choose a random event based on the fuzz data.
66
+ (dcd_eventid_t )_fuzz_data_provider->ConsumeIntegralInRange <uint8_t >(
67
+ DCD_EVENT_INVALID + 1 , DCD_EVENT_COUNT - 1 ),
68
+ // Identify trigger as either an interrupt or a syncrhonous call
69
+ // depending on fuzz data.
70
+ _fuzz_data_provider->ConsumeBool ());
71
+ }
72
+
73
+ if (_fuzz_data_provider->ConsumeBool ()) {
74
+ constexpr size_t kSetupFrameLength = 8 ;
75
+ std::vector<uint8_t > setup =
76
+ _fuzz_data_provider->ConsumeBytes <uint8_t >(kSetupFrameLength );
77
+ // Fuzz consumer may return less than requested. If this is the case
78
+ // we want to make sure that at least that length is allocated and available
79
+ // to the signal handler.
80
+ if (setup.size () != kSetupFrameLength ) {
81
+ setup.resize (kSetupFrameLength );
82
+ }
83
+ dcd_event_setup_received (rhport, setup.data (),
84
+ // Identify trigger as either an interrupt or a
85
+ // syncrhonous call depending on fuzz data.
86
+ _fuzz_data_provider->ConsumeBool ());
87
+ }
88
+ }
89
+
90
+ void dcd_int_enable (uint8_t rhport) {
91
+ state.interrupts_enabled = true ;
92
+ UNUSED (rhport);
93
+ return ;
94
+ }
95
+
96
+ void dcd_int_disable (uint8_t rhport) {
97
+ state.interrupts_enabled = false ;
98
+ UNUSED (rhport);
99
+ return ;
100
+ }
101
+
102
+ void dcd_set_address (uint8_t rhport, uint8_t dev_addr) {
103
+ UNUSED (rhport);
104
+ state.address = dev_addr;
105
+ // Respond with status.
106
+ dcd_edpt_xfer (rhport, tu_edpt_addr (0 , TUSB_DIR_IN), NULL , 0 );
107
+ return ;
108
+ }
109
+
110
+ void dcd_remote_wakeup (uint8_t rhport) {
111
+ UNUSED (rhport);
112
+ return ;
113
+ }
114
+
115
+ void dcd_connect (uint8_t rhport) {
116
+ UNUSED (rhport);
117
+ return ;
118
+ }
119
+
120
+ void dcd_disconnect (uint8_t rhport) {
121
+ UNUSED (rhport);
122
+ return ;
123
+ }
124
+
125
+ void dcd_sof_enable (uint8_t rhport, bool en) {
126
+ state.sof_enabled = en;
127
+ UNUSED (rhport);
128
+ return ;
129
+ }
130
+
131
+ // --------------------------------------------------------------------+
132
+ // Endpoint API
133
+ // --------------------------------------------------------------------+
134
+
135
+ // Configure endpoint's registers according to descriptor
136
+ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const *desc_ep) {
137
+ UNUSED (rhport);
138
+ UNUSED (desc_ep);
139
+ return _fuzz_data_provider->ConsumeBool ();
140
+ }
141
+
142
+ // Close all non-control endpoints, cancel all pending transfers if any.
143
+ // Invoked when switching from a non-zero Configuration by SET_CONFIGURE
144
+ // therefore required for multiple configuration support.
145
+ void dcd_edpt_close_all (uint8_t rhport) {
146
+ UNUSED (rhport);
147
+ return ;
148
+ }
149
+
150
+ // Close an endpoint.
151
+ // Since it is weak, caller must TU_ASSERT this function's existence before
152
+ // calling it.
153
+ void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr) {
154
+ UNUSED (rhport);
155
+ UNUSED (ep_addr);
156
+ return ;
157
+ }
158
+
159
+ // Submit a transfer, When complete dcd_event_xfer_complete() is invoked to
160
+ // notify the stack
161
+ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t *buffer,
162
+ uint16_t total_bytes) {
163
+ UNUSED (rhport);
164
+ UNUSED (buffer);
165
+ UNUSED (total_bytes);
166
+
167
+ uint8_t const dir = tu_edpt_dir (ep_addr);
168
+
169
+ if (dir == TUSB_DIR_IN) {
170
+ std::vector<uint8_t > temp =
171
+ _fuzz_data_provider->ConsumeBytes <uint8_t >(total_bytes);
172
+ std::copy (temp.begin (), temp.end (), buffer);
173
+ }
174
+ // Ignore output data as it's not useful for fuzzing without a more
175
+ // complex fuzzed backend.
176
+
177
+ return _fuzz_data_provider->ConsumeBool ();
178
+ }
179
+
180
+ /* TODO: implement a fuzzed version of this.
181
+ bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t *ff,
182
+ uint16_t total_bytes) {}
183
+ */
184
+
185
+ // Stall endpoint, any queuing transfer should be removed from endpoint
186
+ void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr) {
187
+
188
+ UNUSED (rhport);
189
+ UNUSED (ep_addr);
190
+ return ;
191
+ }
192
+
193
+ // clear stall, data toggle is also reset to DATA0
194
+ // This API never calls with control endpoints, since it is auto cleared when
195
+ // receiving setup packet
196
+ void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr) {
197
+
198
+ UNUSED (rhport);
199
+ UNUSED (ep_addr);
200
+ return ;
201
+ }
202
+ }
0 commit comments