Skip to content

Commit 4a7e129

Browse files
committed
wip: latent usb device enabling/disabling
1 parent 2a58b66 commit 4a7e129

File tree

16 files changed

+261
-64
lines changed

16 files changed

+261
-64
lines changed

locale/circuitpython.pot

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -600,6 +600,14 @@ msgstr ""
600600
msgid "Can't set CCCD on local Characteristic"
601601
msgstr ""
602602

603+
#: shared-bindings/usb_cdc/__init__.c shared-bindings/usb_midi/__init__.c
604+
msgid "Cannot change USB devices now"
605+
msgstr ""
606+
607+
#: shared-bindings/storage/__init__.c
608+
msgid "Cannot change usb devices now"
609+
msgstr ""
610+
603611
#: shared-bindings/_bleio/Adapter.c
604612
msgid "Cannot create a new Adapter; use _bleio.adapter;"
605613
msgstr ""
@@ -1080,10 +1088,6 @@ msgstr ""
10801088
msgid "I2SOut not available"
10811089
msgstr ""
10821090

1083-
#: ports/esp32s2/common-hal/alarm/pin/__init__.c
1084-
msgid "IOs 0, 2 & 4 do not support internal pullup in sleep"
1085-
msgstr ""
1086-
10871091
#: shared-bindings/aesio/aes.c
10881092
#, c-format
10891093
msgid "IV must be %d bytes long"
@@ -3249,10 +3253,6 @@ msgstr ""
32493253
msgid "invalid syntax for number"
32503254
msgstr ""
32513255

3252-
#: ports/esp32s2/common-hal/alarm/pin/__init__.c
3253-
msgid "io must be rtc io"
3254-
msgstr ""
3255-
32563256
#: py/objtype.c
32573257
msgid "issubclass() arg 1 must be a class"
32583258
msgstr ""
@@ -3712,6 +3712,7 @@ msgstr ""
37123712
#: ports/esp32s2/boards/adafruit_funhouse/mpconfigboard.h
37133713
#: ports/esp32s2/boards/adafruit_magtag_2.9_grayscale/mpconfigboard.h
37143714
#: ports/esp32s2/boards/adafruit_metro_esp32s2/mpconfigboard.h
3715+
#: ports/esp32s2/boards/artisense_rd00/mpconfigboard.h
37153716
#: ports/esp32s2/boards/electroniccats_bastwifi/mpconfigboard.h
37163717
#: ports/esp32s2/boards/espressif_kaluga_1/mpconfigboard.h
37173718
#: ports/esp32s2/boards/espressif_saola_1_wroom/mpconfigboard.h
@@ -4010,10 +4011,6 @@ msgstr ""
40104011
msgid "trapz is defined for 1D arrays of equal length"
40114012
msgstr ""
40124013

4013-
#: ports/esp32s2/common-hal/alarm/pin/__init__.c
4014-
msgid "trigger level must be 0 or 1"
4015-
msgstr ""
4016-
40174014
#: py/obj.c
40184015
msgid "tuple/list has wrong length"
40194016
msgstr ""
@@ -4148,10 +4145,6 @@ msgstr ""
41484145
msgid "value_count must be > 0"
41494146
msgstr ""
41504147

4151-
#: ports/esp32s2/common-hal/alarm/pin/__init__.c
4152-
msgid "wakeup conflict"
4153-
msgstr ""
4154-
41554148
#: ports/esp32s2/common-hal/watchdog/WatchDogTimer.c
41564149
msgid "watchdog not initialized"
41574150
msgstr ""

main.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,10 +94,18 @@
9494
#include "shared-module/network/__init__.h"
9595
#endif
9696

97+
#if CIRCUITPY_STORAGE
98+
#include "shared-module/storage/__init__.h"
99+
#endif
100+
97101
#if CIRCUITPY_USB_CDC
98102
#include "shared-module/usb_cdc/__init__.h"
99103
#endif
100104

105+
#if CIRCUITPY_USB_MIDI
106+
#include "shared-module/usb_midi/__init__.h"
107+
#endif
108+
101109
#if CIRCUITPY_WIFI
102110
#include "shared-bindings/wifi/__init__.h"
103111
#endif
@@ -169,6 +177,20 @@ STATIC void start_mp(supervisor_allocation* heap) {
169177
#if CIRCUITPY_NETWORK
170178
network_module_init();
171179
#endif
180+
181+
// Do before boot.py.
182+
183+
#if CIRCUITPY_STORAGE
184+
storage_init();
185+
#endif
186+
187+
#if CIRCUITPY_USB_CDC
188+
usb_cdc_init();
189+
#endif
190+
191+
#if CIRCUITPY_USB_MIDI
192+
usb_midi_init();
193+
#endif
172194
}
173195

