diff --git a/epicardium/cdcacm.c b/epicardium/cdcacm.c
index 5a023fedee93fc0013ad83e0f762725426504b65..72b9ba6569d79bd3f6d23c580d6929605d6636c4 100644
--- a/epicardium/cdcacm.c
+++ b/epicardium/cdcacm.c
@@ -1,303 +1,48 @@
-/*******************************************************************************
- * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
- *
- * 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 MAXIM INTEGRATED 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.
- *
- * Except as contained in this notice, the name of Maxim Integrated
- * Products, Inc. shall not be used except as stated in the Maxim Integrated
- * Products, Inc. Branding Policy.
- *
- * The mere transfer of this software does not imply any licenses
- * of trade secrets, proprietary technology, copyrights, patents,
- * trademarks, maskwork rights, or any other form of intellectual
- * property whatsoever. Maxim Integrated Products, Inc. retains all
- * ownership rights.
- *
- * $Id: main.c 32120 2017-11-28 23:51:11Z lorne.smith $
- *
- *******************************************************************************
- */
-
-/**
- * @file    main.c
- * @brief   USB CDC-ACM example
- * @details This project creates a virtual COM port, which loops back data sent to it.
- *          Load the project, connect a cable from the PC to the USB connector
- *          on the Evaluation Kit, and observe that the PC now recognizes a new COM port.
- *          A driver for the COM port, if needed, is located in the Driver/ subdirectory.
- *
- */
-
 #include "cdcacm.h"
 
 #include <stdio.h>
 #include <stddef.h>
+#include <errno.h>
 
-#include "mxc_config.h"
-#include "mxc_sys.h"
-#include "mxc_delay.h"
-#include "board.h"
-#include "led.h"
 #include "usb.h"
 #include "usb_event.h"
-#include "enumerate.h"
 #include "cdc_acm.h"
-#include "msc.h"
 
-#include "descriptors.h"
 
 #include "modules/log.h"
