diff --git a/cdcprolific.cpp b/cdcprolific.cpp index f1a97376..fd39ed45 100644 --- a/cdcprolific.cpp +++ b/cdcprolific.cpp @@ -68,7 +68,7 @@ uint8_t PL::Init(uint8_t parent, uint8_t port, bool lowspeed) if( rcode ) goto FailGetDevDescr; - if (((USB_DEVICE_DESCRIPTOR*)buf)->idVendor != PL_VID || ((USB_DEVICE_DESCRIPTOR*)buf)->idProduct != PL_PID) + if (((USB_DEVICE_DESCRIPTOR*)buf)->idVendor != PL_VID && ((USB_DEVICE_DESCRIPTOR*)buf)->idProduct != PL_PID ) return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; // Save type of PL chip diff --git a/cdcprolific.h b/cdcprolific.h index e3702bc5..095f39d3 100644 --- a/cdcprolific.h +++ b/cdcprolific.h @@ -33,8 +33,10 @@ e-mail : support@circuitsathome.com #include "confdescparser.h" #include "cdcacm.h" -#define PL_VID 0x067B -#define PL_PID 0x2303 +#define PL_VID 0x067B +#define PL_PID ( 0x2303 || 0x0609 ) + +//#define PL_PID 0x0609 #define PROLIFIC_REV_H 0x0202 #define PROLIFIC_REV_X 0x0300 diff --git a/examples/pl2303/pl2303_gprs_terminal/pl2303_gprs_terminal.pde b/examples/pl2303/pl2303_gprs_terminal/pl2303_gprs_terminal.pde new file mode 100644 index 00000000..5d1fecda --- /dev/null +++ b/examples/pl2303/pl2303_gprs_terminal/pl2303_gprs_terminal.pde @@ -0,0 +1,104 @@ +/* Arduino terminal for PL2303 USB to serial converter and DealeXtreme GPRS modem. */ +/* USB support */ +#include +#include +#include +#include +#include +#include +#include +#include +/* CDC support */ +#include +#include +/* Debug support */ +#include +#include +#include +#include + +class PLAsyncOper : public CDCAsyncOper +{ +public: + virtual uint8_t OnInit(ACM *pacm); +}; + +uint8_t PLAsyncOper::OnInit(ACM *pacm) +{ + uint8_t rcode; + + // Set DTR = 1 + rcode = pacm->SetControlLineState(1); + + if (rcode) + { + ErrorMessage(PSTR("SetControlLineState"), rcode); + return rcode; + } + + LINE_CODING lc; + //lc.dwDTERate = 9600; + lc.dwDTERate = 115200; + lc.bCharFormat = 0; + lc.bParityType = 0; + lc.bDataBits = 8; + + rcode = pacm->SetLineCoding(&lc); + + if (rcode) + ErrorMessage(PSTR("SetLineCoding"), rcode); + + return rcode; +} +USB Usb; +//USBHub Hub(&Usb); +PLAsyncOper AsyncOper; +PL Pl(&Usb, &AsyncOper); + +void setup() +{ + Serial.begin( 115200 ); + Serial.println("Start"); + + if (Usb.Init() == -1) + Serial.println("OSCOKIRQ failed to assert"); + + delay( 200 ); +} + +void loop() +{ + Usb.Task(); + + if( Usb.getUsbTaskState() == USB_STATE_RUNNING ) + { + uint8_t rcode; + + /* reading the keyboard */ + if(Serial.available()) { + uint8_t data= Serial.read(); + + /* sending to the phone */ + rcode = Pl.SndData(1, &data); + if (rcode) + ErrorMessage(PSTR("SndData"), rcode); + }//if(Serial.available()... + + /* reading the converter */ + /* buffer size must be greater or equal to max.packet size */ + /* it it set to 64 (largest possible max.packet size) here, can be tuned down + for particular endpoint */ + uint8_t buf[64]; + uint16_t rcvd = 64; + rcode = Pl.RcvData(&rcvd, buf); + if (rcode && rcode != hrNAK) + ErrorMessage(PSTR("Ret"), rcode); + + if( rcvd ) { //more than zero bytes received + for(uint16_t i=0; i < rcvd; i++ ) { + Serial.print(buf[i]); //printing on the screen + } + }//if( rcvd ... + }//if( Usb.getUsbTaskState() == USB_STATE_RUNNING.. +} + diff --git a/hiduniversal.cpp b/hiduniversal.cpp new file mode 100644 index 00000000..e3dae0eb --- /dev/null +++ b/hiduniversal.cpp @@ -0,0 +1,416 @@ +#include "hiduniversal.h" + +HIDUniversal::HIDUniversal(USB *p) : + HID(p), + qNextPollTime(0), + bPollEnable(false), + bHasReportId(false) +{ + Initialize(); + + if (pUsb) + pUsb->RegisterDeviceClass(this); +} + +uint16_t HIDUniversal::GetHidClassDescrLen(uint8_t type, uint8_t num) +{ + for (uint8_t i=0, n=0; iGetAddressPool(); + + USBTRACE("HU Init\r\n"); + + if (bAddress) + return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE; + + // Get pointer to pseudo device with address 0 assigned + p = addrPool.GetUsbDevicePtr(0); + + if (!p) + return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; + + if (!p->epinfo) + { + USBTRACE("epinfo\r\n"); + return USB_ERROR_EPINFO_IS_NULL; + } + + // Save old pointer to EP_RECORD of address 0 + oldep_ptr = p->epinfo; + + // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence + p->epinfo = epInfo; + + p->lowspeed = lowspeed; + + // Get device descriptor + rcode = pUsb->getDevDescr( 0, 0, 8, (uint8_t*)buf ); + + if (!rcode) + len = (buf[0] > constBufSize) ? constBufSize : buf[0]; + + if( rcode ) + { + // Restore p->epinfo + p->epinfo = oldep_ptr; + + goto FailGetDevDescr; + } + + // Restore p->epinfo + p->epinfo = oldep_ptr; + + // Allocate new address according to device class + bAddress = addrPool.AllocAddress(parent, false, port); + + if (!bAddress) + return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; + + // Extract Max Packet Size from the device descriptor + epInfo[0].maxPktSize = (uint8_t)((USB_DEVICE_DESCRIPTOR*)buf)->bMaxPacketSize0; + + // Assign new address to the device + rcode = pUsb->setAddr( 0, 0, bAddress ); + + if (rcode) + { + p->lowspeed = false; + addrPool.FreeAddress(bAddress); + bAddress = 0; + USBTRACE2("setAddr:",rcode); + return rcode; + } + + USBTRACE2("Addr:", bAddress); + + p->lowspeed = false; + + p = addrPool.GetUsbDevicePtr(bAddress); + + if (!p) + return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; + + p->lowspeed = lowspeed; + + if (len) + rcode = pUsb->getDevDescr( bAddress, 0, len, (uint8_t*)buf ); + + if(rcode) + goto FailGetDevDescr; + + num_of_conf = ((USB_DEVICE_DESCRIPTOR*)buf)->bNumConfigurations; + + // Assign epInfo to epinfo pointer + rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); + + if (rcode) + goto FailSetDevTblEntry; + + USBTRACE2("NC:", num_of_conf); + + for (uint8_t i=0; i HexDump; + ConfigDescParser confDescrParser(this); + + rcode = pUsb->getConfDescr(bAddress, 0, i, &HexDump); + rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser); + + if (bNumEP > 1) + break; + } // for + + if (bNumEP < 2) + return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; + + // Assign epInfo to epinfo pointer + rcode = pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo); + + USBTRACE2("\r\nCnf:", bConfNum); + + // Set Configuration Value + //rcode = pUsb->setConf(bAddress, 0, 0); + rcode = pUsb->setConf(bAddress, 0, bConfNum); + + if (rcode) + goto FailSetConfDescr; + + for (uint8_t i=0; i Hex; + ReportDescParser Rpt; + + if (rcode = GetReportDescr(0, &Hex)) + goto FailGetReportDescr; + + if (rcode = GetReportDescr(0, &Rpt)) + goto FailGetReportDescr; + } + bPollEnable = true; + return 0; + +FailGetDevDescr: + USBTRACE("getDevDescr:"); + goto Fail; + +FailSetDevTblEntry: + USBTRACE("setDevTblEn:"); + goto Fail; + +FailGetConfDescr: + USBTRACE("getConf:"); + goto Fail; + +FailSetConfDescr: + USBTRACE("setConf:"); + goto Fail; + +FailSetProtocol: + USBTRACE("SetProto:"); + goto Fail; + +FailSetIdle: + USBTRACE("SetIdle:"); + goto Fail; + +FailGetReportDescr: + USBTRACE("GetReportDescr:"); + goto Fail; + +Fail: + Serial.println(rcode, HEX); + Release(); + return rcode; +} + +HIDUniversal::HIDInterface* HIDUniversal::FindInterface(uint8_t iface, uint8_t alt, uint8_t proto) +{ + for (uint8_t i=0; i 1 && conf != bConfNum) + return; + + ErrorMessage(PSTR("\r\nConf.Val"), conf); + ErrorMessage(PSTR("Iface Num"), iface); + ErrorMessage(PSTR("Alt.Set"), alt); + + bConfNum = conf; + + uint8_t index = 0; + HIDInterface *piface = FindInterface(iface, alt, proto); + + // Fill in interface structure in case of new interface + if (!piface) + { + piface = hidInterfaces + bNumIface; + piface->bmInterface = iface; + piface->bmAltSet = alt; + piface->bmProtocol = proto; + bNumIface ++; + } + + if ((pep->bmAttributes & 0x03) == 3 && (pep->bEndpointAddress & 0x80) == 0x80) + { + USBTRACE("I8\r\n"); + index = epInterruptInIndex; + } + else + { + USBTRACE("I0\r\n"); + index = epInterruptOutIndex; + } + + if (index) + { + USBTRACE2("Ind:", index); + + // Fill in the endpoint info structure + epInfo[bNumEP].epAddr = (pep->bEndpointAddress & 0x0F); + epInfo[bNumEP].maxPktSize = (uint8_t)pep->wMaxPacketSize; + epInfo[bNumEP].epAttribs = 0; + + // Fill in the endpoint index list + piface->epIndex[index] = bNumEP; //(pep->bEndpointAddress & 0x0F); + + bNumEP ++; + } + PrintEndpointDescriptor(pep); +} + + +uint8_t HIDUniversal::Release() +{ + pUsb->GetAddressPool().FreeAddress(bAddress); + + bNumEP = 1; + bAddress = 0; + qNextPollTime = 0; + bPollEnable = false; + return 0; +} + +uint8_t HIDUniversal::Poll() +{ + uint8_t rcode = 0; + + if (!bPollEnable) + return 0; + + if (qNextPollTime <= millis()) + { + qNextPollTime = millis() + 50; + + const uint8_t const_buff_len = 16; + uint8_t buf[const_buff_len]; + + for (uint8_t i=0; iinTransfer(bAddress, epInfo[index].epAddr, &read, buf); + + if (rcode) + { + if (rcode != hrNAK) + USBTRACE2("Poll:", rcode); + else + USBTRACE2("poll:", rcode); + return rcode; + } + Serial.print("Read:"); + PrintHex(read); + Serial.println(""); + + for (uint8_t i=0; i(buf[i]); + if (read) + Serial.println(""); + + HIDReportParser *prs = GetReportParser( ((bHasReportId) ? *buf : 0) ); + + if (prs) + prs->Parse(this, bHasReportId, (uint8_t)read, buf); + } + + } + return rcode; +} diff --git a/hiduniversal.h b/hiduniversal.h new file mode 100644 index 00000000..ba56ddf6 --- /dev/null +++ b/hiduniversal.h @@ -0,0 +1,67 @@ +#if !defined(__HIDUNIVERSAL_H__) +#define __HIDUNIVERSAL_H__ + +#include "hid.h" +#include "hidescriptorparser.h" + +class HIDUniversal : public HID +{ + struct ReportParser + { + uint8_t rptId; + HIDReportParser *rptParser; + } rptParsers[MAX_REPORT_PARSERS]; + + // HID class specific descriptor type and length info obtained from HID descriptor + HID_CLASS_DESCRIPTOR_LEN_AND_TYPE descrInfo[HID_MAX_HID_CLASS_DESCRIPTORS]; + + // Returns HID class specific descriptor length by its type and order number + uint16_t GetHidClassDescrLen(uint8_t type, uint8_t num); + + EpInfo epInfo[totalEndpoints]; + + struct HIDInterface + { + struct + { + uint8_t bmInterface : 3; + uint8_t bmAltSet : 3; + uint8_t bmProtocol : 2; + }; + uint8_t epIndex[maxEpPerInterface]; + }; + + HIDInterface hidInterfaces[maxHidInterfaces]; + + uint8_t bConfNum; // configuration number + uint8_t bNumIface; // number of interfaces in the configuration + uint8_t bNumEP; // total number of EP in the configuration + uint32_t qNextPollTime; // next poll time + bool bPollEnable; // poll enable flag + + void Initialize(); + HIDInterface* FindInterface(uint8_t iface, uint8_t alt, uint8_t proto); + +protected: + bool bHasReportId; + + // HID implementation + virtual HIDReportParser* GetReportParser(uint8_t id); + +public: + HIDUniversal(USB *p); + + // HID implementation + virtual bool SetReportParser(uint8_t id, HIDReportParser *prs); + + // USBDeviceConfig implementation + virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed); + virtual uint8_t Release(); + virtual uint8_t Poll(); + virtual uint8_t GetAddress() { return bAddress; }; + + // UsbConfigXtracter implementation + virtual void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep); +}; + +#endif // __HIDUNIVERSAL_H__ \ No newline at end of file