123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341 |
- /**
- * \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*)µsoft_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*)µsoft_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 = µsoft_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
|