-#include "modules/filesystem.h"
-#include <errno.h>
-
-/***** Definitions *****/
-#define EVENT_ENUM_COMP     MAXUSB_NUM_EVENTS
-
-#define BUFFER_SIZE  64
-
-#define STRINGIFY(x) #x
-#define TOSTRING(x) STRINGIFY(x)
-
-/***** Global Data *****/
-//SWYM: rename to CDC_xy or put into struct CDC_state
-volatile int configured; //SWYM: actually unused...
-volatile int suspended;
-volatile unsigned int event_flags;
-int remote_wake_en;
-
-/***** Function Prototypes *****/
-static int setconfig_callback(usb_setup_pkt *sud, void *cbdata);
-static int setfeature_callback(usb_setup_pkt *sud, void *cbdata);
-static int clrfeature_callback(usb_setup_pkt *sud, void *cbdata);
-static int event_callback(maxusb_event_t evt, void *data);
-static void usb_app_sleep(void);
-static void usb_app_wakeup(void);
-static int usb_read_callback(void);
-static void deconfigure(void);
-
-/***** File Scope Variables *****/
-
-/* This EP assignment must match the Configuration Descriptor */
-static const acm_cfg_t acm_cfg = {
-  1,                  /* EP OUT */
-  MXC_USBHS_MAX_PACKET, /* OUT max packet size */
-  2,                  /* EP IN */
-  MXC_USBHS_MAX_PACKET, /* IN max packet size */
-  3,                  /* EP Notify */
-  MXC_USBHS_MAX_PACKET, /* Notify max packet size */
-};
-
-static volatile int usb_read_complete;
-static volatile bool initialized = false;
-static const msc_cfg_t* s_msc_cfg = NULL;
-
-
-int usb_startup_cb()
-{
-    const sys_cfg_usbhs_t sys_usbhs_cfg = NULL;
-    LOG_INFO("usb", "SYS_USBHS_Init");
-    return SYS_USBHS_Init(&sys_usbhs_cfg);
-}
-
-int usb_shutdown_cb()
-{
-    LOG_INFO("usb", "SYS_USBHS_Shutdown");
-    SYS_USBHS_Shutdown();
-    SYS_Reset_Periph(SYS_RESET_USB);
-    if (s_msc_cfg) {
-        LOG_INFO("usb", "re-attaching FLASH");
-        fatfs_attach();
-        s_msc_cfg = NULL;
-    }
-    return 0;
-}
-
-/* User-supplied function to delay usec micro-seconds */
-void delay_us(unsigned int usec)
-{
-    /* mxc_delay() takes unsigned long, so can't use it directly */
-    mxc_delay(usec);
-}
-
-/******************************************************************************/
-int epc_usb_init(uint16_t interfaces)
-{
-    if (initialized) {
-        //NVIC_DisableIRQ(USB_IRQn); //yes? no?
-        
-        usb_disconnect();
-        deconfigure();
-        //usb_app_sleep();
-        usb_shutdown();
-        initialized = false;
-    }
-    if (interfaces == 0) {
-        return 0;
-    }
-    maxusb_cfg_options_t usb_opts;
-
-    /* Initialize state */
-    configured = 0;
-    suspended = 0;
-    event_flags = 0;
-    remote_wake_en = 0;
-
-    /* Start out in full speed */
-    usb_opts.enable_hs = 0;
-    usb_opts.delay_us = delay_us; /* Function which will be used for delays */
-    usb_opts.init_callback = usb_startup_cb;
-    usb_opts.shutdown_callback = usb_shutdown_cb;
-
-    /* Initialize the usb module */
-    if (usb_init(&usb_opts) != 0) {
-        LOG_ERR("cdcacm", "usb_init() failed");
-        return -EIO;
-    }
-
-    /* Initialize the enumeration module */
-    if (enum_init() != 0) {
-        usb_shutdown();
-        LOG_ERR("cdcacm", "enum_init() failed");
-        return -EIO;
-    }
-
-    /* Register enumeration data */
-    if (interfaces & USB_IFACE_STORAGE) {
-        config_descriptor.config_descriptor.wTotalLength = sizeof(config_descriptor);
-        config_descriptor.config_descriptor.bNumInterfaces = 3;
-    } else {
-        config_descriptor.config_descriptor.wTotalLength = offsetof(struct config_descriptor_s, msc_interface_descriptor);
-        config_descriptor.config_descriptor.bNumInterfaces = 2;
-    }
-    enum_register_descriptor(ENUM_DESC_DEVICE, (uint8_t*)&composite_device_descriptor, 0);
-    enum_register_descriptor(ENUM_DESC_CONFIG, (uint8_t*)&config_descriptor, 0);
-    enum_register_descriptor(ENUM_DESC_STRING, lang_id_desc, 0);
-    enum_register_descriptor(ENUM_DESC_STRING, mfg_id_desc, 1);
-    enum_register_descriptor(ENUM_DESC_STRING, prod_id_desc, 2);
-    //used in composite but not in cdc (see iSerialNumber)
-    enum_register_descriptor(ENUM_DESC_STRING, serial_id_desc, 3);
-    enum_register_descriptor(ENUM_DESC_STRING, cdcacm_func_desc, 4);
-    enum_register_descriptor(ENUM_DESC_STRING, msc_func_desc, 5);
-
-    /* Handle configuration */
-    enum_register_callback(ENUM_SETCONFIG, setconfig_callback, NULL);
-
-    /* Handle feature set/clear */
-    enum_register_callback(ENUM_SETFEATURE, setfeature_callback, NULL);
-    enum_register_callback(ENUM_CLRFEATURE, clrfeature_callback, NULL);
 
-    /* Initialize the class driver */
-    if (acm_init(&config_descriptor.comm_interface_descriptor) != 0) {
-        enum_clearconfig();
-        usb_shutdown();
-        LOG_ERR("cdcacm", "acm_init() failed");
-        return -EIO;
-    }
-
-    if (interfaces & USB_IFACE_STORAGE) {
-        /* Initialize the class driver */
-        static const msc_idstrings_t ids = {
-            "CCC",    /* Vendor string.  Maximum of 8 bytes */
-            "card10", /* Product string.  Maximum of 16 bytes */
-            "1.0"     /* Version string.  Maximum of 4 bytes */
-        };
-
-        /* This EP assignment must match the Configuration Descriptor */
-        static const msc_cfg_t msc_cfg = {
-            4,                    /* EP OUT */
-            MXC_USBHS_MAX_PACKET, /* OUT max packet size */
-            5,                    /* EP IN */
-            MXC_USBHS_MAX_PACKET, /* IN max packet size */
-        };
-        s_msc_cfg = &msc_cfg;
-        LOG_INFO("usb", "detaching FLASH");
-        fatfs_detach();
-
-
-        /* Functions to control "disk" memory. See msc.h for definitions. */
-        int mscmem_init(void);
-        int mscmem_start(void);
-        int mscmem_stop(void);
-        uint32_t mscmem_size(void);
-        int mscmem_read(uint32_t lba, uint8_t* buffer);
-        int mscmem_write(uint32_t lba, uint8_t* buffer);
-        int mscmem_ready(void);
-
-        static const msc_mem_t mem = {
-            mscmem_init, mscmem_start, mscmem_stop,  mscmem_ready,
-            mscmem_size, mscmem_read,  mscmem_write,
-        };
-        if (msc_init(&config_descriptor.msc_interface_descriptor, &ids, &mem) != 0) {
-            LOG_ERR("msc", "msc_init() failed\n");
-            return -EIO;
-        }
-    } else {
-        s_msc_cfg = NULL;
-    }
-
-    /* Register callbacks */
-    usb_event_enable(MAXUSB_EVENT_NOVBUS, event_callback, NULL);
-    usb_event_enable(MAXUSB_EVENT_VBUS, event_callback, NULL);
-    acm_register_callback(ACM_CB_READ_READY, usb_read_callback);
-    usb_read_complete = 0;
-
-    /* Start with USB in low power mode */
-    usb_app_sleep();
-    /* TODO: Fix priority */
-    NVIC_SetPriority(USB_IRQn, 6);
-    NVIC_EnableIRQ(USB_IRQn);
-
-    initialized = true;
-
-    return 0;
-}
 
 int cdcacm_num_read_avail(void)
 {
-    return acm_canread();
+	return acm_canread();
 }
 
 uint8_t cdcacm_read(void)
 {
-    while(acm_canread() <= 0) {
-    }
+	while (acm_canread() <= 0) {
+	}
 
-    uint8_t buf;
-    acm_read(&buf, 1);
-    return buf;
+	uint8_t buf;
+	acm_read(&buf, 1);
+	return buf;
 }
 
 void cdcacm_write(uint8_t *data, int len)
 {
-    static int lockup_disable = 0;
-    if (acm_present() && !lockup_disable) {
-        int ret = acm_write(data, len);
-        if (ret < 0) {
-            LOG_ERR("cdcacm", "fifo lockup detected");
-            lockup_disable = 1;
-        } else if (ret != len) {
-            LOG_WARN("cdcacm", "write length mismatch, got %d", ret);
-        }
-    }
+	static int lockup_disable = 0;
+	if (acm_present() && !lockup_disable) {
+		int ret = acm_write(data, len);
+		if (ret < 0) {
+			LOG_ERR("cdcacm", "fifo lockup detected");
+			lockup_disable = 1;
+		} else if (ret != len) {
+			LOG_WARN(
+				"cdcacm", "write length mismatch, got %d", ret
+			);
+		}
+	}
 }
 
-
 /******************************************************************************/
 #if 0
 static void echo_usb(void)
@@ -328,131 +73,6 @@ static void echo_usb(void)
 #endif
 
 #include "mx25lba.h"
