summaryrefslogtreecommitdiff
path: root/ports
diff options
context:
space:
mode:
authorScott Shawcroft <scott.shawcroft@gmail.com>2017-10-26 16:53:25 -0700
committerScott Shawcroft <scott.shawcroft@gmail.com>2017-10-30 18:29:20 -0700
commit4aeef100f6d78313e1cc58fb6ef6d6b0da5c879d (patch)
tree65289dee99b86f0fb7fd8ed25ebac6beee4e1e2a /ports
parent189366983366cf5cad214d15070a0a53ccce24a8 (diff)
atmel-samd: More USB polish
* Introduce a python script to generate the USB descriptor instead of a bunch of C macros. In the future, we can use this dynamically in CircuitPython. * Add support for detecting read-only mass storage mounts. Fixes #377
Diffstat (limited to 'ports')
-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
24 files changed, 291 insertions, 48 deletions
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);