diff --git a/libraries/USBDevice/USBSerial/USBCDC.cpp b/libraries/USBDevice/USBSerial/USBCDC.cpp index 29ea68a62e2..5dff9f1a4ff 100644 --- a/libraries/USBDevice/USBSerial/USBCDC.cpp +++ b/libraries/USBDevice/USBSerial/USBCDC.cpp @@ -52,6 +52,7 @@ bool USBCDC::USBCallback_request(void) { break; case CDC_SET_LINE_CODING: transfer->remaining = 7; + transfer->notify = true; success = true; terminal_connected = true; break; @@ -67,6 +68,31 @@ bool USBCDC::USBCallback_request(void) { return success; } +void USBCDC::USBCallback_requestCompleted(uint8_t *buf, uint32_t length) { + // Request of setting line coding has 7 bytes + if (length != 7) { + return; + } + + CONTROL_TRANSFER * transfer = getTransferPtr(); + + /* Process class-specific requests */ + if (transfer->setup.bmRequestType.Type == CLASS_TYPE) { + if (transfer->setup.bRequest == CDC_SET_LINE_CODING) { + if (memcmp(cdc_line_coding, buf, 7)) { + memcpy(cdc_line_coding, buf, 7); + + int baud = buf[0] + (buf[1] << 8) + + (buf[2] << 16) + (buf[3] << 24); + int stop = buf[4]; + int bits = buf[6]; + int parity = buf[5]; + + lineCodingChanged(baud, bits, parity, stop); + } + } + } +} // Called in ISR context // Set configuration. Return false if the diff --git a/libraries/USBDevice/USBSerial/USBCDC.h b/libraries/USBDevice/USBSerial/USBCDC.h index 9d810f8ff86..c2f14e5b1ed 100644 --- a/libraries/USBDevice/USBSerial/USBCDC.h +++ b/libraries/USBDevice/USBSerial/USBCDC.h @@ -99,9 +99,21 @@ class USBCDC: public USBDevice { * @returns true if successful */ bool readEP_NB(uint8_t * buffer, uint32_t * size); + + /* + * Called by USBCallback_requestCompleted when CDC line coding is changed + * Warning: Called in ISR + * + * @param baud The baud rate + * @param bits The number of bits in a word (5-8) + * @param parity The parity + * @param stop The number of stop bits (1 or 2) + */ + virtual void lineCodingChanged(int baud, int bits, int parity, int stop) {}; protected: virtual bool USBCallback_request(); + virtual void USBCallback_requestCompleted(uint8_t *buf, uint32_t length); virtual bool USBCallback_setConfiguration(uint8_t configuration); volatile bool terminal_connected; diff --git a/libraries/USBDevice/USBSerial/USBSerial.h b/libraries/USBDevice/USBSerial/USBSerial.h index 49fab116f82..7a73c8a93ba 100644 --- a/libraries/USBDevice/USBSerial/USBSerial.h +++ b/libraries/USBDevice/USBSerial/USBSerial.h @@ -55,7 +55,9 @@ class USBSerial: public USBCDC, public Stream { * @param product_release Your preoduct_release (default: 0x0001) * */ - USBSerial(uint16_t vendor_id = 0x1f00, uint16_t product_id = 0x2012, uint16_t product_release = 0x0001): USBCDC(vendor_id, product_id, product_release), buf(128){ }; + USBSerial(uint16_t vendor_id = 0x1f00, uint16_t product_id = 0x2012, uint16_t product_release = 0x0001): USBCDC(vendor_id, product_id, product_release), buf(128){ + settingsChangedCallback = 0; + }; /** @@ -79,6 +81,22 @@ class USBSerial: public USBCDC, public Stream { * @returns the number of bytes available */ uint8_t available(); + + /** Determine if there is a character available to read + * + * @returns + * 1 if there is a character available to read, + * 0 otherwise + */ + int readable() { return available() ? 1 : 0; } + + /** Determine if there is space available to write a character + * + * @returns + * 1 if there is space to write a character, + * 0 otherwise + */ + int writeable() { return 1; } // always return 1, for write operation is blocking /** * Write a block of data. @@ -110,19 +128,33 @@ class USBSerial: public USBCDC, public Stream { * * @param fptr function pointer */ - void attach(void (*fn)(void)) { - if(fn != NULL) { - rx.attach(fn); + void attach(void (*fptr)(void)) { + if(fptr != NULL) { + rx.attach(fptr); } } + /** + * Attach a callback to call when serial's settings are changed. + * + * @param fptr function pointer + */ + void attach(void (*fptr)(int baud, int bits, int parity, int stop)) { + settingsChangedCallback = fptr; + } protected: virtual bool EP2_OUT_callback(); + virtual void lineCodingChanged(int baud, int bits, int parity, int stop){ + if (settingsChangedCallback) { + settingsChangedCallback(baud, bits, parity, stop); + } + } private: FunctionPointer rx; CircBuffer buf; + void (*settingsChangedCallback)(int baud, int bits, int parity, int stop); }; #endif