-
-
-/******************************************************************************/
-static int setconfig_callback(usb_setup_pkt *sud, void *cbdata)
-{
-    LOG_INFO("usb", "setconfig %d \n", (int)sud->wValue);
-    /* Confirm the configuration value */
-    if (sud->wValue == config_descriptor.config_descriptor.bConfigurationValue) {
-        configured = 1;
-        MXC_SETBIT(&event_flags, EVENT_ENUM_COMP);
-        int acm_rc = acm_configure(&acm_cfg);
-        if (acm_rc) {
-            LOG_ERR("usb", "acm_configure failed: %d\n", acm_rc);
-        }
-        int msc_rc = s_msc_cfg ? msc_configure(s_msc_cfg) : 0;
-        if (msc_rc) {
-            LOG_ERR("usb", "msc_configure failed: %d\n", msc_rc);
-        }
-        return acm_rc || msc_rc;
-    } else if (sud->wValue == 0) {
-        configured = 0;
-        return acm_deconfigure();
-    }
-
-    return -1;
-}
-
-/******************************************************************************/
-static int setfeature_callback(usb_setup_pkt *sud, void *cbdata)
-{
-    if(sud->wValue == FEAT_REMOTE_WAKE) {
-        remote_wake_en = 1;
-    } else {
-        // Unknown callback
-        return -1;
-    }
-
-    return 0;
-}
-
-/******************************************************************************/
-static int clrfeature_callback(usb_setup_pkt *sud, void *cbdata)
-{
-    if(sud->wValue == FEAT_REMOTE_WAKE) {
-        remote_wake_en = 0;
-    } else {
-        // Unknown callback
-        return -1;
-    }
-    
-    return 0;
-}
-
-/******************************************************************************/
-static void usb_app_sleep(void)
-{
-    /* TODO: Place low-power code here */
-    suspended = 1;
-}
-
-/******************************************************************************/
-static void usb_app_wakeup(void)
-{
-    /* TODO: Place low-power code here */
-    suspended = 0;
-}
-
-static void deconfigure(void) {
-    enum_clearconfig();
-    acm_deconfigure();
-    if (s_msc_cfg) {
-        msc_deconfigure();
-    }
-    configured = 0;
-}
-/******************************************************************************/
-static int event_callback(maxusb_event_t evt, void *data)
-{
-    /* Set event flag */
-    MXC_SETBIT(&event_flags, evt);
-
-    LOG_INFO("usb", "event %d\n", evt);
-
-    switch (evt) {
-        case MAXUSB_EVENT_NOVBUS:
-            usb_event_disable(MAXUSB_EVENT_BRST);
-            usb_event_disable(MAXUSB_EVENT_SUSP);
-            usb_event_disable(MAXUSB_EVENT_DPACT);
-            usb_disconnect();
-            deconfigure();
-            usb_app_sleep();
-            break;
-        case MAXUSB_EVENT_VBUS:
-            usb_event_clear(MAXUSB_EVENT_BRST);
-            usb_event_enable(MAXUSB_EVENT_BRST, event_callback, NULL);
-            usb_event_clear(MAXUSB_EVENT_SUSP);
-            usb_event_enable(MAXUSB_EVENT_SUSP, event_callback, NULL);
-            usb_connect();
-            usb_app_sleep();
-            break;
-        case MAXUSB_EVENT_BRST:
-            usb_app_wakeup();
-            deconfigure();
-            suspended = 0;
-            break;
-        case MAXUSB_EVENT_SUSP:
-            usb_app_sleep();
-            break;
-        case MAXUSB_EVENT_DPACT:
-            usb_app_wakeup();
-            break;
-        default:
-            break;
-    }
-
-    return 0;
-}
-
-/******************************************************************************/
-static int usb_read_callback(void)
-{
-    usb_read_complete = 1;
-    return 0;
-}
-
 /******************************************************************************/
 #include "FreeRTOS.h"
 #include "task.h"
@@ -460,13 +80,15 @@ static int usb_read_callback(void)
 extern TaskHandle_t serial_task_id;
 void USB_IRQHandler(void)
 {
-    usb_event_handler();
+	usb_event_handler();
 
-    if (serial_task_id != NULL) {
-        BaseType_t xHigherPriorityTaskWoken = pdFALSE;
-        vTaskNotifyGiveFromISR(serial_task_id, &xHigherPriorityTaskWoken);
-        portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
-    }
+	if (serial_task_id != NULL) {
+		BaseType_t xHigherPriorityTaskWoken = pdFALSE;
+		vTaskNotifyGiveFromISR(
+			serial_task_id, &xHigherPriorityTaskWoken
+		);
+		portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
+	}
 }
 
 /******************************************************************************/
@@ -493,6 +115,7 @@ uint32_t mscmem_size(void)
 /******************************************************************************/
 int mscmem_read(uint32_t lba, uint8_t *buffer)
 {
+    LOG_INFO("msc", "mem.read %08lx", lba);
 	return mx25_read(lba, buffer);
 }
 
@@ -504,6 +127,7 @@ int mscmem_write(uint32_t lba, uint8_t *buffer)
 	}
 	dirty = 2;
 	return mx25_write(lba, buffer);
+
 }
 
 /******************************************************************************/
