aboutsummaryrefslogtreecommitdiff
path: root/Marlin/src/HAL/DUE/usb/usb_task.c
diff options
context:
space:
mode:
Diffstat (limited to 'Marlin/src/HAL/DUE/usb/usb_task.c')
-rw-r--r--Marlin/src/HAL/DUE/usb/usb_task.c341
1 files changed, 341 insertions, 0 deletions
diff --git a/Marlin/src/HAL/DUE/usb/usb_task.c b/Marlin/src/HAL/DUE/usb/usb_task.c
new file mode 100644
index 0000000..66bdb26
--- /dev/null
+++ b/Marlin/src/HAL/DUE/usb/usb_task.c
@@ -0,0 +1,341 @@
+/**
+ * \file
+ *
+ * \brief Main functions for USB composite example
+ *
+ * Copyright (c) 2011-2015 Atmel Corporation. All rights reserved.
+ *
+ * \asf_license_start
+ *
+ * \page License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. The name of Atmel may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * 4. This software may only be redistributed and used in connection with an
+ * Atmel microcontroller product.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * \asf_license_stop
+ *
+ */
+
+// Support and FAQ: visit <a href="https://www.atmel.com/design-support/">Atmel Support</a>
+
+#ifdef ARDUINO_ARCH_SAM
+
+#include <Arduino.h>
+#include <Reset.h>
+
+#include "conf_usb.h"
+#include "udc.h"
+
+#if ENABLED(SDSUPPORT)
+ static volatile bool main_b_msc_enable = false;
+#endif
+static volatile bool main_b_cdc_enable = false;
+static volatile bool main_b_dtr_active = false;
+
+void usb_task_idle(void) {
+ #if ENABLED(SDSUPPORT)
+ // Attend SD card access from the USB MSD -- Prioritize access to improve speed
+ int delay = 2;
+ while (main_b_msc_enable && --delay > 0) {
+ if (udi_msc_process_trans()) delay = 10000;
+
+ // Reset the watchdog, just to be sure
+ REG_WDT_CR = WDT_CR_WDRSTT | WDT_CR_KEY(0xA5);
+ }
+ #endif
+}
+
+#if ENABLED(SDSUPPORT)
+ bool usb_task_msc_enable(void) { return ((main_b_msc_enable = true)); }
+ void usb_task_msc_disable(void) { main_b_msc_enable = false; }
+ bool usb_task_msc_isenabled(void) { return main_b_msc_enable; }
+#endif
+
+bool usb_task_cdc_enable(const uint8_t port) { UNUSED(port); return ((main_b_cdc_enable = true)); }
+void usb_task_cdc_disable(const uint8_t port) { UNUSED(port); main_b_cdc_enable = false; main_b_dtr_active = false; }
+bool usb_task_cdc_isenabled(void) { return main_b_cdc_enable; }
+
+/*! \brief Called by CDC interface
+ * Callback running when CDC device have received data
+ */
+void usb_task_cdc_rx_notify(const uint8_t port) { UNUSED(port); }
+
+/*! \brief Configures communication line
+ *
+ * \param cfg line configuration
+ */
+static uint16_t dwDTERate = 0;
+void usb_task_cdc_config(const uint8_t port, usb_cdc_line_coding_t *cfg) {
+ UNUSED(port);
+ // Store last DTE rate
+ dwDTERate = cfg->dwDTERate;
+}
+
+void usb_task_cdc_set_dtr(const uint8_t port, const bool b_enable) {
+ UNUSED(port);
+ // Keep DTR status
+ main_b_dtr_active = b_enable;
+
+ // Implement Arduino-Compatible kludge to enter programming mode from
+ // the native port:
+ // "Auto-reset into the bootloader is triggered when the port, already
+ // open at 1200 bps, is closed."
+
+ if (1200 == dwDTERate) {
+ // We check DTR state to determine if host port is open (bit 0 of lineState).
+ if (!b_enable) {
+
+ // Set RST pin to go low for 65535 clock cycles on reset
+ // This helps restarting when firmware flash ends
+ RSTC->RSTC_MR = 0xA5000F01;
+
+ // Schedule delayed reset
+ initiateReset(250);
+ }
+ else
+ cancelReset();
+ }
+}
+
+bool usb_task_cdc_dtr_active(void) { return main_b_dtr_active; }
+
+/// Microsoft WCID descriptor
+typedef struct USB_MicrosoftCompatibleDescriptor_Interface {
+ uint8_t bFirstInterfaceNumber;
+ uint8_t reserved1;
+ uint8_t compatibleID[8];
+ uint8_t subCompatibleID[8];
+ uint8_t reserved2[6];
+} __attribute__((packed)) USB_MicrosoftCompatibleDescriptor_Interface;
+
+typedef struct USB_MicrosoftCompatibleDescriptor {
+ uint32_t dwLength;
+ uint16_t bcdVersion;
+ uint16_t wIndex;
+ uint8_t bCount;
+ uint8_t reserved[7];
+ USB_MicrosoftCompatibleDescriptor_Interface interfaces[];
+} __attribute__((packed)) USB_MicrosoftCompatibleDescriptor;
+
+// 3D Printer compatible descriptor
+static USB_MicrosoftCompatibleDescriptor microsoft_compatible_id_descriptor = {
+ .dwLength = sizeof(USB_MicrosoftCompatibleDescriptor) +
+ 1*sizeof(USB_MicrosoftCompatibleDescriptor_Interface),
+ .bcdVersion = 0x0100,
+ .wIndex = 0x0004,
+ .bCount = 1,
+ .reserved = {0, 0, 0, 0, 0, 0, 0},
+ .interfaces = {
+ {
+ .bFirstInterfaceNumber = 0,
+ .reserved1 = 1,
+ .compatibleID = "3DPRINT",
+ .subCompatibleID = {0, 0, 0, 0, 0, 0, 0, 0},
+ .reserved2 = {0, 0, 0, 0, 0, 0},
+ }
+ }
+};
+
+#define xstr(s) str(s)
+#define str(s) #s
+
+#define MS3DPRINT_CONFIG u"MS3DPrintConfig"
+#define MS3DPRINT_CONFIG_DATA \
+ u"Base=SD\0"\
+ u"Job3DOutputAreaWidth=" xstr(X_BED_SIZE) "000\0"\
+ u"Job3DOutputAreaDepth=" xstr(Y_BED_SIZE) "000\0"\
+ u"Job3DOutputAreaHeight=" xstr(Z_MAX_POS) "000\0"\
+ u"filamentdiameter=1750\0"
+
+typedef struct USB_MicrosoftExtendedPropertiesDescriptor {
+ uint32_t dwLength;
+ uint16_t bcdVersion;
+ uint16_t wIndex;
+ uint16_t bCount;
+ uint32_t dwPropertySize;
+ uint32_t dwPropertyDataType;
+ uint16_t wPropertyNameLength;
+ uint16_t PropertyName[sizeof(MS3DPRINT_CONFIG)/sizeof(uint16_t)];
+ uint32_t dwPropertyDataLength;
+ uint16_t PropertyData[sizeof(MS3DPRINT_CONFIG_DATA)/sizeof(uint16_t)];
+} __attribute__((packed)) USB_MicrosoftExtendedPropertiesDescriptor;
+
+static USB_MicrosoftExtendedPropertiesDescriptor microsoft_extended_properties_descriptor = {
+ .dwLength = sizeof(USB_MicrosoftExtendedPropertiesDescriptor),
+ .bcdVersion = 0x0100,
+ .wIndex = 0x0005,
+ .bCount = 1,
+
+ .dwPropertySize = 4 + 4 + 2 + 4 + sizeof(MS3DPRINT_CONFIG) + sizeof(MS3DPRINT_CONFIG_DATA),
+ .dwPropertyDataType = 7, // (1=REG_SZ, 4=REG_DWORD, 7=REG_MULTI_SZ)
+ .wPropertyNameLength = sizeof(MS3DPRINT_CONFIG),
+ .PropertyName = MS3DPRINT_CONFIG,
+ .dwPropertyDataLength = sizeof(MS3DPRINT_CONFIG_DATA),
+ .PropertyData = MS3DPRINT_CONFIG_DATA
+};
+
+/**************************************************************************************************
+** WCID configuration information
+** Hooked into UDC via UDC_GET_EXTRA_STRING #define.
+*/
+bool usb_task_extra_string(void) {
+ static uint8_t udi_msft_magic[] = "MSFT100\xEE";
+ static uint8_t udi_cdc_name[] = "CDC interface";
+ #if ENABLED(SDSUPPORT)
+ static uint8_t udi_msc_name[] = "MSC interface";
+ #endif
+
+ struct extra_strings_desc_t {
+ usb_str_desc_t header;
+ #if ENABLED(SDSUPPORT)
+ le16_t string[Max(Max(sizeof(udi_cdc_name) - 1, sizeof(udi_msc_name) - 1), sizeof(udi_msft_magic) - 1)];
+ #else
+ le16_t string[Max(sizeof(udi_cdc_name) - 1, sizeof(udi_msft_magic) - 1)];
+ #endif
+ };
+ static UDC_DESC_STORAGE struct extra_strings_desc_t extra_strings_desc = {
+ .header.bDescriptorType = USB_DT_STRING
+ };
+
+ uint8_t *str;
+ uint8_t str_lgt = 0;
+
+ // Link payload pointer to the string corresponding at request
+ switch (udd_g_ctrlreq.req.wValue & 0xFF) {
+ case UDI_CDC_IAD_STRING_ID:
+ str_lgt = sizeof(udi_cdc_name) - 1;
+ str = udi_cdc_name;
+ break;
+ #if ENABLED(SDSUPPORT)
+ case UDI_MSC_STRING_ID:
+ str_lgt = sizeof(udi_msc_name) - 1;
+ str = udi_msc_name;
+ break;
+ #endif
+ case 0xEE:
+ str_lgt = sizeof(udi_msft_magic) - 1;
+ str = udi_msft_magic;
+ break;
+ default:
+ return false;
+ }
+
+ for (uint8_t i = 0; i < str_lgt; i++)
+ extra_strings_desc.string[i] = cpu_to_le16((le16_t)str[i]);
+
+ extra_strings_desc.header.bLength = 2 + str_lgt * 2;
+ udd_g_ctrlreq.payload_size = extra_strings_desc.header.bLength;
+ udd_g_ctrlreq.payload = (uint8_t*)&extra_strings_desc;
+
+ // if the string is larger than request length, then cut it
+ if (udd_g_ctrlreq.payload_size > udd_g_ctrlreq.req.wLength) {
+ udd_g_ctrlreq.payload_size = udd_g_ctrlreq.req.wLength;
+ }
+
+ return true;
+}
+
+/**************************************************************************************************
+** Handle device requests that the ASF stack doesn't
+*/
+bool usb_task_other_requests(void) {
+ uint8_t* ptr = 0;
+ uint16_t size = 0;
+
+ if (Udd_setup_type() == USB_REQ_TYPE_VENDOR) {
+ //if (udd_g_ctrlreq.req.bRequest == 0x30)
+ if (1) {
+ if (udd_g_ctrlreq.req.wIndex == 0x04) {
+ ptr = (uint8_t*)&microsoft_compatible_id_descriptor;
+ size = (udd_g_ctrlreq.req.wLength);
+ if (size > microsoft_compatible_id_descriptor.dwLength)
+ size = microsoft_compatible_id_descriptor.dwLength;
+ }
+ else if (udd_g_ctrlreq.req.wIndex == 0x05) {
+ ptr = (uint8_t*)&microsoft_extended_properties_descriptor;
+ size = (udd_g_ctrlreq.req.wLength);
+ if (size > microsoft_extended_properties_descriptor.dwLength)
+ size = microsoft_extended_properties_descriptor.dwLength;
+ }
+ else
+ return false;
+ }
+ }
+
+ udd_g_ctrlreq.payload_size = size;
+ if (size == 0) {
+ udd_g_ctrlreq.callback = 0;
+ udd_g_ctrlreq.over_under_run = 0;
+ }
+ else
+ udd_g_ctrlreq.payload = ptr;
+
+ return true;
+}
+
+void usb_task_init(void) {
+
+ uint16_t *ptr;
+
+ // Disable USB peripheral so we start clean and avoid lockups
+ otg_disable();
+ udd_disable();
+
+ // Set the USB interrupt to our stack
+ UDD_SetStack(&USBD_ISR);
+
+ // Start USB stack to authorize VBus monitoring
+ udc_start();
+
+ // Patch in filament diameter - Be careful: String is in UNICODE (2bytes per char)
+ ptr = &microsoft_extended_properties_descriptor.PropertyData[0];
+ while (ptr[0] || ptr[1]) { // Double 0 flags end of resource
+
+ // Found the filamentdiameter= unicode string
+ if (ptr[0] == 'r' && ptr[1] == '=') {
+ char diam[16];
+ char *sptr;
+
+ // Patch in the filament diameter
+ sprintf_P(diam, PSTR("%d"), (int)((DEFAULT_NOMINAL_FILAMENT_DIA) * 1000.0));
+
+ // And copy it to the proper place, expanding it to unicode
+ sptr = &diam[0];
+ ptr += 2;
+ while (*sptr) *ptr++ = *sptr++;
+
+ // Done!
+ break;
+ }
+
+ // Go to the next character
+ ptr++;
+ }
+}
+
+#endif // ARDUINO_ARCH_SAM