174196
STATIC void stop_mp(void) {

py/circuitpy_mpconfig.mk

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -325,10 +325,8 @@ CFLAGS += -DCIRCUITPY_TOUCHIO=$(CIRCUITPY_TOUCHIO)
325325
CIRCUITPY_UHEAP ?= 0
326326
CFLAGS += -DCIRCUITPY_UHEAP=$(CIRCUITPY_UHEAP)
327327

328-
# Disable by default for now, until we have dynamic enabling.
329-
CIRCUITPY_USB_CDC ?= 0
330328
# Secondary CDC is usually available if there are at least 8 endpoints.
331-
#CIRCUITPY_USB_CDC ?= $(shell expr $(USB_NUM_EP) '>=' 8)
329+
CIRCUITPY_USB_CDC ?= $(shell expr $(USB_NUM_EP) '>=' 8)
332330
CFLAGS += -DCIRCUITPY_USB_CDC=$(CIRCUITPY_USB_CDC)
333331

334332
CIRCUITPY_USB_HID ?= 1

shared-bindings/storage/__init__.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,21 @@ mp_obj_t storage_erase_filesystem(void) {
158158
}
159159
MP_DEFINE_CONST_FUN_OBJ_0(storage_erase_filesystem_obj, storage_erase_filesystem);
160160

161+
//| def enable_usb(enabled: True) -> None:
162+
//| """Enable or disable presenting ``CIRCUITPY`` as a USB mass storage device.
163+
//| By default, ``CIRCUITPY`` is visible.
164+
//| Use ``storage.enable_usb(False)`` to hide CIRCUITPY from the host computer.
165+
//| Can be changed in ``boot.py``, before USB is connected."""
166+
//| ...
167+
//|
168+
STATIC mp_obj_t storage_enable_usb(mp_obj_t enabled) {
169+
if (!common_hal_storage_enable_usb(mp_obj_is_true(enabled))) {
170+
mp_raise_RuntimeError(translate("Cannot change usb devices now"));
171+
}
172+
return mp_const_none;
173+
}
174+
MP_DEFINE_CONST_FUN_OBJ_1(storage_enable_usb_obj, storage_enable_usb);
175+
161176
STATIC const mp_rom_map_elem_t storage_module_globals_table[] = {
162177
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_storage) },
163178