@@ -515,6 +139,7 @@ int mscmem_start()
 /******************************************************************************/
 int mscmem_stop()
 {
+    LOG_INFO("msc", "mem.stop");
 	int ret = mx25_stop();
 	//bootloader_stop();
 	return ret;
diff --git a/epicardium/descriptors.h b/epicardium/descriptors.h
index 44ef924c8921dedb6003bda928a7b99c6b5776b3..344c29473fbc0a8855de87abf66c59fa2786adee 100644
--- a/epicardium/descriptors.h
+++ b/epicardium/descriptors.h
@@ -43,7 +43,6 @@
 
 #define EPICARDIUM_USBSTORAGE
 
-#ifdef EPICARDIUM_USBSTORAGE
 usb_device_descriptor_t __attribute__((aligned(4))) composite_device_descriptor = {
     .bLength            = 0x12,
     .bDescriptorType    = 0x01,         /* Device          */
@@ -60,47 +59,28 @@ usb_device_descriptor_t __attribute__((aligned(4))) composite_device_descriptor
     .iSerialNumber      = 0x03,
     .bNumConfigurations = 0x01
 };
-#else
-usb_device_descriptor_t __attribute__((aligned(4))) device_descriptor = {
-    0x12,         /* bLength = 18                     */
-    0x01,         /* bDescriptorType = Device         */
-    0x0110,       /* bcdUSB USB spec rev (BCD)        */
-    0x02,         /* bDeviceClass = comm class (2)    */
-    0x00,         /* bDeviceSubClass                  */
-    0x00,         /* bDeviceProtocol                  */
-    0x40,         /* bMaxPacketSize0 is 64 bytes      */
-    0x0B6A,       /* idVendor (Maxim Integrated)      */
-    0x003C,       /* idProduct                        */
-    0x0100,       /* bcdDevice                        */
-    0x01,         /* iManufacturer Descriptor ID      */
-    0x02,         /* iProduct Descriptor ID           */
-    0x00,         /* iSerialNumber = (0) No string    */
-    0x01          /* bNumConfigurations               */
-};
-
-#endif//EPICARDIUM_USBSTORAGE
 
 __attribute__((aligned(4)))
 struct config_descriptor_s {
     usb_configuration_descriptor_t  config_descriptor;
     /* Interface #1 Comm Interface */
-    usb_interface_descriptor_t      comm_interface_descriptor;
+    usb_interface_descriptor_t      if_comm;
     uint8_t                         header_functional_descriptor[5];
     uint8_t                         call_management_descriptor[5];
     uint8_t                         acm_functional_descriptor[4];
     uint8_t                         union_functional_descriptor[5];
-    usb_endpoint_descriptor_t       endpoint_descriptor_3;
+    usb_endpoint_descriptor_t       ep_comm_in;
     /* Interface #2 Data Interface */
-    usb_interface_descriptor_t      data_interface_descriptor;
-    usb_endpoint_descriptor_t       endpoint_descriptor_1;
-    usb_endpoint_descriptor_t       endpoint_descriptor_2;
+    usb_interface_descriptor_t      if_data;
+    usb_endpoint_descriptor_t       ep_data_out;
+    usb_endpoint_descriptor_t       ep_data_in;
     /* Interface #3 Mass Storage Device */
-    usb_interface_descriptor_t      msc_interface_descriptor;
-    usb_endpoint_descriptor_t       endpoint_descriptor_4;
-    usb_endpoint_descriptor_t       endpoint_descriptor_5;
+    usb_interface_descriptor_t      if_msc;
+    usb_endpoint_descriptor_t       ep_msc_out;
+    usb_endpoint_descriptor_t       ep_msc_in;
 } __attribute__((packed))  config_descriptor =
 {
-    {
+    .config_descriptor = {
         0x09,       /*  bLength = 9                     */
         0x02,       /*  bDescriptorType = Config (2)    */
         sizeof(config_descriptor),
@@ -118,7 +98,7 @@ struct config_descriptor_s {
         0xE0,       /*  bmAttributes (self-powered, remote wakeup) */
         0x01,       /*  MaxPower is 2ma (units are 2ma/bit) */
     },
-    { /*  First Interface Descriptor For Comm Class Interface */
+    .if_comm = { /*  First Interface Descriptor For Comm Class Interface */
         0x09,       /*  bLength = 9                     */
         0x04,       /*  bDescriptorType = Interface (4) */
         0x00,       /*  bInterfaceNumber                */
@@ -129,33 +109,33 @@ struct config_descriptor_s {
         0x01,       /*  bInterfaceProtocol = Common "AT" commands (1), no class specific protocol (0) */
         0x00,       /*  iInterface                      */
     },
-    { /*  Header Functional Descriptor */
+    .header_functional_descriptor = { /*  Header Functional Descriptor */
         0x05,         /*  bFunctionalLength = 5           */
         0x24,         /*  bDescriptorType                 */
         0x00,         /*  bDescriptorSubtype              */
         0x10, 0x01,   /*  bcdCDC                          */
     },
-    { /*  Call Management Descriptor */
+    .call_management_descriptor = { /*  Call Management Descriptor */
         0x05,         /*  bFunctionalLength = 5           */
         0x24,         /*  bDescriptorType                 */
         0x01,         /*  bDescriptorSubtype              */
         0x03,         /*  bmCapabilities = Device handles call management itself (0x01), management over data class (0x02) */
         0x01,         /*  bmDataInterface                 */
     },
-    { /*  Abstract Control Management Functional Descriptor */
+    .acm_functional_descriptor = { /*  Abstract Control Management Functional Descriptor */
         0x04,         /*  bFunctionalLength = 4           */
         0x24,         /*  bDescriptorType                 */
         0x02,         /*  bDescriptorSubtype              */
         0x02,         /*  bmCapabilities                  */
     },
-    { /*  Union Functional Descriptor */
+    .union_functional_descriptor = { /*  Union Functional Descriptor */
         0x05,         /*  bFunctionalLength = 5           */
         0x24,         /*  bDescriptorType                 */
         0x06,         /*  bDescriptorSubtype              */
         0x00,         /*  bmMasterInterface               */
         0x01,         /*  bmSlaveInterface0               */
     },
-    { /*  IN Endpoint 3 (Descriptor #1) */
+    .ep_comm_in = { /*  IN Endpoint 3 (Descriptor #1) */
         0x07,         /*  bLength                          */
         0x05,         /*  bDescriptorType (Endpoint)       */
         0x83,         /*  bEndpointAddress (EP3-IN)        */
@@ -163,7 +143,7 @@ struct config_descriptor_s {
         0x0040,       /*  wMaxPacketSize                   */
         0xff,         /*  bInterval (milliseconds)         */
     },
-    { /*  Interface #2 Descriptor For Data Interface */
+    .if_data = { /*  Interface #2 Descriptor For Data Interface */
         0x09,         /*  bLength                          */
         0x04,         /*  bDescriptorType (Interface)      */
         0x01,         /*  bInterfaceNumber                 */
@@ -174,7 +154,7 @@ struct config_descriptor_s {
         0x00,         /*  bInterfaceProtocol = No class specific protocol (0) */
         0x00,         /*  biInterface = No Text String (0) (SWYM: biInterface? string? wat?)*/
     },
-    { /*  OUT Endpoint 1 (Descriptor #2) */
+    .ep_data_out = { /*  OUT Endpoint 1 (Descriptor #2) */
         0x07,         /*  bLength                          */
         0x05,         /*  bDescriptorType (Endpoint)       */
         0x01,         /*  bEndpointAddress (EP1-OUT)       */
@@ -182,7 +162,7 @@ struct config_descriptor_s {
         0x0040,       /*  wMaxPacketSize                   */
         0x00,         /*  bInterval (N/A)                  */
     },
-    { /*  IN Endpoint 2 (Descriptor #3) */
+    .ep_data_in = { /*  IN Endpoint 2 (Descriptor #3) */
         0x07,         /*  bLength                          */
         0x05,         /*  bDescriptorType (Endpoint)       */
         0x82,         /*  bEndpointAddress (EP2-IN)        */
@@ -191,7 +171,7 @@ struct config_descriptor_s {
         0x00          /*  bInterval (N/A)                  */
     },
     /********** Interface #3 : Mass Storage Device **********/
-    { /*  Second Interface Descriptor For MSC Interface */
+    .if_msc = {
         0x09,       /*  bLength = 9                     */
         0x04,       /*  bDescriptorType = Interface (4) */
         0x02,       /*  bInterfaceNumber                */
@@ -202,7 +182,7 @@ struct config_descriptor_s {
         0x50,       /*  bInterfaceProtocol = Bulk-Only Transport */
         0x05,       /*  iInterface                      */
     },
-    { /*  OUT Endpoint 1 (Descriptor #4) */
+    .ep_msc_out = {
         0x07,         /*  bLength                          */
         0x05,         /*  bDescriptorType (Endpoint)       */
         0x04,         /*  bEndpointAddress (EP4-OUT)       */
@@ -210,7 +190,7 @@ struct config_descriptor_s {
         0x0040,       /*  wMaxPacketSize                   */
         0x00,         /*  bInterval (N/A)                  */
     },
-    { /*  IN Endpoint 2 (Descriptor #5) */
+    .ep_msc_in = {
         0x07,         /*  bLength                          */
         0x05,         /*  bDescriptorType (Endpoint)       */
         0x85,         /*  bEndpointAddress (EP5-IN)        */
diff --git a/epicardium/meson.build b/epicardium/meson.build
index c5dc701d6164c79246e9a6aa8bc761c01626b32e..c8031c2f0ddb761766706527a3329d0510f3241a 100644
--- a/epicardium/meson.build
+++ b/epicardium/meson.build
@@ -71,6 +71,7 @@ subdir('l0der/')
 elf = executable(
   name + '.elf',
   'cdcacm.c',
+  'usb.c',
   'main.c',
   'support.c',
   module_sources,
diff --git a/epicardium/usb.c b/epicardium/usb.c
new file mode 100644
index 0000000000000000000000000000000000000000..3700c4f3831547e85a6d8f2e2b34b3d68c9d25ac
--- /dev/null
+++ b/epicardium/usb.c
@@ -0,0 +1,426 @@
+/**
+ * 
+ * 
+ * setting up USB basically consists of two parts:
+ * 
+ * - set up descriptors
+ * - initialize the corresponding MAXUSB stacks - acm, msc...
+ * 
+ * at the moment, the descriptors are statically initialized in
+ * descriptors.h several descriptors point to enumeration descriptors
+ * via iFooBar indizes. Those enumeration descriptors are registered
+ * via enum_register_descriptor(type, desc, idx), where the idx passed
+ * corresponds to the iFooBar index mentioned above.
+ * 
+ * There are several callbacks, some of which do not perform anything meaningful
+ * at the moment. For example usb_write_callback sets a global flag that is never
+ * read from. These will be removed later on.
+ * 
+ * The  initialization routines of acm & msc refer to the descriptors from which,
+ * among other things, they get their enpoint IDs. These are hard-coded right now
+ * but it would make sense to allocate these IDs at runtime. There is, AFAICT, no
+ * reason for these endpoint IDs to be 3, 1, 2 in the CDCACM case for example.
+ * 
+ * Allocating those at runtime would also make the setup less rigid: we can have all
+ * combinations of {cdcacm, storage} interfaces without the awkward descriptor hackery
+ * in epc_usb_init.
+ * 
+ * To generalize even further, the descriptors could be malloced. The total length of
+ * the descriptor structure can easily be derived from the number of interfaces to be
+ * configured. The memory allocated will then be split up (with alignment of the single
+ * descriptor structs taken care of) in a simple bump-allocator strategy on demand.
+ * 
+ * 
+ * MSC:
+ * 
+ * atm it is not possible to detect umount from the host. One would expect
+ * msc_stop to be called due to a CMD_START_STOP handled by msc_cbwReceived
+ * but this does not seem to be the case. At least for Linux hosts.
+ * On wireshark, one can see that, upon umount, a 
+ * USBMS packet "SCSI: prevent/allow removal" is sent. It looks as though this
+ * might reach the CMD_MEDIUM_REMOVAL case in msc_cbwReceived, in which the
+ * msc module does not invoke any callback / call mem.stop()...
+ * ...printf'ing from this case, it's clear that several CMD_MEDIUM_REMOVAL frames
+ * are received, even before mounting.
+ * ...alright, there's several pairs of prevent/allow coming in. There are no
+ * other parameters in the frame that seem to signify "I am actually accessing the FS"
+ * which makes sense, it's mass storage - it doesn't care if there is an FS or not.
+ * Some of these pre-mount prevent/allow pairs bracket mem.read() calls at different addresses.
+ * The only way a mount by an OS could be detected is:
+ *  1: check of prevent is asserted for a certain time
+ *  2: check if, in that time, an address range from 0x00..sizeof(FAT) has been read
+ * where 2 is probably not a solid indicator, since OSes besides Linux may (wrongfully?)
+ * not re-read the FAT after asserting prevent post-mount.
+ * 
+ */
+#include <stdio.h>
+#include <stddef.h>
+
+#include "cdcacm.h"
+#include "mxc_config.h"
+#include "mxc_sys.h"
+#include "mxc_delay.h"
+#include "usb.h"
+#include "usb_event.h"
+#include "enumerate.h"
+
+#include "descriptors.h"
+#include "msc.h"
+#include "cdc_acm.h"
+
+#include "modules/log.h"
+#include "modules/filesystem.h"
+
+
+/* instead of having three callbacks for setconfig, setfeature and clrfeature, we're
+ * using a single callback and pass one of three tags as cbdata parameter
+ * to enum_register_callback
+ */
+
+enum usb_setup_callback_type {
+    USBSC_SetConfig,
+    USBSC_SetFeature,
+    USBSC_ClrFeature,
+};
+struct usb_setup_callback_tag {
+    enum usb_setup_callback_type which;
+    //potentially needed callback data can be placed here like this:
+    // union {
+    //     struct {} setconfig;
+    //     struct {} setfeature;
+    //     struct {} clrfeature;
+    // } data;
+};
+
+
+/***** Function Prototypes *****/
+static int cb_usb_setup(usb_setup_pkt *sud, void *cbdata);
+static int cb_usb_event(maxusb_event_t evt, void *data);
+static int cb_usb_shutdown();
+static int cb_usb_init();
+static int cb_acm_read_ready(void);
+static void usb_app_sleep(void);
+static void usb_app_wakeup(void);
+static int deconfigure(void);
+/* needed for usb_opts. mxc_delay() takes unsigned long, so can't use it directly */
+static void delay_us(unsigned int usec);
+
+
+static const struct usb_setup_callback_tag s_callbackData_SetConfig = {
+    .which = USBSC_SetConfig,
+};
+static const struct usb_setup_callback_tag s_callbackData_SetFeature = {
+    .which = USBSC_SetFeature,
+};
+static const struct usb_setup_callback_tag s_callbackData_ClrFeature = {
+    .which = USBSC_ClrFeature,
+};
+
+volatile int suspended;
+int remote_wake_en; //SWYM: unused, only written to!
+static volatile int usb_read_complete; // SWYM: only ever written to
+static volatile bool initialized  = false;
+uint16_t configured;
+uint16_t initialized;
+
+
+int cb_usb_init()
+{
+	const sys_cfg_usbhs_t sys_usbhs_cfg = NULL;
+	LOG_INFO("usb", "SYS_USBHS_Init");
+	return SYS_USBHS_Init(&sys_usbhs_cfg);
+}
+
+int cb_usb_shutdown()
+{
+	LOG_INFO("usb", "SYS_USBHS_Shutdown");
+	SYS_USBHS_Shutdown();
+	SYS_Reset_Periph(SYS_RESET_USB);
+	if (configured & USB_IFACE_STORAGE) {
+		LOG_INFO("usb", "re-attaching FLASH");
+		fatfs_attach();
+		configured &= ~USB_IFACE_STORAGE
+	}
+	return 0;
+}
+
+/* User-supplied function to delay usec micro-seconds */
+static void delay_us(unsigned int usec)
+{
+	/* mxc_delay() takes unsigned long, so can't use it directly */
+	mxc_delay(usec);
+}
+
+/******************************************************************************/
+int epc_usb_init(uint16_t interfaces)
+{
+	if (initialized) {
+		//NVIC_DisableIRQ(USB_IRQn); //yes? no?
+
+		usb_disconnect();
+		deconfigure();
+		//usb_app_sleep();
+		usb_shutdown();
+		initialized = 0;
+	}
+	if (interfaces == 0) {
+		return 0;
+	}
+	maxusb_cfg_options_t usb_opts;
+
+	/* Initialize state */
+	configured     = 0;
+	suspended      = 0;
+	remote_wake_en = 0;
+
+	/* Start out in full speed */
+	usb_opts.enable_hs         = 0;
+	usb_opts.delay_us          = delay_us;
+	usb_opts.init_callback     = cb_usb_init;
+	usb_opts.shutdown_callback = cb_usb_shutdown;
+
+	/* Initialize the usb module */
+	if (usb_init(&usb_opts) != 0) {
+		LOG_ERR("cdcacm", "usb_init() failed");
+		return -EIO;
+	}
+
+	/* Initialize the enumeration module */
+	if (enum_init() != 0) {
+		usb_shutdown();
+		LOG_ERR("cdcacm", "enum_init() failed");
+		return -EIO;
+	}
+
+	/* Register enumeration data */
+	if (interfaces & USB_IFACE_STORAGE) {
+		config_descriptor.config_descriptor.wTotalLength =
+			sizeof(config_descriptor);
+		config_descriptor.config_descriptor.bNumInterfaces = 3;
+	} else {
+		config_descriptor.config_descriptor.wTotalLength = offsetof(
+			struct config_descriptor_s, if_msc
+		);
+		config_descriptor.config_descriptor.bNumInterfaces = 2;
+	}
+	enum_register_descriptor(
+		ENUM_DESC_DEVICE, (uint8_t *)&composite_device_descriptor, 0
+	);
+	enum_register_descriptor(
+		ENUM_DESC_CONFIG, (uint8_t *)&config_descriptor, 0
+	);
+	enum_register_descriptor(ENUM_DESC_STRING, lang_id_desc, 0);
+	enum_register_descriptor(ENUM_DESC_STRING, mfg_id_desc, 1);
+	enum_register_descriptor(ENUM_DESC_STRING, prod_id_desc, 2);
+	//used in composite but not in cdc (see iSerialNumber)
+    //TODO: what do we want our serial to be?
+	enum_register_descriptor(ENUM_DESC_STRING, serial_id_desc, 3);
+	enum_register_descriptor(ENUM_DESC_STRING, cdcacm_func_desc, 4);
+	enum_register_descriptor(ENUM_DESC_STRING, msc_func_desc, 5);
+
+	/* Handle configuration */
+	enum_register_callback(ENUM_SETCONFIG, cb_usb_setup, (void*)&s_callbackData_SetConfig);
+
+	/* Handle feature set/clear */
+	enum_register_callback(ENUM_SETFEATURE, cb_usb_setup, (void*)&s_callbackData_SetFeature);
+	enum_register_callback(ENUM_CLRFEATURE, cb_usb_setup, (void*)&s_callbackData_ClrFeature);
+
+	if (interfaces & USB_IFACE_CDCACM) {
+		if (acm_init(&config_descriptor.if_comm) != 0) {
+			enum_clearconfig();
+			usb_shutdown();
+			LOG_ERR("cdcacm", "acm_init() failed");
+			return -EIO;
+		} else {
+			configured |= USB_IFACE_CDCACM;
+		}
+	}
+
+	if (interfaces & USB_IFACE_STORAGE) {
+		/* Initialize the class driver */
+		static const msc_idstrings_t ids = {
+			"CCC",    /* Vendor string.  Maximum of 8 bytes */
+			"card10", /* Product string.  Maximum of 16 bytes */
+			"1.0"     /* Version string.  Maximum of 4 bytes */
+		};
+
+		configured |= USB_IFACE_STORAGE;
+		LOG_INFO("usb", "detaching FLASH");
+		fatfs_detach(); //SWYM: move to mscmem_init
+
+		/* Functions to control "disk" memory. See msc.h for definitions. */
+		int mscmem_init(void);
+		int mscmem_start(void);
+		int mscmem_stop(void);
+		uint32_t mscmem_size(void);
+		int mscmem_read(uint32_t lba, uint8_t * buffer);
+		int mscmem_write(uint32_t lba, uint8_t * buffer);
+		int mscmem_ready(void);
+
+		static const msc_mem_t mem = {
+			mscmem_init, mscmem_start, mscmem_stop,  mscmem_ready,
+			mscmem_size, mscmem_read,  mscmem_write,
+		};
+		if (msc_init(
+			    &config_descriptor.if_msc,
+			    &ids,
+			    &mem) != 0) {
+			LOG_ERR("msc", "msc_init() failed\n");
+			return -EIO;
+		}
+	}
+
+	/* Register callbacks */
+	usb_event_enable(MAXUSB_EVENT_NOVBUS, cb_usb_event, NULL);
+	usb_event_enable(MAXUSB_EVENT_VBUS, cb_usb_event, NULL);
+	acm_register_callback(ACM_CB_READ_READY, cb_acm_read_ready); //SWYM: actually not needed
+	usb_read_complete = 0;
+
+	/* Start with USB in low power mode */
+	usb_app_sleep();
+	/* TODO: Fix priority */
+	NVIC_SetPriority(USB_IRQn, 6);
+	NVIC_EnableIRQ(USB_IRQn);
+
+	initialized = true;
+
+	return 0;
+}
+
+static int cb_usb_setup(usb_setup_pkt *sud, void *cbdata)
+{
+    const struct usb_setup_callback_tag* self = (const struct usb_setup_callback_tag*)cbdata;
+    switch(self->which) {
+    case USBSC_SetConfig:
+        if (sud->wValue ==
+            config_descriptor.config_descriptor.bConfigurationValue)
+        {
+            int acm_rc = 0;
+			if (configured & USB_IFACE_CDCACM) {
+				const acm_cfg_t acm_cfg = {
+					config_descriptor.ep_data_out.bEndpointAddress,
+					MXC_USBHS_MAX_PACKET, /* OUT max packet size */
+					config_descriptor.ep_data_in.bEndpointAddress & 0x7,
+					MXC_USBHS_MAX_PACKET, /* IN max packet size */
+					config_descriptor.ep_comm_in.bEndpointAddress & 0x7,
+					MXC_USBHS_MAX_PACKET, /* Notify max packet size */
+				};
+
+				acm_configure(&acm_cfg);
+				if (acm_rc) {
+					LOG_ERR("usb", "acm_configure failed: %d\n", acm_rc);
+				} else {
+					initialized |= USB_IFACE_CDCACM;
+				}
+			}
+			int msc_rc = 0;
+			if (configured & USB_IFACE_STORAGE) {
+				const msc_cfg_t msc_cfg = {
+					config_descriptor.ep_msc_out.bEndpointAddress,
+					MXC_USBHS_MAX_PACKET, /* OUT max packet size */
+					config_descriptor.ep_msc_out.bEndpointAddress & 0x7,
+					MXC_USBHS_MAX_PACKET, /* IN max packet size */
+				};
+				msc_rc = msc_configure(&msc_cfg);
+				if (msc_rc) {
+					LOG_ERR("usb", "msc_configure failed: %d\n", msc_rc);
+				} else {
+					initialized |= USB_IFACE_STORAGE;
+				}
+			}
+            return acm_rc || msc_rc;
+        } else if (sud->wValue == 0) {
+            return deconfigure();
+        }
+        break;
+    case USBSC_SetFeature:
+        if (sud->wValue == FEAT_REMOTE_WAKE) {
+            remote_wake_en = 1;
+            return 0;
+        }
+        break;
+    case USBSC_ClrFeature:
+        if (sud->wValue == FEAT_REMOTE_WAKE) {
+            remote_wake_en = 0;
+            return 0;
+        }
+        break;
+    }
+    return -1;
+}
+
+/******************************************************************************/
+static void usb_app_sleep(void)
+{
+	/* TODO: Place low-power code here */
+	suspended = 1;
+}
+
+/******************************************************************************/
+static void usb_app_wakeup(void)
+{
+	/* TODO: Place low-power code here */
+	suspended = 0;
+}
+
+static int deconfigure(void)
+{
+	enum_clearconfig();
+	int rc_acm = 0;
+	int rc_msc = 0;
+	if (initialized & USB_IFACE_CDCACM) {
+		rc_acm = acm_deconfigure();
+	}
+	if (initialized & USB_IFACE_STORAGE) {
+		rc_msc = msc_deconfigure();
+	}
+	initialized = 0;
+	return rc_acm || rc_msc;
+}
+/******************************************************************************/
+static int cb_usb_event(maxusb_event_t evt, void *data)
+{
+	LOG_INFO("usb", "event %d\n", evt);
+
+	switch (evt) {
+	case MAXUSB_EVENT_NOVBUS:
+		usb_event_disable(MAXUSB_EVENT_BRST);
+		usb_event_disable(MAXUSB_EVENT_SUSP);
+		usb_event_disable(MAXUSB_EVENT_DPACT);
+		usb_disconnect();
+		deconfigure();
+		usb_app_sleep();
+		break;
+	case MAXUSB_EVENT_VBUS:
+		usb_event_clear(MAXUSB_EVENT_BRST);
+		usb_event_enable(MAXUSB_EVENT_BRST, cb_usb_event, NULL);
+		usb_event_clear(MAXUSB_EVENT_SUSP);
+		usb_event_enable(MAXUSB_EVENT_SUSP, cb_usb_event, NULL);
+		usb_connect();
+		usb_app_sleep();
+		break;
+	case MAXUSB_EVENT_BRST:
+		usb_app_wakeup();
+		deconfigure();
+		suspended = 0;
+		break;
+	case MAXUSB_EVENT_SUSP:
+		usb_app_sleep();
+		break;
+	case MAXUSB_EVENT_DPACT:
+		usb_app_wakeup();
+		break;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+/******************************************************************************/
+static int cb_acm_read_ready(void)
+{
+	usb_read_complete = 1;
+	return 0;
+}
+
diff --git a/lib/sdk/Libraries/MAXUSB/src/devclass/msc.c b/lib/sdk/Libraries/MAXUSB/src/devclass/msc.c
index 897cbf33eb12e15abfe154e54fa3bf87a239b332..df214a6ad0ae2b4d1f39c687f249c2814f08f499 100644
--- a/lib/sdk/Libraries/MAXUSB/src/devclass/msc.c
+++ b/lib/sdk/Libraries/MAXUSB/src/devclass/msc.c
@@ -40,6 +40,7 @@
 #include "usb_event.h"
 #include "enumerate.h"
 #include "msc.h"
+#include <stdio.h>
 
 /***** Definitions *****/
 
@@ -381,6 +382,7 @@ static void msc_cbwReceived(void* cbdata)
                 msc_sendModeSense();
                 break;
             case CMD_MEDIUM_REMOVAL:
+                printf("CMD_MEDIUM_REMOVAL: %s\n", *(req_data + CBW_CB_IDX + 4) ? "prevent" : "allow");
                 /* This command only requires a CSW to be sent back. */
                 msc_sendCSW();
                 break;
diff --git a/pycardium/modules/usb.c b/pycardium/modules/usb.c
new file mode 100644
index 0000000000000000000000000000000000000000..1b178abc1d0af0609de450d1cfe473c02edd9af3
--- /dev/null
+++ b/pycardium/modules/usb.c
@@ -0,0 +1,44 @@
+#include "py/obj.h"
+#include "py/runtime.h"
+#include "py/builtin.h"
+
+#include "epicardium.h"
+
+static mp_obj_t mp_usb_shutdown()
+{
+    epic_usb_shutdown();
+	return mp_const_none;
+}
+
+static mp_obj_t mp_usb_storage()
+{
+    epic_usb_storage();
+	return mp_const_none;
+}
+
+static mp_obj_t mp_usb_cdcacm()
+{
+    epic_usb_cdcacm();
+	return mp_const_none;
+}
+static MP_DEFINE_CONST_FUN_OBJ_0(usb_shutdown_obj, mp_usb_shutdown);
+static MP_DEFINE_CONST_FUN_OBJ_0(usb_storage_obj, mp_usb_storage);
+static MP_DEFINE_CONST_FUN_OBJ_0(usb_cdcacm_obj, mp_usb_cdcacm);
+
+static const mp_rom_map_elem_t usb_module_globals_table[] = {
+	{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_usb) },
+	{ MP_ROM_QSTR(MP_QSTR_shutdown), MP_ROM_PTR(&usb_shutdown_obj) },
+	{ MP_ROM_QSTR(MP_QSTR_storage), MP_ROM_PTR(&usb_storage_obj) },
+	{ MP_ROM_QSTR(MP_QSTR_cdcacm), MP_ROM_PTR(&usb_cdcacm_obj) },
+};
+static MP_DEFINE_CONST_DICT(usb_module_globals, usb_module_globals_table);
+
+// Define module object.
+const mp_obj_module_t usb_module = {
+	.base    = { &mp_type_module },
+	.globals = (mp_obj_dict_t *)&usb_module_globals,
+};
+
+/* Register the module to make it available in Python */
+/* clang-format off */
+MP_REGISTER_MODULE(MP_QSTR_usb, usb_module, 1);