diff --git a/cdc_XR21B1411.cpp b/cdc_XR21B1411.cpp index 6490c40e..74df8c3b 100644 --- a/cdc_XR21B1411.cpp +++ b/cdc_XR21B1411.cpp @@ -14,18 +14,20 @@ Circuits At Home, LTD Web : http://www.circuitsathome.com e-mail : support@circuitsathome.com */ -#include "cdcprolific.h" +#include "cdc_XR21B1411.h" -PL2303::PL2303(USB *p, CDCAsyncOper *pasync) : -ACM(p, pasync), -wPLType(0) { +XR21B1411::XR21B1411(USB *p, CDCAsyncOper *pasync) : +ACM(p, pasync) { + // Is this needed?? + _enhanced_status = enhanced_features(); // Set up features } -uint8_t PL2303::Init(uint8_t parent, uint8_t port, bool lowspeed) { +uint8_t XR21B1411::Init(uint8_t parent, uint8_t port, bool lowspeed) { const uint8_t constBufSize = sizeof (USB_DEVICE_DESCRIPTOR); uint8_t buf[constBufSize]; USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast(buf); + uint8_t rcode; UsbDevice *p = NULL; EpInfo *oldep_ptr = NULL; @@ -33,7 +35,7 @@ uint8_t PL2303::Init(uint8_t parent, uint8_t port, bool lowspeed) { AddressPool &addrPool = pUsb->GetAddressPool(); - USBTRACE("PL Init\r\n"); + USBTRACE("XR Init\r\n"); if(bAddress) return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE; @@ -58,7 +60,7 @@ uint8_t PL2303::Init(uint8_t parent, uint8_t port, bool lowspeed) { p->lowspeed = lowspeed; // Get device descriptor - rcode = pUsb->getDevDescr(0, 0, sizeof (USB_DEVICE_DESCRIPTOR), (uint8_t*)buf); + rcode = pUsb->getDevDescr(0, 0, constBufSize, (uint8_t*)buf); // Restore p->epinfo p->epinfo = oldep_ptr; @@ -66,12 +68,6 @@ uint8_t PL2303::Init(uint8_t parent, uint8_t port, bool lowspeed) { if(rcode) goto FailGetDevDescr; - if(udd->idVendor != PL_VID && udd->idProduct != PL_PID) - return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; - - // Save type of PL chip - wPLType = udd->bcdDevice; - // Allocate new address according to device class bAddress = addrPool.AllocAddress(parent, false, port); @@ -105,6 +101,9 @@ uint8_t PL2303::Init(uint8_t parent, uint8_t port, bool lowspeed) { num_of_conf = udd->bNumConfigurations; + if((((udd->idVendor != 0x2890U) || (udd->idProduct != 0x0201U)) && ((udd->idVendor != 0x04e2U) || (udd->idProduct != 0x1411U)))) + return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; + // Assign epInfo to epinfo pointer rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); @@ -114,15 +113,22 @@ uint8_t PL2303::Init(uint8_t parent, uint8_t port, bool lowspeed) { USBTRACE2("NC:", num_of_conf); for(uint8_t i = 0; i < num_of_conf; i++) { - HexDumper HexDump; - ConfigDescParser < 0xFF, 0, 0, CP_MASK_COMPARE_CLASS> confDescrParser(this); + ConfigDescParser< USB_CLASS_COM_AND_CDC_CTRL, + CDC_SUBCLASS_ACM, + CDC_PROTOCOL_ITU_T_V_250, + CP_MASK_COMPARE_CLASS | + CP_MASK_COMPARE_SUBCLASS | + CP_MASK_COMPARE_PROTOCOL > CdcControlParser(this); - rcode = pUsb->getConfDescr(bAddress, 0, i, &HexDump); + ConfigDescParser CdcDataParser(this); + + rcode = pUsb->getConfDescr(bAddress, 0, i, &CdcControlParser); if(rcode) goto FailGetConfDescr; - rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser); + rcode = pUsb->getConfDescr(bAddress, 0, i, &CdcDataParser); if(rcode) goto FailGetConfDescr; @@ -131,7 +137,7 @@ uint8_t PL2303::Init(uint8_t parent, uint8_t port, bool lowspeed) { break; } // for - if(bNumEP < 2) + if(bNumEP < 4) return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; // Assign epInfo to epinfo pointer @@ -145,15 +151,26 @@ uint8_t PL2303::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) goto FailOnInit; - USBTRACE("PL configured\r\n"); + USBTRACE("XR configured\r\n"); + + ready = true; //bPollEnable = true; - ready = true; + + //USBTRACE("Poll enabled\r\n"); return 0; FailGetDevDescr: @@ -192,19 +209,3 @@ Fail: Release(); return rcode; } - -//uint8_t PL::Poll() -//{ -// uint8_t rcode = 0; -// -// //if (!bPollEnable) -// // return 0; -// -// //if (qNextPollTime <= millis()) -// //{ -// // USB_HOST_SERIAL.println(bAddress, HEX); -// -// // qNextPollTime = millis() + 100; -// //} -// return rcode; -//} diff --git a/cdc_XR21B1411.h b/cdc_XR21B1411.h index 32566585..347f0df6 100644 --- a/cdc_XR21B1411.h +++ b/cdc_XR21B1411.h @@ -1,4 +1,6 @@ -/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. +/* Copyright (C) 2015 Andrew J. Kroll + and + Circuits At Home, LTD. All rights reserved. This software may be distributed and modified under the terms of the GNU General Public License version 2 (GPL2) as published by the Free Software @@ -14,122 +16,257 @@ Circuits At Home, LTD Web : http://www.circuitsathome.com e-mail : support@circuitsathome.com */ -#if !defined(__CDCPROLIFIC_H__) -#define __CDCPROLIFIC_H__ +#if !defined(__CDC_XR21B1411_H__) +#define __CDC_XR21B1411_H__ #include "cdcacm.h" -#define PL_VID 0x067B -#define PL_PID ( 0x2303 || 0x0609 ) +#define XR_REG_CUSTOM_DRIVER (0x020DU) // DRIVER SELECT +#define XR_REG_CUSTOM_DRIVER_ACTIVE (0x0001U) // 0: CDC 1: CUSTOM -//#define PL_PID 0x0609 +#define XR_REG_ACM_FLOW_CTL (0x0216U) // FLOW CONTROL REGISTER CDCACM MODE +#define XR_REG_FLOW_CTL (0x0C06U) // FLOW CONTROL REGISTER CUSTOM MODE +#define XR_REG_FLOW_CTL_HALF_DPLX (0x0008U) // 0:FULL DUPLEX 1:HALF DUPLEX +#define XR_REG_FLOW_CTL_MODE_MASK (0x0007U) // MODE BITMASK +#define XR_REG_FLOW_CTL_NONE (0x0000U) // NO FLOW CONTROL +#define XR_REG_FLOW_CTL_HW (0x0001U) // HARDWARE FLOW CONTROL +#define XR_REG_FLOW_CTL_SW (0x0002U) // SOFTWARE FLOW CONTROL +#define XR_REG_FLOW_CTL_MMMRX (0x0003U) // MULTIDROP RX UPON ADDRESS MATCH +#define XR_REG_FLOW_CTL_MMMRXTX (0x0004U) // MULTIDROP RX/TX UPON ADDRESS MATCH -#define PROLIFIC_REV_H 0x0202 -#define PROLIFIC_REV_X 0x0300 -#define PROLIFIC_REV_HX_CHIP_D 0x0400 -#define PROLIFIC_REV_1 0x0001 +#define XR_REG_ACM_GPIO_MODE (0x0217U) // GPIO MODE REGISTER IN CDCACM MODE +#define XR_REG_GPIO_MODE (0x0C0CU) // GPIO MODE REGISTER IN CUSTOM MODE +#define XR_REG_GPIO_MODE_GPIO (0x0000U) // ALL GPIO PINS ACM PROGRAMMABLE +#define XR_REG_GPIO_MODE_FC_RTSCTS (0x0001U) // AUTO RTSCTS HW FC (GPIO 4/5) +#define XR_REG_GPIO_MODE_FC_DTRDSR (0x0002U) // AUTO DTRDSR HW FC (GPIO 2/3) +#define XR_REG_GPIO_MODE_ATE (0x0003U) // AUTO TRANSCEIVER ENABLE DURING TX (GPIO 5) +#define XR_REG_GPIO_MODE_ATE_ADDRESS (0x0004U) // AUTO TRANSCEIVER ENABLE ON ADDRESS MATCH (GPIO 5) -#define kXOnChar '\x11' -#define kXOffChar '\x13' +#define XR_REG_ACM_GPIO_DIR (0x0218U) // GPIO DIRECTION REGISTER CDCACM MODE, 0:IN 1:OUT +#define XR_REG_GPIO_DIR (0x0C0DU) // GPIO DIRECTION REGISTER CUSTOM MODE, 0:IN 1:OUT -#define SPECIAL_SHIFT (5) -#define SPECIAL_MASK ((1<ctrlReq(bAddress, 0, XR_READ_REQUEST_TYPE, 1, 0, 0, reg, 2, 2, (uint8_t *)val, NULL)); + } + + uint8_t write_register(uint16_t reg, uint16_t val) { + return (pUsb->ctrlReq(bAddress, 0, XR_WRITE_REQUEST_TYPE, 0, BGRAB0(val), BGRAB1(val), reg, 0, 0, NULL, NULL)); + } + + + //////////////////////////////////////////////////////////////////////// + // The following methods set the CDC-ACM defaults. + //////////////////////////////////////////////////////////////////////// + + virtual void autoflowRTS(bool s) { + uint16_t val; + uint8_t rval; + rval = read_register(XR_REG_ACM_FLOW_CTL, &val); + if(!rval) { + if(s) { + val &= XR_REG_FLOW_CTL_HALF_DPLX; + val |= XR_REG_FLOW_CTL_HW; + } else { + val &= XR_REG_FLOW_CTL_HALF_DPLX; + } + rval = write_register(XR_REG_ACM_FLOW_CTL, val); + if(!rval) { + rval = write_register(XR_REG_ACM_GPIO_MODE, XR_REG_GPIO_MODE_GPIO); + if(!rval) { + // ACM commands apply the new settings. + LINE_CODING LCT; + rval = GetLineCoding(&LCT); + if(!rval) { + rval = SetLineCoding(&LCT); + if(!rval) { + _enhanced_status.autoflow_XON = false; + _enhanced_status.autoflow_DSR = false; + _enhanced_status.autoflow_RTS = s; + } + } + } + } + } + }; + + virtual void autoflowDSR(bool s) { + uint16_t val; + uint8_t rval; + rval = read_register(XR_REG_ACM_FLOW_CTL, &val); + if(!rval) { + if(s) { + val &= XR_REG_FLOW_CTL_HALF_DPLX; + val |= XR_REG_FLOW_CTL_HW; + } else { + val &= XR_REG_FLOW_CTL_HALF_DPLX; + } + rval = write_register(XR_REG_ACM_FLOW_CTL, val); + if(!rval) { + if(s) { + rval = write_register(XR_REG_ACM_GPIO_MODE, XR_REG_GPIO_MODE_FC_DTRDSR); + } else { + rval = write_register(XR_REG_ACM_GPIO_MODE, XR_REG_GPIO_MODE_GPIO); + } + if(!rval) { + // ACM commands apply the new settings. + LINE_CODING LCT; + rval = GetLineCoding(&LCT); + if(!rval) { + rval = SetLineCoding(&LCT); + if(!rval) { + _enhanced_status.autoflow_XON = false; + _enhanced_status.autoflow_RTS = false; + _enhanced_status.autoflow_DSR = s; + } + } + } + } + } + }; + + virtual void autoflowXON(bool s) { + // NOTE: hardware defaults to the normal XON/XOFF + uint16_t val; + uint8_t rval; + rval = read_register(XR_REG_ACM_FLOW_CTL, &val); + if(!rval) { + if(s) { + val &= XR_REG_FLOW_CTL_HALF_DPLX; + val |= XR_REG_FLOW_CTL_SW; + } else { + val &= XR_REG_FLOW_CTL_HALF_DPLX; + } + rval = write_register(XR_REG_ACM_FLOW_CTL, val); + if(!rval) { + rval = write_register(XR_REG_ACM_GPIO_MODE, XR_REG_GPIO_MODE_GPIO); + if(!rval) { + // ACM commands apply the new settings. + LINE_CODING LCT; + rval = GetLineCoding(&LCT); + if(!rval) { + rval = SetLineCoding(&LCT); + if(!rval) { + _enhanced_status.autoflow_RTS = false; + _enhanced_status.autoflow_DSR = false; + _enhanced_status.autoflow_XON = s; + } + } + } + } + } + }; + + virtual void half_duplex(bool s) { + uint16_t val; + uint8_t rval; + rval = read_register(XR_REG_ACM_FLOW_CTL, &val); + if(!rval) { + if(s) { + val |= XR_REG_FLOW_CTL_HALF_DPLX; + } else { + val &= XR_REG_FLOW_CTL_MODE_MASK; + } + rval = write_register(XR_REG_ACM_FLOW_CTL, val); + if(!rval) { + // ACM commands apply the new settings. + LINE_CODING LCT; + rval = GetLineCoding(&LCT); + if(!rval) { + rval = SetLineCoding(&LCT); + if(!rval) { + _enhanced_status.half_duplex = s; + } + } + } + } + }; + + + }; #endif // __CDCPROLIFIC_H__