PID 0609 added to prolific driver

This commit is contained in:
Oleg Mazurov 2011-10-19 17:33:15 -06:00
parent df307305f5
commit a97fb4bbda
5 changed files with 592 additions and 3 deletions

View file

@ -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

View file

@ -34,7 +34,9 @@ e-mail : support@circuitsathome.com
#include "cdcacm.h"
#define PL_VID 0x067B
#define PL_PID 0x2303
#define PL_PID ( 0x2303 || 0x0609 )
//#define PL_PID 0x0609
#define PROLIFIC_REV_H 0x0202
#define PROLIFIC_REV_X 0x0300

View file

@ -0,0 +1,104 @@
/* Arduino terminal for PL2303 USB to serial converter and DealeXtreme GPRS modem. */
/* USB support */
#include <avrpins.h>
#include <max3421e.h>
#include <usbhost.h>
#include <usb_ch9.h>
#include <Usb.h>
#include <usbhub.h>
#include <avr/pgmspace.h>
#include <address.h>
/* CDC support */
#include <cdcacm.h>
#include <cdcprolific.h>
/* Debug support */
#include <printhex.h>
#include <message.h>
#include <hexdump.h>
#include <parsetools.h>
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<uint8_t>(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<uint8_t>(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<uint8_t>(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<uint8_t>(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..
}

416
hiduniversal.cpp Normal file
View file

@ -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; i<HID_MAX_HID_CLASS_DESCRIPTORS; i++)
{
if (descrInfo[i].bDescrType == type)
{
if (n == num)
return descrInfo[i].wDescriptorLength;
n ++;
}
}
return 0;
}
void HIDUniversal::Initialize()
{
for (uint8_t i=0; i<MAX_REPORT_PARSERS; i++)
{
rptParsers[i].rptId = 0;
rptParsers[i].rptParser = NULL;
}
for (uint8_t i=0; i<HID_MAX_HID_CLASS_DESCRIPTORS; i++)
{
descrInfo[i].bDescrType = 0;
descrInfo[i].wDescriptorLength = 0;
}
for (uint8_t i=0; i<maxHidInterfaces; i++)
{
hidInterfaces[i].bmInterface = 0;
hidInterfaces[i].bmProtocol = 0;
for (uint8_t j=0; j<maxEpPerInterface; j++)
hidInterfaces[i].epIndex[j] = 0;
}
for(uint8_t i=0; i<totalEndpoints; i++)
{
epInfo[i].epAddr = 0;
epInfo[i].maxPktSize = (i) ? 0 : 8;
epInfo[i].epAttribs = 0;
if (!i)
epInfo[i].bmNakPower = USB_NAK_MAX_POWER;
}
bNumEP = 1;
bNumIface = 0;
bConfNum = 0;
}
bool HIDUniversal::SetReportParser(uint8_t id, HIDReportParser *prs)
{
for (uint8_t i=0; i<MAX_REPORT_PARSERS; i++)
{
if (rptParsers[i].rptId == 0 && rptParsers[i].rptParser == NULL)
{
rptParsers[i].rptId = id;
rptParsers[i].rptParser = prs;
return true;
}
}
return false;
}
HIDReportParser* HIDUniversal::GetReportParser(uint8_t id)
{
if (!bHasReportId)
return ((rptParsers[0].rptParser) ? rptParsers[0].rptParser : NULL);
for (uint8_t i=0; i<MAX_REPORT_PARSERS; i++)
{
if (rptParsers[i].rptId == id)
return rptParsers[i].rptParser;
}
return NULL;
}
uint8_t HIDUniversal::Init(uint8_t parent, uint8_t port, bool lowspeed)
{
const uint8_t constBufSize = sizeof(USB_DEVICE_DESCRIPTOR);
uint8_t buf[constBufSize];
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();
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<num_of_conf; i++)
{
HexDumper<USBReadParser, uint16_t, uint16_t> HexDump;
ConfigDescParser<USB_CLASS_HID, 0, 0,
CP_MASK_COMPARE_CLASS> 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<bNumIface; i++)
{
if (hidInterfaces[i].epIndex[epInterruptInIndex] == 0)
continue;
USBTRACE("Proto\r\n");
//rcode = SetProtocol(hidInterfaces[i].bmInterface, HID_RPT_PROTOCOL);
//if (rcode)
// goto FailSetProtocol;
rcode = SetIdle(hidInterfaces[i].bmInterface, 0, 0);
if (rcode)
goto FailSetIdle;
}
USBTRACE("HU configured\r\n");
{
HexDumper<USBReadParser, uint16_t, uint16_t> 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<bNumIface && i<maxHidInterfaces; i++)
if (hidInterfaces[i].bmInterface == iface && hidInterfaces[i].bmAltSet == alt
&& hidInterfaces[i].bmProtocol == proto)
return hidInterfaces + i;
return NULL;
}
void HIDUniversal::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *pep)
{
// If the first configuration satisfies, the others are not concidered.
if (bNumEP > 1 && conf != bConfNum)
return;
ErrorMessage<uint8_t>(PSTR("\r\nConf.Val"), conf);
ErrorMessage<uint8_t>(PSTR("Iface Num"), iface);
ErrorMessage<uint8_t>(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; i<bNumIface; i++)
{
uint8_t index = hidInterfaces[i].epIndex[epInterruptInIndex];
uint16_t read = (uint16_t)epInfo[index].maxPktSize;
USBTRACE2("i:", i);
USBTRACE2("Ind:", index);
USBTRACE2("EP:", epInfo[index].epAddr);
USBTRACE2("Rd:", read);
uint8_t rcode = pUsb->inTransfer(bAddress, epInfo[index].epAddr, &read, buf);
if (rcode)
{
if (rcode != hrNAK)
USBTRACE2("Poll:", rcode);
else
USBTRACE2("poll:", rcode);
return rcode;
}
Serial.print("Read:");
PrintHex<uint8_t>(read);
Serial.println("");
for (uint8_t i=0; i<read; i++)
PrintHex<uint8_t>(buf[i]);
if (read)
Serial.println("");
HIDReportParser *prs = GetReportParser( ((bHasReportId) ? *buf : 0) );
if (prs)
prs->Parse(this, bHasReportId, (uint8_t)read, buf);
}
}
return rcode;
}

67
hiduniversal.h Normal file
View file

@ -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__