@@ -166,6 +181,7 @@ STATIC const mp_rom_map_elem_t storage_module_globals_table[] = {
166181
{ MP_ROM_QSTR(MP_QSTR_remount), MP_ROM_PTR(&storage_remount_obj) },
167182
{ MP_ROM_QSTR(MP_QSTR_getmount), MP_ROM_PTR(&storage_getmount_obj) },
168183
{ MP_ROM_QSTR(MP_QSTR_erase_filesystem), MP_ROM_PTR(&storage_erase_filesystem_obj) },
184+
{ MP_ROM_QSTR(MP_QSTR_enable_usb), MP_ROM_PTR(&storage_enable_usb_obj) },
169185

170186
//| class VfsFat:
171187
//| def __init__(self, block_device: str) -> None:

shared-bindings/storage/__init__.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,5 +36,6 @@ void common_hal_storage_umount_object(mp_obj_t vfs_obj);
3636
void common_hal_storage_remount(const char *path, bool readonly, bool disable_concurrent_write_protection);
3737
mp_obj_t common_hal_storage_getmount(const char *path);
3838
void common_hal_storage_erase_filesystem(void);
39+
bool common_hal_storage_enable_usb(bool enabled);
3940

4041
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_STORAGE___INIT___H

shared-bindings/usb_cdc/__init__.c

Lines changed: 61 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -36,22 +36,73 @@
3636

3737
//| """USB CDC Serial streams
3838
//|
39-
//| The `usb_cdc` module allows access to USB CDC (serial) communications."""
39+
//| The `usb_cdc` module allows access to USB CDC (serial) communications.
4040
//|
41-
//| serials: Tuple[Serial, ...]
42-
//| """Tuple of all CDC streams. Each item is a `Serial`.
43-
//| ``serials[0]`` is the USB REPL connection.
44-
//| ``serials[1]`` is a second USB serial connection, unconnected to the REPL.
41+
//| On Windows, each `Serial` is visible as a separate COM port. The ports will often
42+
//| be assigned consecutively, REPL first, but this is not always true.
43+
//|
44+
//| On Linux, the ports are typically ``/dev/ttyACM0`` and ``/dev/ttyACM1``. The REPL
45+
//| is usually first.
46+
//|
47+
//| On MacOS, the ports are typically ``/dev/cu.usbmodem<something>``. The something
48+
//| varies based on the USB bus and port used. The REPL is usually first.
4549
//| """
4650
//|
51+
//| repl: Optional[Serial]
52+
//| """The `Serial` object that can be used to communicate over the REPL serial
53+
//| channel. ``None`` if disabled.
54+
//|
55+
//| Note that`sys.stdin` and `sys.stdout` are also connected to the REPL, though
56+
//| they are text-based streams, and the `repl` object is a binary stream."""
57+
//|
58+
//| data: Optional[Serial]
59+
//| """A `Serial` object that can be used to send and receive binary data to and from
60+
//| the host.
61+
//| Note that `data` is *disabled* by default."""
62+
63+
64+
65+
66+
//| def enable_repl(enabled:bool) -> None:
67+
//| """Enable or disable the `repl` USB serial connection. The REPL
68+
//| is enabled by default.
69+
//| Can be changed in ``boot.py``, before USB is connected."""
70+
//| ...
71+
//|
72+
STATIC mp_obj_t usb_cdc_enable_repl(mp_obj_t enabled) {
73+
if (!common_hal_usb_cdc_enable_repl(mp_obj_is_true(enabled))) {
74+
mp_raise_RuntimeError(translate("Cannot change USB devices now"));
75+
}
76+
return mp_const_none;
77+
}
78+
MP_DEFINE_CONST_FUN_OBJ_1(usb_cdc_enable_repl_obj, usb_cdc_enable_repl);
79+
80+
//| def enable_data(enabled: bool) -> None:
81+
//| """Enable or disable the `data` USB serial connection;n
82+
//| *disabled* by default.
83+
//| Can be changed in ``boot.py``, before USB is connected."""
84+
//| ...
85+
//|
86+
STATIC mp_obj_t usb_cdc_enable_data(mp_obj_t enabled) {
87+
if (!common_hal_usb_cdc_enable_data(mp_obj_is_true(enabled))) {
88+
mp_raise_RuntimeError(translate("Cannot change USB devices now"));
89+
}
90+
return mp_const_none;
91+
}
92+
MP_DEFINE_CONST_FUN_OBJ_1(usb_cdc_enable_data_obj, usb_cdc_enable_data);
4793

48-
static const mp_map_elem_t usb_cdc_module_globals_table[] = {
49-
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_usb_cdc) },
50-
{ MP_ROM_QSTR(MP_QSTR_Serial), MP_OBJ_FROM_PTR(&usb_cdc_serial_type) },
51-
{ MP_ROM_QSTR(MP_QSTR_serials), MP_OBJ_FROM_PTR(&usb_cdc_serials_tuple) },
94+
// The usb_cdc module dict is mutable so that .repl and .data may
95+
// be set to a Serial or to None depending on whether they are enabled or not.
96+
static mp_map_elem_t usb_cdc_module_globals_table[] = {
97+
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_usb_cdc) },
98+
{ MP_ROM_QSTR(MP_QSTR_Serial), MP_OBJ_FROM_PTR(&usb_cdc_serial_type) },
99+
{ MP_ROM_QSTR(MP_QSTR_repl), mp_const_none },
100+
{ MP_ROM_QSTR(MP_QSTR_data), mp_const_none },
101+
{ MP_ROM_QSTR(MP_QSTR_enable_repl), MP_OBJ_FROM_PTR(&usb_cdc_enable_repl_obj) },
102+
{ MP_ROM_QSTR(MP_QSTR_enable_data), MP_OBJ_FROM_PTR(&usb_cdc_enable_data_obj) },
52103
};
53104

