diff --git a/cdcacm.cpp b/cdcacm.cpp index 23f43e75..2cd2c9a8 100644 --- a/cdcacm.cpp +++ b/cdcacm.cpp @@ -30,21 +30,20 @@ bNumEP(1), qNextPollTime(0), bPollEnable(false), ready(false) { + _enhanced_status = enhanced_features(); // Set up features for(uint8_t i = 0; i < ACM_MAX_ENDPOINTS; i++) { epInfo[i].epAddr = 0; epInfo[i].maxPktSize = (i) ? 0 : 8; epInfo[i].epAttribs = 0; - //epInfo[i].bmNakPower = USB_NAK_NOWAIT; - epInfo[i].bmNakPower = USB_NAK_MAX_POWER; + epInfo[i].bmNakPower = (i == epDataInIndex) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER; - //if (!i) - epInfo[i].bmNakPower = USB_NAK_MAX_POWER; } if(pUsb) pUsb->RegisterDeviceClass(this); } uint8_t ACM::Init(uint8_t parent, uint8_t port, bool lowspeed) { + const uint8_t constBufSize = sizeof (USB_DEVICE_DESCRIPTOR); uint8_t buf[constBufSize]; @@ -170,6 +169,13 @@ uint8_t ACM::Init(uint8_t parent, uint8_t port, bool lowspeed) { if(rcode) goto FailSetConfDescr; + // Set up features status + _enhanced_status = enhanced_features(); + half_duplex(false); + autoflowRTS(false); + autoflowDSR(false); + autoflowXON(false); + wide(false); // Always false, because this is only available in custom mode. rcode = pAsync->OnInit(this); if(rcode) diff --git a/cdcacm.h b/cdcacm.h index 13a4f253..8372f56b 100644 --- a/cdcacm.h +++ b/cdcacm.h @@ -129,11 +129,34 @@ class CDCAsyncOper { public: virtual uint8_t OnInit(ACM *pacm) { + return 0; }; //virtual void OnDataRcvd(ACM *pacm, uint8_t nbytes, uint8_t *dataptr) = 0; //virtual void OnDisconnected(ACM *pacm) = 0; }; +/** + * This structure is used to report the extended capabilities of the connected device. + * It is also used to report the current status. + * Regular CDC-ACM reports all as false. + */ +typedef struct { + + union { + uint8_t tty; + + struct { + bool enhanced : 1; // Do we have the ability to set/clear any features? + // Status and 8th bit in data stream. + // Presence only indicates feature is available, but this isn't used for CDC-ACM. + bool wide : 1; + bool autoflow_RTS : 1; // Has autoflow on RTS/CTS + bool autoflow_DSR : 1; // Has autoflow on DTR/DSR + bool autoflow_XON : 1; // Has autoflow XON/XOFF + bool half_duplex : 1; // Has half-duplex capability. + } __attribute__((packed)); + }; +} tty_features; #define ACM_MAX_ENDPOINTS 4 @@ -151,8 +174,9 @@ protected: uint8_t bDataIface; // Data interface value uint8_t bNumEP; // total number of EP in the configuration uint32_t qNextPollTime; // next poll time - bool bPollEnable; // poll enable flag - bool ready; //device ready indicator + volatile bool bPollEnable; // poll enable flag + volatile bool ready; //device ready indicator + tty_features _enhanced_status; // current status EpInfo epInfo[ACM_MAX_ENDPOINTS]; @@ -170,7 +194,7 @@ public: uint8_t SendBreak(uint16_t duration); uint8_t GetNotif(uint16_t *bytes_rcvd, uint8_t *dataptr); - // Methods for recieving and sending data + // Methods for receiving and sending data uint8_t RcvData(uint16_t *nbytesptr, uint8_t *dataptr); uint8_t SndData(uint16_t nbytes, uint8_t *dataptr); @@ -179,6 +203,10 @@ public: uint8_t Release(); uint8_t Poll(); + bool available(void) { + + }; + virtual uint8_t GetAddress() { return bAddress; }; @@ -187,6 +215,36 @@ public: return ready; }; + virtual tty_features enhanced_status(void) { + return _enhanced_status; + }; + + virtual tty_features enhanced_features(void) { + tty_features rv; + rv.enhanced = false; + rv.autoflow_RTS = false; + rv.autoflow_DSR = false; + rv.autoflow_XON = false; + rv.half_duplex = false; + rv.wide = false; + return rv; + }; + + virtual void autoflowRTS(bool s) { + }; + + virtual void autoflowDSR(bool s) { + }; + + virtual void autoflowXON(bool s) { + }; + + virtual void half_duplex(bool s) { + }; + + virtual void wide(bool s) { + }; + // UsbConfigXtracter implementation void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep); }; diff --git a/cdcftdi.cpp b/cdcftdi.cpp index 97dd0ad1..80d21d16 100644 --- a/cdcftdi.cpp +++ b/cdcftdi.cpp @@ -30,9 +30,7 @@ wFTDIType(0) { epInfo[i].epAddr = 0; epInfo[i].maxPktSize = (i) ? 0 : 8; epInfo[i].epAttribs = 0; - - //if (!i) - epInfo[i].bmNakPower = USB_NAK_MAX_POWER; + epInfo[i].bmNakPower = (i==epDataInIndex) ? USB_NAK_NOWAIT: USB_NAK_MAX_POWER; } if(pUsb) pUsb->RegisterDeviceClass(this); @@ -46,11 +44,8 @@ uint8_t FTDI::Init(uint8_t parent, uint8_t port, bool lowspeed) { uint8_t rcode; UsbDevice *p = NULL; EpInfo *oldep_ptr = NULL; - //uint8_t len = 0; - //uint16_t cd_len = 0; uint8_t num_of_conf; // number of configurations - //uint8_t num_of_intf; // number of interfaces AddressPool &addrPool = pUsb->GetAddressPool();