diff --git a/hardware/arduino/sam/cores/arduino/USB/CDC.cpp b/hardware/arduino/sam/cores/arduino/USB/CDC.cpp index 9ab8356d9..1df3061e3 100644 --- a/hardware/arduino/sam/cores/arduino/USB/CDC.cpp +++ b/hardware/arduino/sam/cores/arduino/USB/CDC.cpp @@ -55,6 +55,8 @@ static volatile LineInfo _usbLineInfo = { 0x00 // lineState }; +static volatile int32_t breakValue = -1; + _Pragma("pack(1)") static const CDCDescriptor _cdcInterface = { @@ -144,6 +146,7 @@ bool WEAK CDC_Setup(USBSetup& setup) if (CDC_SEND_BREAK == r) { + breakValue = ((uint16_t)setup.wValueH << 8) | setup.wValueL; return true; } } @@ -305,6 +308,28 @@ Serial_::operator bool() return result; } +int32_t Serial_::readBreak() { + uint8_t enableInterrupts = ((__get_PRIMASK() & 0x1) == 0 && + (__get_FAULTMASK() & 0x1) == 0); + + // disable interrupts, + // to avoid clearing a breakValue that might occur + // while processing the current break value + __disable_irq(); + + int ret = breakValue; + + breakValue = -1; + + if (enableInterrupts) + { + // re-enable the interrupts + __enable_irq(); + } + + return ret; +} + unsigned long Serial_::baud() { return _usbLineInfo.dwDTERate; } diff --git a/hardware/arduino/sam/cores/arduino/USB/USBAPI.h b/hardware/arduino/sam/cores/arduino/USB/USBAPI.h index dbc2ec5dc..2eeaca08e 100644 --- a/hardware/arduino/sam/cores/arduino/USB/USBAPI.h +++ b/hardware/arduino/sam/cores/arduino/USB/USBAPI.h @@ -63,6 +63,23 @@ public: using Print::write; // pull in write(str) from Print operator bool(); + // This method allows processing "SEND_BREAK" requests sent by + // the USB host. Those requests indicate that the host wants to + // send a BREAK signal and are accompanied by a single uint16_t + // value, specifying the duration of the break. The value 0 + // means to end any current break, while the value 0xffff means + // to start an indefinite break. + // readBreak() will return the value of the most recent break + // request, but will return it at most once, returning -1 when + // readBreak() is called again (until another break request is + // received, which is again returned once). + // This also mean that if two break requests are received + // without readBreak() being called in between, the value of the + // first request is lost. + // Note that the value returned is a long, so it can return + // 0-0xffff as well as -1. + int32_t readBreak(); + // These return the settings specified by the USB host for the // serial port. These aren't really used, but are offered here // in case a sketch wants to act on these settings.