54-
static MP_DEFINE_CONST_DICT(usb_cdc_module_globals, usb_cdc_module_globals_table);
105+
static MP_DEFINE_MUTABLE_DICT(usb_cdc_module_globals, usb_cdc_module_globals_table);
55106

56107
const mp_obj_module_t usb_cdc_module = {
57108
.base = { &mp_type_module },

shared-bindings/usb_cdc/__init__.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,7 @@
2929

3030
#include "shared-module/usb_cdc/__init__.h"
3131

32+
bool common_hal_usb_cdc_enable_repl(bool enabled);
33+
bool common_hal_usb_cdc_enable_data(bool enabled);
34+
3235
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_USB_CDC___INIT___H

shared-bindings/usb_midi/__init__.c

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,25 @@
4343
//| """Tuple of all MIDI ports. Each item is ether `PortIn` or `PortOut`."""
4444
//|
4545

46+
//| def enable(enabled: bool) -> None:
47+
//| """Enable or disable USB MIDI device. By default, MIDI is enabled.
48+
//| Can be changed in ``boot.py``, before USB is connected."""
49+
//| ...
50+
//|
51+
STATIC mp_obj_t usb_midi_enable(mp_obj_t enabled) {
52+
if (!common_hal_usb_midi_enable(mp_obj_is_true(enabled))) {
53+
mp_raise_RuntimeError(translate("Cannot change USB devices now"));
54+
}
55+
return mp_const_none;
56+
}
57+
MP_DEFINE_CONST_FUN_OBJ_1(usb_midi_enable_obj, usb_midi_enable);
58+
4659
mp_map_elem_t usb_midi_module_globals_table[] = {
4760
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_usb_midi) },
48-
{ MP_ROM_QSTR(MP_QSTR_ports), mp_const_empty_tuple },
61+
{ MP_ROM_QSTR(MP_QSTR_enable), MP_OBJ_FROM_PTR(&usb_midi_enable_obj) },
62+
{ MP_ROM_QSTR(MP_QSTR_ports), mp_const_empty_tuple },
4963
{ MP_ROM_QSTR(MP_QSTR_PortIn), MP_OBJ_FROM_PTR(&usb_midi_portin_type) },
50-
{ MP_ROM_QSTR(MP_QSTR_PortOut), MP_OBJ_FROM_PTR(&usb_midi_portout_type) },
64+
{ MP_ROM_QSTR(MP_QSTR_PortOut), MP_OBJ_FROM_PTR(&usb_midi_portout_type) },
5165
};
5266

5367
// This isn't const so we can set ports dynamically.

shared-bindings/usb_midi/__init__.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,6 @@
3131

3232
extern mp_obj_dict_t usb_midi_module_globals;
3333

34+
bool common_hal_usb_midi_enable(bool enabled);
35+
3436
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_USB_MIDI___INIT___H

shared-module/storage/__init__.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@
3939
#include "supervisor/filesystem.h"
4040
#include "supervisor/flash.h"
4141
#include "supervisor/usb.h"
42+
#include "tusb.h"
43+
44+
// Is the MSC device enabled?
45+
static bool usb_storage_enabled;
4246

4347
STATIC mp_obj_t mp_vfs_proxy_call(mp_vfs_mount_t *vfs, qstr meth_name, size_t n_args, const mp_obj_t *args) {
4448
if (vfs == MP_VFS_NONE) {
@@ -57,6 +61,10 @@ STATIC mp_obj_t mp_vfs_proxy_call(mp_vfs_mount_t *vfs, qstr meth_name, size_t n_
5761
return mp_call_method_n_kw(n_args, 0, meth);
5862
}
5963

64+
void storage_init(void) {
65+
usb_storage_enabled = true;
66+
}
67+
6068
void common_hal_storage_mount(mp_obj_t vfs_obj, const char *mount_path, bool readonly) {
6169
// create new object
6270
mp_vfs_mount_t *vfs = m_new_obj(mp_vfs_mount_t);
@@ -166,3 +174,12 @@ void common_hal_storage_erase_filesystem(void) {
166174
common_hal_mcu_reset();
167175
// We won't actually get here, since we're resetting.
168176
}
177+
178+
bool common_hal_storage_enable_usb(bool enabled) {
179+
// We can't change the descriptors once we're connected.
180+
if (!tud_connected()) {
181+
return false;
182+
}
183+
usb_storage_enabled = enabled;
184+
return true;
185+
}

0 commit comments

Comments
 (0)