From ddd3418a4faabdfb82bef69ec62e2560125c919b Mon Sep 17 00:00:00 2001 From: Zach Eveland Date: Sun, 14 Aug 2011 16:59:34 -0400 Subject: Serial via USB works Integrated rest of Peter's USB implementation --- cores/arduino/CDC.cpp | 162 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 162 insertions(+) create mode 100644 cores/arduino/CDC.cpp (limited to 'cores/arduino/CDC.cpp') diff --git a/cores/arduino/CDC.cpp b/cores/arduino/CDC.cpp new file mode 100644 index 0000000..05d0c18 --- /dev/null +++ b/cores/arduino/CDC.cpp @@ -0,0 +1,162 @@ + + +/* Copyright (c) 2011, Peter Barrett +** +** Permission to use, copy, modify, and/or distribute this software for +** any purpose with or without fee is hereby granted, provided that the +** above copyright notice and this permission notice appear in all copies. +** +** THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL +** WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +** WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR +** BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES +** OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +** WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +** ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +** SOFTWARE. +*/ + +#include "Platform.h" +#include "USBAPI.h" +#include + +#ifdef CDC_ENABLED + +// TODO: Should really use the wdt here +// Not currently working for a non-obvious reason + +typedef void (*AppPtr_t)(void) __attribute__ ((noreturn)); +AppPtr_t Bootloader = (AppPtr_t)(30*1024); + +void Reboot() +{ + USB.detach(); + cli(); + Bootloader(); + //wdt_enable(WDTO_15MS); + //while(1); // reboot +} + +typedef struct +{ + u32 dwDTERate; + u8 bCharFormat; + u8 bParityType; + u8 bDataBits; + u8 lineState; +} LineInfo; + +static volatile LineInfo _usbLineInfo = { 57600, 0x00, 0x00, 0x00, 0x00 }; + +#define WEAK __attribute__ ((weak)) + +extern const CDCDescriptor _cdcInterface PROGMEM; +const CDCDescriptor _cdcInterface = +{ + D_IAD(0,2,CDC_COMMUNICATION_INTERFACE_CLASS,CDC_ABSTRACT_CONTROL_MODEL,1), + + // CDC communication interface + D_INTERFACE(CDC_ACM_INTERFACE,1,CDC_COMMUNICATION_INTERFACE_CLASS,CDC_ABSTRACT_CONTROL_MODEL,0), + D_CDCCS(CDC_HEADER,0x10,0x01), // Header (1.10 bcd) + D_CDCCS(CDC_CALL_MANAGEMENT,1,1), // Device handles call management (not) + D_CDCCS4(CDC_ABSTRACT_CONTROL_MANAGEMENT,6), // SET_LINE_CODING, GET_LINE_CODING, SET_CONTROL_LINE_STATE supported + D_CDCCS(CDC_UNION,CDC_ACM_INTERFACE,CDC_DATA_INTERFACE), // Communication interface is master, data interface is slave 0 + D_ENDPOINT(USB_ENDPOINT_IN (CDC_ENDPOINT_ACM),USB_ENDPOINT_TYPE_INTERRUPT,0x10,0x40), + + // CDC data interface + D_INTERFACE(CDC_DATA_INTERFACE,2,CDC_DATA_INTERFACE_CLASS,0,0), + D_ENDPOINT(USB_ENDPOINT_OUT(CDC_ENDPOINT_OUT),USB_ENDPOINT_TYPE_BULK,0x40,0), + D_ENDPOINT(USB_ENDPOINT_IN (CDC_ENDPOINT_IN ),USB_ENDPOINT_TYPE_BULK,0x40,0) +}; + +int WEAK CDC_GetInterface(u8* interfaceNum) +{ + interfaceNum[0] += 2; // uses 2 + return USB_SendControl(TRANSFER_PGM,&_cdcInterface,sizeof(_cdcInterface)); +} + +bool WEAK CDC_Setup(Setup& setup) +{ + u8 r = setup.bRequest; + u8 requestType = setup.bmRequestType; + + if (REQUEST_DEVICETOHOST_CLASS_INTERFACE == requestType) + { + if (CDC_GET_LINE_CODING == r) + { + USB_SendControl(0,(void*)&_usbLineInfo,7); + return true; + } + } + + if (REQUEST_HOSTTODEVICE_CLASS_INTERFACE == requestType) + { + if (CDC_SET_LINE_CODING == r) + { + USB_RecvControl((void*)&_usbLineInfo,7); + return true; + } + + if (CDC_SET_CONTROL_LINE_STATE == r) + { + _usbLineInfo.lineState = setup.wValueL; + if (_usbLineInfo.dwDTERate == 115200 && _usbLineInfo.lineState == 0) // Emulate DTR reset hack + Reboot(); + return true; + } + } + return false; +} + + +int _serialPeek = -1; +void Serial_::begin(uint16_t baud_count) +{ +} + +void Serial_::end(void) +{ +} + +int Serial_::available(void) +{ + u8 avail = USB_Available(CDC_RX); + if (_serialPeek != -1) + avail++; + return avail; +} + +// peek is nasty +int Serial_::peek(void) +{ + if (_serialPeek == -1) + _serialPeek = read(); + return _serialPeek; +} + +int Serial_::read(void) +{ + int c; + if (_serialPeek != -1) + { + c = _serialPeek; + _serialPeek = -1; + } else { + c = USB_Recv(CDC_RX); + } + return c; +} + +void Serial_::flush(void) +{ + USB_Flush(CDC_TX); +} + +void Serial_::write(uint8_t c) +{ + USB_Send(CDC_TX,&c,1); +} + +Serial_ Serial; + +#endif -- cgit v1.2.3-18-g5258