summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--extmod/vfs_fat.h4
-rw-r--r--extmod/vfs_fat_diskio.c4
-rw-r--r--main.c8
-rw-r--r--ports/atmel-samd/Makefile11
m---------ports/atmel-samd/asf40
-rw-r--r--ports/atmel-samd/asf4_conf/samd21/hpl_usb_config.h16
-rw-r--r--ports/atmel-samd/asf4_conf/samd51/hpl_usb_config.h4
-rw-r--r--ports/atmel-samd/boards/arduino_zero/mpconfigboard.mk2
-rw-r--r--ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.mk2
-rw-r--r--ports/atmel-samd/boards/feather_m0_adalogger/mpconfigboard.mk2
-rw-r--r--ports/atmel-samd/boards/feather_m0_basic/mpconfigboard.mk2
-rw-r--r--ports/atmel-samd/boards/feather_m0_express/mpconfigboard.mk2
-rw-r--r--ports/atmel-samd/boards/gemma_m0/mpconfigboard.mk2
-rw-r--r--ports/atmel-samd/boards/metro_m0_express/mpconfigboard.mk2
-rw-r--r--ports/atmel-samd/boards/metro_m4_express/mpconfigboard.mk2
-rw-r--r--ports/atmel-samd/boards/trinket_m0/mpconfigboard.mk2
-rw-r--r--ports/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.mk2
-rw-r--r--ports/atmel-samd/common-hal/storage/__init__.c2
-rw-r--r--ports/atmel-samd/flash_api.c8
-rw-r--r--ports/atmel-samd/flash_api.h2
-rw-r--r--ports/atmel-samd/supervisor/filesystem.c4
-rw-r--r--ports/atmel-samd/supervisor/serial.c40
-rw-r--r--ports/atmel-samd/tools/autogen_usb_descriptor.h36
-rw-r--r--ports/atmel-samd/tools/gen_usb_descriptor.py150
-rw-r--r--ports/atmel-samd/usb.c12
-rw-r--r--ports/atmel-samd/usb_mass_storage.c33
-rw-r--r--ports/atmel-samd/usb_mass_storage.h1
-rw-r--r--supervisor/filesystem.h2
-rw-r--r--supervisor/stub/filesystem.c2
-rw-r--r--tools/usb_descriptor/cdc.py53
-rw-r--r--tools/usb_descriptor/core.py187
31 files changed, 541 insertions, 58 deletions
diff --git a/extmod/vfs_fat.h b/extmod/vfs_fat.h
index 5de1a237b..273ddc84e 100644
--- a/extmod/vfs_fat.h
+++ b/extmod/vfs_fat.h
@@ -35,8 +35,8 @@
#define FSUSER_NATIVE (0x0001) // readblocks[2]/writeblocks[2] contain native func
#define FSUSER_FREE_OBJ (0x0002) // fs_user_mount_t obj should be freed on umount
#define FSUSER_HAVE_IOCTL (0x0004) // new protocol with ioctl
-// Device is write-able over USB and read-only to MicroPython.
-#define FSUSER_USB_WRITEABLE (0x0008)
+// Device is writable over USB and read-only to MicroPython.
+#define FSUSER_USB_WRITABLE (0x0008)
typedef struct _fs_user_mount_t {
mp_obj_base_t base;
diff --git a/extmod/vfs_fat_diskio.c b/extmod/vfs_fat_diskio.c
index ad769001d..3b9d86037 100644
--- a/extmod/vfs_fat_diskio.c
+++ b/extmod/vfs_fat_diskio.c
@@ -98,9 +98,9 @@ DSTATUS disk_status (
}
// This is used to determine the writeability of the disk from MicroPython.
- // So, if its USB writeable we make it read-only from MicroPython.
+ // So, if its USB writable we make it read-only from MicroPython.
if (vfs->writeblocks[0] == MP_OBJ_NULL ||
- (vfs->flags & FSUSER_USB_WRITEABLE) != 0) {
+ (vfs->flags & FSUSER_USB_WRITABLE) != 0) {
return STA_PROTECT;
} else {
return 0;
diff --git a/main.c b/main.c
index a2e4b9f72..d5680d05d 100644
--- a/main.c
+++ b/main.c
@@ -234,8 +234,8 @@ int __attribute__((used)) main(void) {
autoreload_enable();
// By default our internal flash is readonly to local python code and
- // writeable over USB. Set it here so that boot.py can change it.
- filesystem_default_writeable(false);
+ // writable over USB. Set it here so that boot.py can change it.
+ filesystem_writable_by_python(false);
// If not in safe mode, run boot before initing USB and capture output in a
// file.
@@ -244,12 +244,12 @@ int __attribute__((used)) main(void) {
#ifdef CIRCUITPY_BOOT_OUTPUT_FILE
// Since USB isn't up yet we can cheat and let ourselves write the boot
// output file.
- filesystem_default_writeable(true);
+ filesystem_writable_by_python(true);
FIL file_pointer;
boot_output_file = &file_pointer;
f_open(&((fs_user_mount_t *) MP_STATE_VM(vfs_mount_table)->obj)->fatfs,
boot_output_file, CIRCUITPY_BOOT_OUTPUT_FILE, FA_WRITE | FA_CREATE_ALWAYS);
- filesystem_default_writeable(false);
+ filesystem_writable_by_python(false);
#endif
// TODO(tannewt): Re-add support for flashing boot error output.
diff --git a/ports/atmel-samd/Makefile b/ports/atmel-samd/Makefile
index ef168dbc9..ef4012802 100644
--- a/ports/atmel-samd/Makefile
+++ b/ports/atmel-samd/Makefile
@@ -73,8 +73,6 @@ BASE_CFLAGS = \
-Wcast-align \
-Wno-error=lto-type-mismatch \
-D__$(CHIP_VARIANT)__ \
- -DCONF_USB_COMPOSITE_IDPRODUCT=$(USB_PID) \
- -DCONF_USB_COMPOSITE_IDVENDER=$(USB_VID) \
-ffunction-sections \
-fdata-sections \
-fshort-enums \
@@ -233,6 +231,7 @@ SRC_C = \
lib/utils/sys_stdio_mphal.c \
lib/libc/string0.c \
lib/mp-readline/readline.c \
+ $(BUILD)/autogen_usb_descriptor.c \
# freetouch/adafruit_ptc.c
# Choose which flash filesystem impl to use.
@@ -359,6 +358,14 @@ $(BUILD)/firmware.uf2: $(BUILD)/firmware.bin
$(ECHO) "Create $@"
python2 $(TOP)/tools/uf2/utils/uf2conv.py -b $(BOOTLOADER_SIZE) -c -o $@ $^
+$(BUILD)/autogen_usb_descriptor.c: tools/gen_usb_descriptor.py Makefile
+ python3 tools/gen_usb_descriptor.py \
+ --manufacturer $(USB_MANUFACTURER)\
+ --product $(USB_PRODUCT)\
+ --vid $(USB_VID)\
+ --pid $(USB_PID)\
+ $@
+
deploy: $(BUILD)/firmware.bin
$(ECHO) "Writing $< to the board"
$(BOSSAC) -u $<
diff --git a/ports/atmel-samd/asf4 b/ports/atmel-samd/asf4
-Subproject e1d02fde5d23a704d33d74e18fcf624eb56132c
+Subproject 1ca9e1f86921d99f0fbc907698f864a60caf675
diff --git a/ports/atmel-samd/asf4_conf/samd21/hpl_usb_config.h b/ports/atmel-samd/asf4_conf/samd21/hpl_usb_config.h
index 0a895dbf8..2108077bc 100644
--- a/ports/atmel-samd/asf4_conf/samd21/hpl_usb_config.h
+++ b/ports/atmel-samd/asf4_conf/samd21/hpl_usb_config.h
@@ -39,7 +39,7 @@
// <CONF_USB_D_N_EP_MAX"> Max possible (by "Max Endpoint Number" config)
// <id> usbd_num_ep_sp
#ifndef CONF_USB_D_NUM_EP_SP
-#define CONF_USB_D_NUM_EP_SP CONF_USB_D_EP_N_MAX
+#define CONF_USB_D_NUM_EP_SP CONF_USB_D_N_EP_MAX
#endif
// </h>
@@ -118,7 +118,7 @@
// <1024=> Cached by 1024 bytes buffer (interrupt or isochronous EP)
// <id> usb_ep1_I_CACHE
#ifndef CONF_USB_EP1_I_CACHE
-#define CONF_USB_EP1_I_CACHE 64
+#define CONF_USB_EP1_I_CACHE 0
#endif
// </h>
@@ -176,7 +176,7 @@
// <1024=> Cached by 1024 bytes buffer (interrupt or isochronous EP)
// <id> usb_arch_ep3_cache
#ifndef CONF_USB_EP3_CACHE
-#define CONF_USB_EP3_CACHE 64
+#define CONF_USB_EP3_CACHE 0
#endif
// <o> Cache buffer size for EP3 IN
@@ -194,7 +194,7 @@
// <1024=> Cached by 1024 bytes buffer (interrupt or isochronous EP)
// <id> usb_ep3_I_CACHE
#ifndef CONF_USB_EP3_I_CACHE
-#define CONF_USB_EP3_I_CACHE 0
+#define CONF_USB_EP3_I_CACHE 64
#endif
// </h>
@@ -252,7 +252,7 @@
// <1024=> Cached by 1024 bytes buffer (interrupt or isochronous EP)
// <id> usb_arch_ep5_cache
#ifndef CONF_USB_EP5_CACHE
-#define CONF_USB_EP5_CACHE 64
+#define CONF_USB_EP5_CACHE 0
#endif
// <o> Cache buffer size for EP5 IN
@@ -290,7 +290,7 @@
// <1024=> Cached by 1024 bytes buffer (interrupt or isochronous EP)
// <id> usb_arch_ep6_cache
#ifndef CONF_USB_EP6_CACHE
-#define CONF_USB_EP6_CACHE 64
+#define CONF_USB_EP6_CACHE 0
#endif
// <o> Cache buffer size for EP6 IN
@@ -308,7 +308,7 @@
// <1024=> Cached by 1024 bytes buffer (interrupt or isochronous EP)
// <id> usb_ep6_I_CACHE
#ifndef CONF_USB_EP6_I_CACHE
-#define CONF_USB_EP6_I_CACHE 64
+#define CONF_USB_EP6_I_CACHE 0
#endif
// </h>
@@ -328,7 +328,7 @@
// <1024=> Cached by 1024 bytes buffer (interrupt or isochronous EP)
// <id> usb_arch_ep7_cache
#ifndef CONF_USB_EP7_CACHE
-#define CONF_USB_EP7_CACHE 64
+#define CONF_USB_EP7_CACHE 0
#endif
// <o> Cache buffer size for EP7 IN
diff --git a/ports/atmel-samd/asf4_conf/samd51/hpl_usb_config.h b/ports/atmel-samd/asf4_conf/samd51/hpl_usb_config.h
index 0f8155ecb..92dfcaa9b 100644
--- a/ports/atmel-samd/asf4_conf/samd51/hpl_usb_config.h
+++ b/ports/atmel-samd/asf4_conf/samd51/hpl_usb_config.h
@@ -120,7 +120,7 @@
// <1024=> Cached by 1024 bytes buffer (interrupt or isochronous EP)
// <id> usb_ep1_I_CACHE
#ifndef CONF_USB_EP1_I_CACHE
-#define CONF_USB_EP1_I_CACHE 64
+#define CONF_USB_EP1_I_CACHE 0
#endif
// </h>
@@ -158,7 +158,7 @@
// <1024=> Cached by 1024 bytes buffer (interrupt or isochronous EP)
// <id> usb_ep2_I_CACHE
#ifndef CONF_USB_EP2_I_CACHE
-#define CONF_USB_EP2_I_CACHE 0
+#define CONF_USB_EP2_I_CACHE 64
#endif
// </h>
diff --git a/ports/atmel-samd/boards/arduino_zero/mpconfigboard.mk b/ports/atmel-samd/boards/arduino_zero/mpconfigboard.mk
index 345c9a2a5..b24cc9c64 100644
--- a/ports/atmel-samd/boards/arduino_zero/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/arduino_zero/mpconfigboard.mk
@@ -1,6 +1,8 @@
LD_FILE = boards/samd21x18-bootloader.ld
USB_VID = 0x2341
USB_PID = 0x824D
+USB_PRODUCT = "Arduino Zero"
+USB_MANUFACTURER = "Arduino"
INTERNAL_FLASH_FILESYSTEM = 1
diff --git a/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.mk b/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.mk
index b2922fb06..1831f9337 100644
--- a/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.mk
@@ -1,6 +1,8 @@
LD_FILE = boards/samd21x18-bootloader-crystalless.ld
USB_VID = 0x239A
USB_PID = 0x8019
+USB_PRODUCT = "CircuitPlayground Express"
+USB_MANUFACTURER = "Adafruit Industries LLC"
#SPI_FLASH_FILESYSTEM = 1
INTERNAL_FLASH_FILESYSTEM = 1
diff --git a/ports/atmel-samd/boards/feather_m0_adalogger/mpconfigboard.mk b/ports/atmel-samd/boards/feather_m0_adalogger/mpconfigboard.mk
index 7580ed66f..debd3d775 100644
--- a/ports/atmel-samd/boards/feather_m0_adalogger/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/feather_m0_adalogger/mpconfigboard.mk
@@ -1,6 +1,8 @@
LD_FILE = boards/samd21x18-bootloader.ld
USB_VID = 0x239A
USB_PID = 0x8015
+USB_PRODUCT = "Feather M0 Adalogger"
+USB_MANUFACTURER = "Adafruit Industries LLC"
INTERNAL_FLASH_FILESYSTEM = 1
diff --git a/ports/atmel-samd/boards/feather_m0_basic/mpconfigboard.mk b/ports/atmel-samd/boards/feather_m0_basic/mpconfigboard.mk
index 7580ed66f..641611176 100644
--- a/ports/atmel-samd/boards/feather_m0_basic/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/feather_m0_basic/mpconfigboard.mk
@@ -1,6 +1,8 @@
LD_FILE = boards/samd21x18-bootloader.ld
USB_VID = 0x239A
USB_PID = 0x8015
+USB_PRODUCT = "Feather M0"
+USB_MANUFACTURER = "Adafruit Industries LLC"
INTERNAL_FLASH_FILESYSTEM = 1
diff --git a/ports/atmel-samd/boards/feather_m0_express/mpconfigboard.mk b/ports/atmel-samd/boards/feather_m0_express/mpconfigboard.mk
index b677f4e51..46c58d04a 100644
--- a/ports/atmel-samd/boards/feather_m0_express/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/feather_m0_express/mpconfigboard.mk
@@ -1,6 +1,8 @@
LD_FILE = boards/samd21x18-bootloader.ld
USB_VID = 0x239A
USB_PID = 0x801b
+USB_PRODUCT = "Feather M0 Express"
+USB_MANUFACTURER = "Adafruit Industries LLC"
#SPI_FLASH_FILESYSTEM = 1
INTERNAL_FLASH_FILESYSTEM = 1
diff --git a/ports/atmel-samd/boards/gemma_m0/mpconfigboard.mk b/ports/atmel-samd/boards/gemma_m0/mpconfigboard.mk
index de1c7c19a..a406e8f58 100644
--- a/ports/atmel-samd/boards/gemma_m0/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/gemma_m0/mpconfigboard.mk
@@ -1,6 +1,8 @@
LD_FILE = boards/samd21x18-bootloader.ld
USB_VID = 0x239A
USB_PID = 0x801D
+USB_PRODUCT = "Gemma M0"
+USB_MANUFACTURER = "Adafruit Industries LLC"
INTERNAL_FLASH_FILESYSTEM = 1
diff --git a/ports/atmel-samd/boards/metro_m0_express/mpconfigboard.mk b/ports/atmel-samd/boards/metro_m0_express/mpconfigboard.mk
index 2845e6bf2..7d63321af 100644
--- a/ports/atmel-samd/boards/metro_m0_express/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/metro_m0_express/mpconfigboard.mk
@@ -1,6 +1,8 @@
LD_FILE = boards/samd21x18-bootloader.ld
USB_VID = 0x239A
USB_PID = 0x8014
+USB_PRODUCT = "Metro M0 Express"
+USB_MANUFACTURER = "Adafruit Industries LLC"
#SPI_FLASH_FILESYSTEM = 1
INTERNAL_FLASH_FILESYSTEM = 1
diff --git a/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.mk b/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.mk
index d8ec94fdf..194116545 100644
--- a/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.mk
@@ -1,6 +1,8 @@
LD_FILE = boards/samd51x19-bootloader.ld
USB_VID = 0x239A
USB_PID = 0x8021
+USB_PRODUCT = "Metro M4 Express"
+USB_MANUFACTURER = "Adafruit Industries LLC"
#SPI_FLASH_FILESYSTEM = 1
INTERNAL_FLASH_FILESYSTEM = 1
diff --git a/ports/atmel-samd/boards/trinket_m0/mpconfigboard.mk b/ports/atmel-samd/boards/trinket_m0/mpconfigboard.mk
index 1e3da5332..43d07eb5f 100644
--- a/ports/atmel-samd/boards/trinket_m0/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/trinket_m0/mpconfigboard.mk
@@ -1,6 +1,8 @@
LD_FILE = boards/samd21x18-bootloader.ld
USB_VID = 0x239A
USB_PID = 0x801F
+USB_PRODUCT = "Trinket M0"
+USB_MANUFACTURER = "Adafruit Industries LLC"
INTERNAL_FLASH_FILESYSTEM = 1
diff --git a/ports/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.mk b/ports/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.mk
index b893d94e4..04dc9e401 100644
--- a/ports/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.mk
@@ -1,6 +1,8 @@
LD_FILE = boards/samd21x18-bootloader-external-flash-crystalless.ld
USB_VID = 0x239A
USB_PID = 0x801F
+USB_PRODUCT="Trinket M0 Haxpress"
+USB_MANUFACTURER="Radomir Dopieralski"
#SPI_FLASH_FILESYSTEM = 1
INTERNAL_FLASH_FILESYSTEM = 1
diff --git a/ports/atmel-samd/common-hal/storage/__init__.c b/ports/atmel-samd/common-hal/storage/__init__.c
index b7c4fa6dd..184184b8b 100644
--- a/ports/atmel-samd/common-hal/storage/__init__.c
+++ b/ports/atmel-samd/common-hal/storage/__init__.c
@@ -42,5 +42,5 @@ void common_hal_storage_remount(const char* mount_path, bool readonly) {
mp_raise_RuntimeError("Cannot remount '/' when USB is active.");
}
- flash_set_usb_writeable(readonly);
+ flash_set_usb_writable(readonly);
}
diff --git a/ports/atmel-samd/flash_api.c b/ports/atmel-samd/flash_api.c
index 7c032a2be..b8a212718 100644
--- a/ports/atmel-samd/flash_api.c
+++ b/ports/atmel-samd/flash_api.c
@@ -30,7 +30,7 @@
#define VFS_INDEX 0
-void flash_set_usb_writeable(bool usb_writeable) {
+void flash_set_usb_writable(bool usb_writable) {
mp_vfs_mount_t* current_mount = MP_STATE_VM(vfs_mount_table);
for (uint8_t i = 0; current_mount != NULL; i++) {
if (i == VFS_INDEX) {
@@ -43,9 +43,9 @@ void flash_set_usb_writeable(bool usb_writeable) {
}
fs_user_mount_t *vfs = (fs_user_mount_t *) current_mount->obj;
- if (usb_writeable) {
- vfs->flags |= FSUSER_USB_WRITEABLE;
+ if (usb_writable) {
+ vfs->flags |= FSUSER_USB_WRITABLE;
} else {
- vfs->flags &= ~FSUSER_USB_WRITEABLE;
+ vfs->flags &= ~FSUSER_USB_WRITABLE;
}
}
diff --git a/ports/atmel-samd/flash_api.h b/ports/atmel-samd/flash_api.h
index 5017891af..3e41f59a2 100644
--- a/ports/atmel-samd/flash_api.h
+++ b/ports/atmel-samd/flash_api.h
@@ -31,6 +31,6 @@
extern void flash_init_vfs(fs_user_mount_t *vfs);
extern void flash_flush(void);
-void flash_set_usb_writeable(bool usb_writeable);
+void flash_set_usb_writable(bool usb_writable);
#endif // MICROPY_INCLUDED_ATMEL_SAMD_FLASH_API_H
diff --git a/ports/atmel-samd/supervisor/filesystem.c b/ports/atmel-samd/supervisor/filesystem.c
index f189ed8b9..45dc5667b 100644
--- a/ports/atmel-samd/supervisor/filesystem.c
+++ b/ports/atmel-samd/supervisor/filesystem.c
@@ -85,8 +85,8 @@ void filesystem_flush(void) {
flash_flush();
}
-void filesystem_default_writeable(bool writeable) {
- flash_set_usb_writeable(writeable);
+void filesystem_writable_by_python(bool writable) {
+ flash_set_usb_writable(!writable);
}
bool filesystem_present(void) {
diff --git a/ports/atmel-samd/supervisor/serial.c b/ports/atmel-samd/supervisor/serial.c
index 67f06baa4..0410c7417 100644
--- a/ports/atmel-samd/supervisor/serial.c
+++ b/ports/atmel-samd/supervisor/serial.c
@@ -29,25 +29,33 @@
#include "supervisor/serial.h"
#include "usb.h"
+#include "tools/autogen_usb_descriptor.h"
-// Serial number as hex characters.
-// char serial_number[USB_DEVICE_GET_SERIAL_NAME_LENGTH];
-// void load_serial_number(void) {
-// char nibble_to_hex[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A',
-// 'B', 'C', 'D', 'E', 'F'};
-// uint32_t* addresses[4] = {(uint32_t *) 0x0080A00C, (uint32_t *) 0x0080A040,
-// (uint32_t *) 0x0080A044, (uint32_t *) 0x0080A048};
-// for (int i = 0; i < 4; i++) {
-// for (int j = 0; j < 8; j++) {
-// uint8_t nibble = (*(addresses[i]) >> j * 4) & 0xf;
-// serial_number[i * 8 + j] = nibble_to_hex[nibble];
-// }
-// }
-// }
-
-// SAMD51 addresses: 0x008061FC, 0x00806010, 0x00806014, 0x00806018
+// Serial number as hex characters. This writes directly to the USB
+// descriptor.
+void load_serial_number(void) {
+ char nibble_to_hex[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+ 'A', 'B', 'C', 'D', 'E', 'F'};
+ #ifdef SAMD21
+ uint32_t* addresses[4] = {(uint32_t *) 0x0080A00C, (uint32_t *) 0x0080A040,
+ (uint32_t *) 0x0080A044, (uint32_t *) 0x0080A048};
+ #endif
+ #ifdef SAMD51
+ uint32_t* addresses[4] = {(uint32_t *) 0x008061FC, (uint32_t *) 0x00806010,
+ (uint32_t *) 0x00806014, (uint32_t *) 0x00806018};
+ #endif
+ for (int i = 0; i < 4; i++) {
+ for (int j = 0; j < 8; j++) {
+ uint8_t nibble = (*(addresses[i]) >> j * 4) & 0xf;
+ // Strings are UTF-16-LE encoded.
+ serial_number[i * 16 + j * 2] = nibble_to_hex[nibble];
+ serial_number[i * 16 + j * 2 + 1] = 0;
+ }
+ }
+}
void serial_init(void) {
+ load_serial_number();
init_usb();
}
diff --git a/ports/atmel-samd/tools/autogen_usb_descriptor.h b/ports/atmel-samd/tools/autogen_usb_descriptor.h
new file mode 100644
index 000000000..00937d42d
--- /dev/null
+++ b/ports/atmel-samd/tools/autogen_usb_descriptor.h
@@ -0,0 +1,36 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef __MICROPY_INCLUDED_ATMEL_SAMD_TOOLS_AUTOGEN_USB_DESCRIPTOR_H__
+#define __MICROPY_INCLUDED_ATMEL_SAMD_TOOLS_AUTOGEN_USB_DESCRIPTOR_H__
+
+#include "usb/device/usbdc.h"
+
+struct usbd_descriptors descriptor_bounds;
+uint8_t* serial_number;
+uint8_t serial_number_length;
+
+#endif // __MICROPY_INCLUDED_ATMEL_SAMD_TOOLS_AUTOGEN_USB_DESCRIPTOR_H__
diff --git a/ports/atmel-samd/tools/gen_usb_descriptor.py b/ports/atmel-samd/tools/gen_usb_descriptor.py
new file mode 100644
index 000000000..2a2b217fd
--- /dev/null
+++ b/ports/atmel-samd/tools/gen_usb_descriptor.py
@@ -0,0 +1,150 @@
+import argparse
+
+import os
+import sys
+
+# path hacking
+sys.path.append("../../tools")
+
+from usb_descriptor import core
+from usb_descriptor import cdc
+
+parser = argparse.ArgumentParser(description='Generate USB descriptors.')
+parser.add_argument('--manufacturer', type=str,
+ help='manufacturer of the device')
+parser.add_argument('--product', type=str,
+ help='product name of the device')
+parser.add_argument('--vid', type=lambda x: int(x, 16),
+ help='vendor id')
+parser.add_argument('--pid', type=lambda x: int(x, 16),
+ help='product id')
+parser.add_argument('--serial_number_length', type=int, default=32,
+ help='length needed for the serial number in digits')
+parser.add_argument('output_file', type=argparse.FileType('w'))
+
+args = parser.parse_args()
+
+langid = core.StringDescriptor("\u0409")
+manufacturer = core.StringDescriptor(args.manufacturer)
+product = core.StringDescriptor(args.product)
+serial_number = core.StringDescriptor("serial number. you should fill in a unique serial number here."[:args.serial_number_length])
+strings = [langid, manufacturer, product, serial_number]
+
+# vid = 0x239A
+# pid = 0x8021
+
+device = core.DeviceDescriptor(
+ idVendor=args.vid,
+ idProduct=args.pid,
+ iManufacturer=strings.index(manufacturer),
+ iProduct=strings.index(product),
+ iSerialNumber=strings.index(serial_number))
+
+# Interface numbers are interface set local and endpoints are interface local
+# until core.join_interfaces renumbers them.
+cdc_interfaces = [
+ core.InterfaceDescriptor(
+ bInterfaceClass=0x2, # Communications Device Class
+ bInterfaceSubClass=0x02, # Abstract control model
+ bInterfaceProtocol=0x01, # Common AT Commands
+ subdescriptors=[
+ # Working 2.x
+ # radix: hexadecimal
+ # 05 24 00 10 01 header
+ # 05 24 01 03 01 call manage
+ # 04 24 02 06 acm
+ # 05 24 06 00 01 union
+ cdc.Header(bcdCDC=0x0110),
+ cdc.CallManagement(bmCapabilities=0x03, bDataInterface=0x01),
+ cdc.AbstractControlManagement(bmCapabilities=0x02),
+ cdc.Union(bMasterInterface=0x00,
+ bSlaveInterface=[0x01]),
+ core.EndpointDescriptor(
+ bEndpointAddress=0x0 | core.EndpointDescriptor.DIRECTION_IN,
+ bmAttributes=core.EndpointDescriptor.TYPE_INTERRUPT,
+ wMaxPacketSize=0x8,
+ bInterval=10)
+ ]
+ ),
+ core.InterfaceDescriptor(
+ bInterfaceClass=0x0a,
+ subdescriptors=[
+ core.EndpointDescriptor(
+ bEndpointAddress=0x0 | core.EndpointDescriptor.DIRECTION_IN,
+ bmAttributes=core.EndpointDescriptor.TYPE_BULK),
+ core.EndpointDescriptor(
+ bEndpointAddress=0x0 | core.EndpointDescriptor.DIRECTION_OUT,
+ bmAttributes=core.EndpointDescriptor.TYPE_BULK)
+ ]
+ )
+]
+
+msc_interfaces = [
+ core.InterfaceDescriptor(
+ bInterfaceClass=0x08,
+ bInterfaceSubClass=0x06,
+ bInterfaceProtocol=0x50,
+ subdescriptors=[
+ core.EndpointDescriptor(
+ bEndpointAddress=0x0 | core.EndpointDescriptor.DIRECTION_IN,
+ bmAttributes=core.EndpointDescriptor.TYPE_BULK),
+ core.EndpointDescriptor(
+ bEndpointAddress=0x1 | core.EndpointDescriptor.DIRECTION_OUT,
+ bmAttributes=core.EndpointDescriptor.TYPE_BULK)
+ ]
+ )
+]
+
+interfaces = core.join_interfaces(cdc_interfaces, msc_interfaces)
+
+cdc_function = core.InterfaceAssociationDescriptor(
+ bFirstInterface=interfaces.index(cdc_interfaces[0]),
+ bInterfaceCount=len(cdc_interfaces),
+ bFunctionClass=0x2, # Communications Device Class
+ bFunctionSubClass=0x2, # Abstract control model
+ bFunctionProtocol=0x1) # Common AT Commands
+
+configuration = core.ConfigurationDescriptor(
+ wTotalLength=(core.ConfigurationDescriptor.bLength +
+ cdc_function.bLength +
+ sum([len(bytes(x)) for x in interfaces])),
+ bNumInterfaces=len(interfaces))
+
+descriptor_list = [device, configuration, cdc_function]
+descriptor_list.extend(interfaces)
+descriptor_list.extend(strings)
+
+output_file = args.output_file
+
+output_file.write("#include <stdint.h>\n\n")
+output_file.write("#include \"tools/autogen_usb_descriptor.h\"\n\n")
+output_file.write("uint8_t usb_descriptors[] = {\n")
+descriptor_length = 0
+serial_number_offset = None
+for descriptor in descriptor_list:
+ output_file.write("// " + str(descriptor) + "\n")
+ b = bytes(descriptor)
+ i = 0
+ if descriptor == serial_number:
+ # Add two for the length and descriptor type bytes.
+ serial_number_offset = descriptor_length + 2
+ # This prints each subdescriptor on a separate line.
+ while i < len(b):
+ length = b[i]
+ for j in range(length):
+ output_file.write("0x{:02x}, ".format(b[i + j]))
+ output_file.write("\n")
+ i += length
+ descriptor_length += length
+
+ output_file.write("\n")
+output_file.write("};\n\n")
+output_file.write("struct usbd_descriptors descriptor_bounds = " +
+ "{usb_descriptors," +
+ " usb_descriptors + sizeof(usb_descriptors)};\n")
+output_file.write("uint8_t* serial_number = usb_descriptors + " +
+ str(serial_number_offset) + ";\n")
+output_file.write("uint8_t serial_number_length = " +
+ str(args.serial_number_length) + ";\n")
+
+output_file.close()
diff --git a/ports/atmel-samd/usb.c b/ports/atmel-samd/usb.c
index bd712a5d2..993ac7eaa 100644
--- a/ports/atmel-samd/usb.c
+++ b/ports/atmel-samd/usb.c
@@ -44,6 +44,7 @@
#include "hpl/gclk/hpl_gclk_base.h"
#include "lib/utils/interrupt_char.h"
+#include "tools/autogen_usb_descriptor.h"
#include "reset.h"
#include "usb_mass_storage.h"
@@ -67,13 +68,6 @@ volatile uint8_t usb_rx_count = 0;
volatile bool mp_cdc_enabled = false;
volatile bool usb_transmitting = false;
-static uint8_t multi_desc_bytes[] = {
- /* Device descriptors and Configuration descriptors list. */
- COMPOSITE_DESCES_LS_FS,
-};
-
-static struct usbd_descriptors multi_desc = {multi_desc_bytes, multi_desc_bytes + sizeof(multi_desc_bytes)};
-
/** Ctrl endpoint buffer */
COMPILER_ALIGNED(4) static uint8_t ctrl_buffer[64];
@@ -221,8 +215,10 @@ void init_usb(void) {
mscdf_register_callback(MSCDF_CB_EJECT_DISK, (FUNC_PTR)usb_msc_disk_eject);
mscdf_register_callback(MSCDF_CB_TEST_DISK_READY, (FUNC_PTR)usb_msc_disk_is_ready);
mscdf_register_callback(MSCDF_CB_XFER_BLOCKS_DONE, (FUNC_PTR)usb_msc_xfer_done);
+ mscdf_register_callback(MSCDF_CB_IS_WRITABLE, (FUNC_PTR)usb_msc_disk_is_writable);
+
+ usbdc_start(&descriptor_bounds);
- usbdc_start(&multi_desc);
usbdc_attach();
}
diff --git a/ports/atmel-samd/usb_mass_storage.c b/ports/atmel-samd/usb_mass_storage.c
index 6b9a22d25..3e96c3787 100644
--- a/ports/atmel-samd/usb_mass_storage.c
+++ b/ports/atmel-samd/usb_mass_storage.c
@@ -87,6 +87,28 @@ int32_t usb_msc_disk_eject(uint8_t lun) {
}
/**
+ * \brief Inquiry whether Disk is writable. ERR_DENIED if it is not writable.
+ * ERR_NONE if it is. ERR_NOT_FOUND if its missing.
+ * \param[in] lun logic unit number
+ * \return Operation status.
+ */
+int32_t usb_msc_disk_is_writable(uint8_t lun) {
+ if (lun > 1) {
+ return ERR_NOT_FOUND;
+ }
+
+ fs_user_mount_t* vfs = get_vfs(lun);
+ if (vfs == NULL) {
+ return ERR_NOT_FOUND;
+ }
+ if (vfs->writeblocks[0] == MP_OBJ_NULL ||
+ (vfs->flags & FSUSER_USB_WRITABLE) == 0) {
+ return ERR_DENIED;
+ }
+ return ERR_NONE;
+}
+
+/**
* \brief Inquiry whether Disk is ready
* \param[in] lun logic unit number
* \return Operation status.
@@ -178,7 +200,7 @@ COMPILER_ALIGNED(4) uint8_t sector_buffer[512];
*/
int32_t usb_msc_new_read(uint8_t lun, uint32_t addr, uint32_t nblocks) {
if (lun > 1) {
- return ERR_DENIED;
+ return ERR_NOT_FOUND;
}
// Store transfer info so we can service it in the "background".
@@ -199,13 +221,16 @@ int32_t usb_msc_new_read(uint8_t lun, uint32_t addr, uint32_t nblocks) {
*/
int32_t usb_msc_new_write(uint8_t lun, uint32_t addr, uint32_t nblocks) {
if (lun > 1) {
- return ERR_DENIED;
+ return ERR_NOT_FOUND;
}
fs_user_mount_t * vfs = get_vfs(lun);
// This is used to determine the writeability of the disk from USB.
- if (vfs == NULL || vfs->writeblocks[0] == MP_OBJ_NULL /*||
- (vfs->flags & FSUSER_USB_WRITEABLE) == 0*/) {
+ if (vfs == NULL) {
+ return ERR_NOT_FOUND;
+ }
+ if (vfs->writeblocks[0] == MP_OBJ_NULL ||
+ (vfs->flags & FSUSER_USB_WRITABLE) == 0) {
return ERR_DENIED;
}
diff --git a/ports/atmel-samd/usb_mass_storage.h b/ports/atmel-samd/usb_mass_storage.h
index d8906a16f..767a6779c 100644
--- a/ports/atmel-samd/usb_mass_storage.h
+++ b/ports/atmel-samd/usb_mass_storage.h
@@ -37,6 +37,7 @@ void usb_msc_background(void);
// Callbacks that hook into ASF4's USB stack.
int32_t usb_msc_disk_eject(uint8_t lun);
+int32_t usb_msc_disk_is_writable(uint8_t lun);
int32_t usb_msc_disk_is_ready(uint8_t lun);
int32_t usb_msc_new_read(uint8_t lun, uint32_t addr, uint32_t nblocks);
int32_t usb_msc_new_write(uint8_t lun, uint32_t addr, uint32_t nblocks);
diff --git a/supervisor/filesystem.h b/supervisor/filesystem.h
index fd2bf0364..cfd1ed027 100644
--- a/supervisor/filesystem.h
+++ b/supervisor/filesystem.h
@@ -31,7 +31,7 @@
void filesystem_init(bool create_allowed);
void filesystem_flush(void);
-void filesystem_default_writeable(bool writeable);
+void filesystem_writable_by_python(bool writable);
bool filesystem_present(void);
#endif // MICROPY_INCLUDED_SUPERVISOR_FILESYSTEM_H
diff --git a/supervisor/stub/filesystem.c b/supervisor/stub/filesystem.c
index 462ee62a4..12fe9fb10 100644
--- a/supervisor/stub/filesystem.c
+++ b/supervisor/stub/filesystem.c
@@ -32,7 +32,7 @@ void filesystem_init(void) {
void filesystem_flush(void) {
}
-void filesystem_default_writeable(bool writeable) {
+void filesystem_writable_by_python(bool writable) {
}
bool filesystem_present(void) {
diff --git a/tools/usb_descriptor/cdc.py b/tools/usb_descriptor/cdc.py
new file mode 100644
index 000000000..4042e7673
--- /dev/null
+++ b/tools/usb_descriptor/cdc.py
@@ -0,0 +1,53 @@
+from . import core
+import struct
+
+class FunctionalDescriptor(core.Descriptor):
+ bDescriptorType = 0x24
+
+ def __init__(self, *args, **kwargs):
+ super().__init__(*args, **kwargs)
+ self.fmt = "<BBB" + self.fmt[3:]
+
+ def __bytes__(self):
+ return struct.pack(self.fmt, self.bLength, self.bDescriptorType, self.bDescriptorSubtype, *self.data)
+
+
+class Header(FunctionalDescriptor):
+ fields = [('bcdCDC', "H", None)]
+ bLength = 0x05
+ bDescriptorSubtype = 0x0
+
+
+class CallManagement(FunctionalDescriptor):
+ fields = [('bmCapabilities', "b", None),
+ ('bDataInterface', "b", None)]
+ bLength = 0x05
+ bDescriptorSubtype = 0x01
+
+
+class AbstractControlManagement(FunctionalDescriptor):
+ fields = [('bmCapabilities', "b", None)]
+ bLength = 0x04
+ bDescriptorSubtype = 0x02
+
+
+class DirectLineManagement(FunctionalDescriptor):
+ fields = [('bmCapabilities', "b", None)]
+ bLength = 0x04
+ bDescriptorSubtype = 0x03
+
+
+class Union(FunctionalDescriptor):
+ fields = [('bMasterInterface', "b", None)]
+ bDescriptorSubtype = 0x06
+
+ def __init__(self, *args, **kwargs):
+ self.bSlaveInterface = kwargs["bSlaveInterface"]
+ super().__init__(*args, **kwargs)
+
+ def __bytes__(self):
+ return super().__bytes__() + bytes(self.bSlaveInterface)
+
+ @property
+ def bLength(self):
+ return 0x4 + len(self.bSlaveInterface)
diff --git a/tools/usb_descriptor/core.py b/tools/usb_descriptor/core.py
new file mode 100644
index 000000000..03d9c3e63
--- /dev/null
+++ b/tools/usb_descriptor/core.py
@@ -0,0 +1,187 @@
+import struct
+
+
+def join_interfaces(*args):
+ interfaces = []
+ base_endpoint_number = 1
+ for interface_set in args:
+ base_interface_number = len(interfaces)
+ for i, interface in enumerate(interface_set):
+ interfaces.append(interface)
+ interface.bInterfaceNumber = interfaces.index(interface)
+ max_endpoint_address = base_endpoint_number
+ for subdescriptor in interface.subdescriptors:
+ if subdescriptor.bDescriptorType == EndpointDescriptor.bDescriptorType:
+ subdescriptor.bEndpointAddress += base_endpoint_number
+ max_endpoint_address = max(max_endpoint_address, subdescriptor.bEndpointAddress & 0xf)
+ base_endpoint_number = max_endpoint_address + 1
+ return interfaces
+
+
+class Descriptor:
+ def __init__(self, *args, **kwargs):
+ self.fmt = ["<B", "B"]
+ for field in self.fields:
+ self.fmt.append(field[1])
+ self.fmt = "".join(self.fmt)
+ if len(args) == 1:
+ self.data = struct.unpack(self.fmt, args[0])
+ if self.data[1] != self.bDescriptorType:
+ raise RuntimeError("Descriptor type doesn't match.")
+ return
+ elif len(args) > 1:
+ raise TypeError("Only one arg or keyword args expected.")
+ elif len(kwargs) == 0:
+ raise TypeError("Only one arg or keyword args expected.")
+
+ self.data = []
+ for field, _, default in self.fields:
+ if field in kwargs:
+ self.data.append(kwargs[field])
+ elif default is not None:
+ self.data.append(default)
+ else:
+ raise ValueError("Missing {} argument.".format(field))
+
+ def __bytes__(self):
+ return struct.pack(self.fmt, self.bLength, self.bDescriptorType, *self.data)
+
+ @property
+ def bDescriptorType(self):
+ return self._bDescriptorType
+
+class EndpointDescriptor(Descriptor):
+ fields = [('bEndpointAddress', "B", None),
+ ('bmAttributes', "B", None),
+ ('wMaxPacketSize', "H", 0x40),
+ ('bInterval', "B", 0)]
+
+ bLength = 0x07
+ bDescriptorType = 0x5
+
+ TYPE_CONTROL = 0b00
+ TYPE_ISOCHRONOUS = 0b01
+ TYPE_BULK = 0b10
+ TYPE_INTERRUPT = 0b11
+
+ DIRECTION_IN = 0x80
+ DIRECTION_OUT = 0x00
+
+ @property
+ def bEndpointAddress(self):
+ return self.data[0]
+
+ @bEndpointAddress.setter
+ def bEndpointAddress(self, value):
+ self.data[0] = value
+
+
+class InterfaceDescriptor(Descriptor):
+ fields = [('bInterfaceNumber', "B", 0),
+ ('bAlternateSetting', "B", 0),
+ ('bNumEndpoints', "B", 0),
+ ('bInterfaceClass', "B", None),
+ ('bInterfaceSubClass', "B", 0),
+ ('bInterfaceProtocol', "B", 0),
+ ('iInterface', "B", 0)]
+
+ bLength = 0x09
+ bDescriptorType = 0x4
+
+ def __init__(self, *args, **kwargs):
+ self.subdescriptors = []
+ if "subdescriptors" in kwargs:
+ self.subdescriptors = kwargs["subdescriptors"]
+ super().__init__(*args, **kwargs)
+
+ def __bytes__(self):
+ endpoint_count = 0
+ subdescriptor_bytes = []
+ for desc in self.subdescriptors:
+ subdescriptor_bytes.append(bytes(desc))
+ if desc.bDescriptorType == EndpointDescriptor.bDescriptorType:
+ endpoint_count += 1
+ subdescriptor_bytes = b"".join(subdescriptor_bytes)
+ self.data[2] = endpoint_count
+ return super().__bytes__() + subdescriptor_bytes
+
+ @property
+ def bInterfaceNumber(self):
+ return self.data[0]
+
+ @bInterfaceNumber.setter
+ def bInterfaceNumber(self, value):
+ self.data[0] = value
+
+class InterfaceAssociationDescriptor(Descriptor):
+ fields = [('bFirstInterface', "B", None),
+ ('bInterfaceCount', "B", None),
+ ('bFunctionClass', "B", None),
+ ('bFunctionSubClass', "B", None),
+ ('bFunctionProtocol', "B", None),
+ ('iFunction', "B", 0)]
+
+ bLength = 0x08
+ bDescriptorType = 0xB
+
+
+class ConfigurationDescriptor(Descriptor):
+ fields = [('wTotalLength', "H", None),
+ ('bNumInterfaces', "B", None),
+ ('bConfigurationValue', "B", 0x1),
+ ('iConfiguration', "B", 0),
+ # bus powered (bit 6), no remote wakeup (bit 5), bit 7 is always 1 and 0-4 are always 0
+ ('bmAttributes', "B", 0x80),
+ # 100 mA by default
+ ('bMaxPower', "B", 50)]
+
+ bLength = 0x09
+ bDescriptorType = 0x2
+
+class DeviceDescriptor(Descriptor):
+ fields = [('bcdUSB', "H", 0x200),
+ ('bDeviceClass', "B", 0xef),
+ ('bDeviceSubClass', "B", 0x02),
+ ('bDeviceProtocol', "B", 0x01),
+ ('bMaxPacketSize0', "B", 0x40),
+ ('idVendor', "H", None),
+ ('idProduct', "H", None),
+ ('bcdDevice', "H", 0x100),
+ ('iManufacturer', "B", None),
+ ('iProduct', "B", None),
+ ('iSerialNumber', "B", None),
+ ('bNumConfigurations', "B", 1)]
+
+ bLength = 0x12
+ bDescriptorType = 0x1
+
+class StringDescriptor:
+ def __init__(self, value):
+ if type(value) == str:
+ self._bString = value.encode("utf-16-le")
+ self._bLength = len(self._bString) + 2
+ elif len(value) > 1:
+ self._bLength = value[0]
+ if value[1] != 3:
+ raise ValueError("Sequence not a StringDescriptor")
+ self._bString = value[2:2+self.bLength]
+
+ def __bytes__(self):
+ return struct.pack("BB{}s".format(len(self._bString)), self.bLength, self.bDescriptorType, self._bString)
+
+ @property
+ def bString(self):
+ return self._bString.decode("utf-16-le")
+
+ @bString.setter
+ def bString(self, value):
+ self._bString = value.encode("utf-16-le")
+ self._bLength = len(self.encoded) + 2
+
+ @property
+ def bDescriptorType(self):
+ return 3
+
+ @property
+ def bLength(self):
+ return self._bLength