forked from adafruit/circuitpython
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathusb.c
More file actions
235 lines (199 loc) · 6 KB
/
Copy pathusb.c
File metadata and controls
235 lines (199 loc) · 6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
// This file is part of the CircuitPython project: https://circuitpython.org
//
// SPDX-FileCopyrightText: Copyright (c) 2018 hathach for Adafruit Industries
//
// SPDX-License-Identifier: MIT
#include "py/objstr.h"
#include "supervisor/background_callback.h"
#include "supervisor/linker.h"
#include "supervisor/shared/tick.h"
#include "supervisor/usb.h"
#include "shared/readline/readline.h"
#if CIRCUITPY_STATUS_BAR
#include "supervisor/shared/status_bar.h"
#endif
#if CIRCUITPY_STORAGE
#include "shared-module/storage/__init__.h"
#endif
#if CIRCUITPY_USB_DEVICE
#include "shared-bindings/supervisor/__init__.h"
#if CIRCUITPY_USB_CDC
#include "shared-module/usb_cdc/__init__.h"
#endif
#if CIRCUITPY_USB_HID
#include "shared-module/usb_hid/__init__.h"
#endif
#if CIRCUITPY_USB_MIDI
#include "shared-module/usb_midi/__init__.h"
#endif
#if CIRCUITPY_USB_VIDEO
#include "shared-module/usb_video/__init__.h"
#endif
#endif
#include "tusb.h"
#if CFG_TUSB_OS == OPT_OS_ZEPHYR
#include <zephyr/kernel.h>
int CFG_TUSB_DEBUG_PRINTF(const char *format, ...) {
va_list args;
va_start(args, format);
printk(format, args);
va_end(args);
return 0;
}
#ifdef CFG_TUSB_DEBUG
#define USBD_STACK_SIZE (5 * CONFIG_IDLE_STACK_SIZE)
#else
#define USBD_STACK_SIZE (5 * CONFIG_IDLE_STACK_SIZE / 2)
#endif
struct k_thread tinyusb_thread_data;
K_THREAD_STACK_DEFINE(tinyusb_thread_stack, USBD_STACK_SIZE);
k_tid_t _tinyusb_tid;
// USB Device Driver task
// This top level thread process all usb events and invoke callbacks
static void tinyusb_thread(void *unused0, void *unused1, void *unused2) {
(void)unused0;
(void)unused1;
(void)unused2;
// RTOS forever loop
while (1) {
// tinyusb device task
if (tusb_inited()) {
tud_task();
tud_cdc_write_flush();
} else {
k_sleep(K_MSEC(1000));
}
}
}
#endif
bool usb_enabled(void) {
return tusb_inited();
}
MP_WEAK void post_usb_init(void) {
}
void usb_init(void) {
#if CIRCUITPY_USB_DEVICE
usb_identification_t defaults;
usb_identification_t *identification;
#if CIRCUITPY_USB_IDENTIFICATION
if (custom_usb_identification != NULL) {
identification = custom_usb_identification;
} else {
#endif
// This compiles to less code than using a struct initializer.
defaults.vid = USB_VID;
defaults.pid = USB_PID;
strcpy(defaults.manufacturer_name, USB_MANUFACTURER);
strcpy(defaults.product_name, USB_PRODUCT);
identification = &defaults;
// This memory only needs to be live through the end of usb_build_descriptors.
#if CIRCUITPY_USB_IDENTIFICATION
}
#endif
if (!usb_build_descriptors(identification)) {
return;
}
init_usb_hardware();
#if CIRCUITPY_USB_HID
usb_hid_build_report_descriptor();
#endif
// Only init device. Host gets inited by the `usb_host` module common-hal.
tud_init(TUD_OPT_RHPORT);
#endif
post_usb_init();
#if MICROPY_KBD_EXCEPTION && CIRCUITPY_USB_DEVICE && CIRCUITPY_USB_CDC
// Set Ctrl+C as wanted char, tud_cdc_rx_wanted_cb() usb_callback will be invoked when Ctrl+C is received
// This usb_callback always got invoked regardless of mp_interrupt_char value since we only set it once here
// Don't watch for ctrl-C if there is no REPL.
if (usb_cdc_console_enabled()) {
// Console will always be itf 0.
tud_cdc_set_wanted_char(CHAR_CTRL_C);
}
#endif
#if CFG_TUSB_OS == OPT_OS_ZEPHYR
_tinyusb_tid = k_thread_create(&tinyusb_thread_data, tinyusb_thread_stack,
K_THREAD_STACK_SIZEOF(tinyusb_thread_stack),
tinyusb_thread,
NULL, NULL, NULL,
CONFIG_MAIN_THREAD_PRIORITY - 1, 0, K_NO_WAIT);
k_thread_name_set(_tinyusb_tid, "tinyusb");
#endif
}
// Set up USB defaults before any USB changes are made in boot.py
void usb_set_defaults(void) {
#if CIRCUITPY_USB_DEVICE
#if CIRCUITPY_STORAGE && CIRCUITPY_USB_MSC
storage_usb_set_defaults();
#endif
#if CIRCUITPY_USB_CDC
usb_cdc_set_defaults();
#endif
#if CIRCUITPY_USB_HID
usb_hid_set_defaults();
#endif
#if CIRCUITPY_USB_MIDI
usb_midi_set_defaults();
#endif
#endif
};
// Call this when ready to run code.py or a REPL, and a VM has been started.
void usb_setup_with_vm(void) {
#if CIRCUITPY_USB_DEVICE
#if CIRCUITPY_USB_HID
usb_hid_setup_devices();
#endif
#if CIRCUITPY_USB_MIDI
usb_midi_setup_ports();
#endif
#endif
}
void usb_background(void) {
if (usb_enabled()) {
#if CFG_TUSB_OS == OPT_OS_NONE || CFG_TUSB_OS == OPT_OS_PICO
tud_task();
#if CIRCUITPY_USB_HOST || CIRCUITPY_MAX3421E
tuh_task();
#endif
#elif CFG_TUSB_OS == OPT_OS_FREERTOS
// Yield to FreeRTOS in case TinyUSB runs in a separate task. Don't use
// port_yield() because it has a longer delay.
vTaskDelay(0);
#endif
// No need to flush if there's no REPL.
#if CIRCUITPY_USB_DEVICE && CIRCUITPY_USB_CDC
if (usb_cdc_console_enabled()) {
// Console will always be itf 0.
tud_cdc_write_flush();
}
#endif
#if CIRCUITPY_USB_DEVICE && CIRCUITPY_USB_VIDEO
usb_video_task();
#endif
}
}
uint32_t tusb_time_millis_api(void) {
return supervisor_ticks_ms32();
}
static background_callback_t usb_callback;
static void usb_background_do(void *unused) {
usb_background();
}
void PLACE_IN_ITCM(usb_background_schedule)(void) {
background_callback_add(&usb_callback, usb_background_do, NULL);
}
void PLACE_IN_ITCM(usb_irq_handler)(int instance) {
#if CFG_TUSB_MCU != OPT_MCU_RP2040
#if CIRCUITPY_USB_DEVICE
// For rp2040, IRQ handler is already installed and invoked automatically
if (instance == CIRCUITPY_USB_DEVICE_INSTANCE) {
tud_int_handler(instance);
}
#endif
#if CIRCUITPY_USB_HOST
if (instance == CIRCUITPY_USB_HOST_INSTANCE) {
tuh_int_handler(instance);
}
#endif
#endif
usb_background_schedule();
}