mirror of
https://github.com/felis/USB_Host_Shield_2.0.git
synced 2024-03-22 11:31:26 +01:00
Merge my debug changes.
Merge my format sanity changes. Track everything.
This commit is contained in:
parent
f5856c72bc
commit
629594f957
39 changed files with 11136 additions and 11344 deletions
182
Usb.cpp
182
Usb.cpp
|
@ -31,31 +31,26 @@ static uint8_t usb_error = 0;
|
||||||
static uint8_t usb_task_state;
|
static uint8_t usb_task_state;
|
||||||
|
|
||||||
/* constructor */
|
/* constructor */
|
||||||
USB::USB () : bmHubPre(0)
|
USB::USB() : bmHubPre(0) {
|
||||||
{
|
|
||||||
usb_task_state = USB_DETACHED_SUBSTATE_INITIALIZE; //set up state machine
|
usb_task_state = USB_DETACHED_SUBSTATE_INITIALIZE; //set up state machine
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize data structures */
|
/* Initialize data structures */
|
||||||
void USB::init()
|
void USB::init() {
|
||||||
{
|
|
||||||
devConfigIndex = 0;
|
devConfigIndex = 0;
|
||||||
bmHubPre = 0;
|
bmHubPre = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t USB::getUsbTaskState( void )
|
uint8_t USB::getUsbTaskState(void) {
|
||||||
{
|
|
||||||
return ( usb_task_state);
|
return ( usb_task_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
void USB::setUsbTaskState( uint8_t state )
|
void USB::setUsbTaskState(uint8_t state) {
|
||||||
{
|
|
||||||
usb_task_state = state;
|
usb_task_state = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
EpInfo* USB::getEpInfoEntry( uint8_t addr, uint8_t ep )
|
EpInfo* USB::getEpInfoEntry(uint8_t addr, uint8_t ep) {
|
||||||
{
|
|
||||||
UsbDevice *p = addrPool.GetUsbDevicePtr(addr);
|
UsbDevice *p = addrPool.GetUsbDevicePtr(addr);
|
||||||
|
|
||||||
if (!p || !p->epinfo)
|
if (!p || !p->epinfo)
|
||||||
|
@ -63,8 +58,7 @@ EpInfo* USB::getEpInfoEntry( uint8_t addr, uint8_t ep )
|
||||||
|
|
||||||
EpInfo *pep = p->epinfo;
|
EpInfo *pep = p->epinfo;
|
||||||
|
|
||||||
for (uint8_t i=0; i<p->epcount; i++)
|
for (uint8_t i = 0; i < p->epcount; i++) {
|
||||||
{
|
|
||||||
if ((pep)->epAddr == ep)
|
if ((pep)->epAddr == ep)
|
||||||
return pep;
|
return pep;
|
||||||
|
|
||||||
|
@ -74,9 +68,9 @@ EpInfo* USB::getEpInfoEntry( uint8_t addr, uint8_t ep )
|
||||||
}
|
}
|
||||||
|
|
||||||
/* set device table entry */
|
/* set device table entry */
|
||||||
|
|
||||||
/* each device is different and has different number of endpoints. This function plugs endpoint record structure, defined in application, to devtable */
|
/* each device is different and has different number of endpoints. This function plugs endpoint record structure, defined in application, to devtable */
|
||||||
uint8_t USB::setEpInfoEntry( uint8_t addr, uint8_t epcount, EpInfo* eprecord_ptr )
|
uint8_t USB::setEpInfoEntry(uint8_t addr, uint8_t epcount, EpInfo* eprecord_ptr) {
|
||||||
{
|
|
||||||
if (!eprecord_ptr)
|
if (!eprecord_ptr)
|
||||||
return USB_ERROR_INVALID_ARGUMENT;
|
return USB_ERROR_INVALID_ARGUMENT;
|
||||||
|
|
||||||
|
@ -92,8 +86,7 @@ uint8_t USB::setEpInfoEntry( uint8_t addr, uint8_t epcount, EpInfo* eprecord_ptr
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t USB::SetAddress(uint8_t addr, uint8_t ep, EpInfo **ppep, uint16_t &nak_limit)
|
uint8_t USB::SetAddress(uint8_t addr, uint8_t ep, EpInfo **ppep, uint16_t &nak_limit) {
|
||||||
{
|
|
||||||
UsbDevice *p = addrPool.GetUsbDevicePtr(addr);
|
UsbDevice *p = addrPool.GetUsbDevicePtr(addr);
|
||||||
|
|
||||||
if (!p)
|
if (!p)
|
||||||
|
@ -109,7 +102,6 @@ uint8_t USB::SetAddress(uint8_t addr, uint8_t ep, EpInfo **ppep, uint16_t &nak_l
|
||||||
|
|
||||||
nak_limit = (0x0001UL << (((*ppep)->bmNakPower > USB_NAK_MAX_POWER) ? USB_NAK_MAX_POWER : (*ppep)->bmNakPower));
|
nak_limit = (0x0001UL << (((*ppep)->bmNakPower > USB_NAK_MAX_POWER) ? USB_NAK_MAX_POWER : (*ppep)->bmNakPower));
|
||||||
nak_limit--;
|
nak_limit--;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
USBTRACE2("\r\nAddress: ", addr);
|
USBTRACE2("\r\nAddress: ", addr);
|
||||||
USBTRACE2(" EP: ", ep);
|
USBTRACE2(" EP: ", ep);
|
||||||
|
@ -131,11 +123,11 @@ uint8_t USB::SetAddress(uint8_t addr, uint8_t ep, EpInfo **ppep, uint16_t &nak_l
|
||||||
/* depending on request. Actual requests are defined as inlines */
|
/* depending on request. Actual requests are defined as inlines */
|
||||||
/* return codes: */
|
/* return codes: */
|
||||||
/* 00 = success */
|
/* 00 = success */
|
||||||
|
|
||||||
/* 01-0f = non-zero HRSLT */
|
/* 01-0f = non-zero HRSLT */
|
||||||
uint8_t USB::ctrlReq(uint8_t addr, uint8_t ep, uint8_t bmReqType, uint8_t bRequest, uint8_t wValLo, uint8_t wValHi,
|
uint8_t USB::ctrlReq(uint8_t addr, uint8_t ep, uint8_t bmReqType, uint8_t bRequest, uint8_t wValLo, uint8_t wValHi,
|
||||||
uint16_t wInd, uint16_t total, uint16_t nbytes, uint8_t* dataptr, USBReadParser *p)
|
uint16_t wInd, uint16_t total, uint16_t nbytes, uint8_t* dataptr, USBReadParser *p) {
|
||||||
{
|
bool direction = false; //request direction, IN or OUT
|
||||||
boolean direction = false; //request direction, IN or OUT
|
|
||||||
uint8_t rcode;
|
uint8_t rcode;
|
||||||
SETUP_PKT setup_pkt;
|
SETUP_PKT setup_pkt;
|
||||||
|
|
||||||
|
@ -172,8 +164,7 @@ uint8_t USB::ctrlReq( uint8_t addr, uint8_t ep, uint8_t bmReqType, uint8_t bRequ
|
||||||
|
|
||||||
pep->bmRcvToggle = 1; //bmRCVTOG1;
|
pep->bmRcvToggle = 1; //bmRCVTOG1;
|
||||||
|
|
||||||
while (left)
|
while (left) {
|
||||||
{
|
|
||||||
// Bytes read into buffer
|
// Bytes read into buffer
|
||||||
uint16_t read = nbytes;
|
uint16_t read = nbytes;
|
||||||
//uint16_t read = (left<nbytes) ? left : nbytes;
|
//uint16_t read = (left<nbytes) ? left : nbytes;
|
||||||
|
@ -192,8 +183,7 @@ uint8_t USB::ctrlReq( uint8_t addr, uint8_t ep, uint8_t bmReqType, uint8_t bRequ
|
||||||
if (read < nbytes)
|
if (read < nbytes)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
} else //OUT transfer
|
||||||
else //OUT transfer
|
|
||||||
{
|
{
|
||||||
pep->bmSndToggle = 1; //bmSNDTOG1;
|
pep->bmSndToggle = 1; //bmSNDTOG1;
|
||||||
rcode = OutTransfer(pep, nak_limit, nbytes, dataptr);
|
rcode = OutTransfer(pep, nak_limit, nbytes, dataptr);
|
||||||
|
@ -207,27 +197,28 @@ uint8_t USB::ctrlReq( uint8_t addr, uint8_t ep, uint8_t bmReqType, uint8_t bRequ
|
||||||
|
|
||||||
/* IN transfer to arbitrary endpoint. Assumes PERADDR is set. Handles multiple packets if necessary. Transfers 'nbytes' bytes. */
|
/* IN transfer to arbitrary endpoint. Assumes PERADDR is set. Handles multiple packets if necessary. Transfers 'nbytes' bytes. */
|
||||||
/* Keep sending INs and writes data to memory area pointed by 'data' */
|
/* Keep sending INs and writes data to memory area pointed by 'data' */
|
||||||
|
|
||||||
/* rcode 0 if no errors. rcode 01-0f is relayed from dispatchPkt(). Rcode f0 means RCVDAVIRQ error,
|
/* rcode 0 if no errors. rcode 01-0f is relayed from dispatchPkt(). Rcode f0 means RCVDAVIRQ error,
|
||||||
fe USB xfer timeout */
|
fe USB xfer timeout */
|
||||||
uint8_t USB::inTransfer( uint8_t addr, uint8_t ep, uint16_t *nbytesptr, uint8_t* data)
|
uint8_t USB::inTransfer(uint8_t addr, uint8_t ep, uint16_t *nbytesptr, uint8_t* data) {
|
||||||
{
|
|
||||||
EpInfo *pep = NULL;
|
EpInfo *pep = NULL;
|
||||||
uint16_t nak_limit = 0;
|
uint16_t nak_limit = 0;
|
||||||
|
|
||||||
uint8_t rcode = SetAddress(addr, ep, &pep, nak_limit);
|
uint8_t rcode = SetAddress(addr, ep, &pep, nak_limit);
|
||||||
|
|
||||||
if (rcode)
|
if (rcode) {
|
||||||
|
//printf("SetAddress Failed");
|
||||||
return rcode;
|
return rcode;
|
||||||
|
}
|
||||||
return InTransfer(pep, nak_limit, nbytesptr, data);
|
return InTransfer(pep, nak_limit, nbytesptr, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t USB::InTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t *nbytesptr, uint8_t* data)
|
uint8_t USB::InTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t *nbytesptr, uint8_t* data) {
|
||||||
{
|
|
||||||
uint8_t rcode = 0;
|
uint8_t rcode = 0;
|
||||||
uint8_t pktsize;
|
uint8_t pktsize;
|
||||||
|
|
||||||
uint16_t nbytes = *nbytesptr;
|
uint16_t nbytes = *nbytesptr;
|
||||||
|
//printf("Requesting %i bytes ", nbytes);
|
||||||
uint8_t maxpktsize = pep->maxPktSize;
|
uint8_t maxpktsize = pep->maxPktSize;
|
||||||
|
|
||||||
*nbytesptr = 0;
|
*nbytesptr = 0;
|
||||||
|
@ -237,16 +228,19 @@ uint8_t USB::InTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t *nbytesptr, ui
|
||||||
{
|
{
|
||||||
rcode = dispatchPkt(tokIN, pep->epAddr, nak_limit); //IN packet to EP-'endpoint'. Function takes care of NAKS.
|
rcode = dispatchPkt(tokIN, pep->epAddr, nak_limit); //IN packet to EP-'endpoint'. Function takes care of NAKS.
|
||||||
|
|
||||||
if( rcode )
|
if (rcode) {
|
||||||
return( rcode ); //should be 0, indicating ACK. Else return error code.
|
//printf("Problem! %i\r\n", rcode);
|
||||||
|
break; //should be 0, indicating ACK. Else return error code.
|
||||||
|
}
|
||||||
/* check for RCVDAVIRQ and generate error if not present */
|
/* check for RCVDAVIRQ and generate error if not present */
|
||||||
/* the only case when absense of RCVDAVIRQ makes sense is when toggle error occured. Need to add handling for that */
|
/* the only case when absense of RCVDAVIRQ makes sense is when toggle error occured. Need to add handling for that */
|
||||||
if(( regRd( rHIRQ ) & bmRCVDAVIRQ ) == 0 )
|
if ((regRd(rHIRQ) & bmRCVDAVIRQ) == 0) {
|
||||||
return ( 0xf0 ); //receive error
|
//printf("Problem! NO RCVDAVIRQ!\r\n");
|
||||||
|
rcode = 0xf0; //receive error
|
||||||
|
break;
|
||||||
|
}
|
||||||
pktsize = regRd(rRCVBC); //number of received bytes
|
pktsize = regRd(rRCVBC); //number of received bytes
|
||||||
|
//printf("Got %i bytes ", pktsize);
|
||||||
assert(pktsize <= nbytes);
|
assert(pktsize <= nbytes);
|
||||||
|
|
||||||
int16_t mem_left = (int16_t) nbytes - *((int16_t*) nbytesptr);
|
int16_t mem_left = (int16_t) nbytes - *((int16_t*) nbytesptr);
|
||||||
|
@ -266,17 +260,19 @@ uint8_t USB::InTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t *nbytesptr, ui
|
||||||
{
|
{
|
||||||
// Save toggle value
|
// Save toggle value
|
||||||
pep->bmRcvToggle = ((regRd(rHRSL) & bmRCVTOGRD)) ? 1 : 0;
|
pep->bmRcvToggle = ((regRd(rHRSL) & bmRCVTOGRD)) ? 1 : 0;
|
||||||
|
//printf("\r\n");
|
||||||
return( 0 );
|
rcode = 0;
|
||||||
|
break;
|
||||||
} // if
|
} // if
|
||||||
} //while( 1 )
|
} //while( 1 )
|
||||||
|
return ( rcode);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* OUT transfer to arbitrary endpoint. Handles multiple packets if necessary. Transfers 'nbytes' bytes. */
|
/* OUT transfer to arbitrary endpoint. Handles multiple packets if necessary. Transfers 'nbytes' bytes. */
|
||||||
/* Handles NAK bug per Maxim Application Note 4000 for single buffer transfer */
|
/* Handles NAK bug per Maxim Application Note 4000 for single buffer transfer */
|
||||||
|
|
||||||
/* rcode 0 if no errors. rcode 01-0f is relayed from HRSL */
|
/* rcode 0 if no errors. rcode 01-0f is relayed from HRSL */
|
||||||
uint8_t USB::outTransfer( uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* data )
|
uint8_t USB::outTransfer(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* data) {
|
||||||
{
|
|
||||||
EpInfo *pep = NULL;
|
EpInfo *pep = NULL;
|
||||||
uint16_t nak_limit;
|
uint16_t nak_limit;
|
||||||
|
|
||||||
|
@ -288,9 +284,8 @@ uint8_t USB::outTransfer( uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* da
|
||||||
return OutTransfer(pep, nak_limit, nbytes, data);
|
return OutTransfer(pep, nak_limit, nbytes, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t USB::OutTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t nbytes, uint8_t *data)
|
uint8_t USB::OutTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t nbytes, uint8_t *data) {
|
||||||
{
|
uint8_t rcode = hrSUCCESS, retry_count;
|
||||||
uint8_t rcode, retry_count;
|
|
||||||
uint8_t *data_p = data; //local copy of the data pointer
|
uint8_t *data_p = data; //local copy of the data pointer
|
||||||
uint16_t bytes_tosend, nak_count;
|
uint16_t bytes_tosend, nak_count;
|
||||||
uint16_t bytes_left = nbytes;
|
uint16_t bytes_left = nbytes;
|
||||||
|
@ -304,8 +299,7 @@ uint8_t USB::OutTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t nbytes, uint8
|
||||||
|
|
||||||
regWr(rHCTL, (pep->bmSndToggle) ? bmSNDTOG1 : bmSNDTOG0); //set toggle value
|
regWr(rHCTL, (pep->bmSndToggle) ? bmSNDTOG1 : bmSNDTOG0); //set toggle value
|
||||||
|
|
||||||
while( bytes_left )
|
while (bytes_left) {
|
||||||
{
|
|
||||||
retry_count = 0;
|
retry_count = 0;
|
||||||
nak_count = 0;
|
nak_count = 0;
|
||||||
bytes_tosend = (bytes_left >= maxpktsize) ? maxpktsize : bytes_left;
|
bytes_tosend = (bytes_left >= maxpktsize) ? maxpktsize : bytes_left;
|
||||||
|
@ -316,10 +310,8 @@ uint8_t USB::OutTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t nbytes, uint8
|
||||||
regWr(rHIRQ, bmHXFRDNIRQ); //clear IRQ
|
regWr(rHIRQ, bmHXFRDNIRQ); //clear IRQ
|
||||||
rcode = (regRd(rHRSL) & 0x0f);
|
rcode = (regRd(rHRSL) & 0x0f);
|
||||||
|
|
||||||
while( rcode && ( timeout > millis()))
|
while (rcode && (timeout > millis())) {
|
||||||
{
|
switch (rcode) {
|
||||||
switch( rcode )
|
|
||||||
{
|
|
||||||
case hrNAK:
|
case hrNAK:
|
||||||
nak_count++;
|
nak_count++;
|
||||||
if (nak_limit && (nak_count == nak_limit))
|
if (nak_limit && (nak_count == nak_limit))
|
||||||
|
@ -353,17 +345,16 @@ uint8_t USB::OutTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t nbytes, uint8
|
||||||
/* If NAK, tries to re-send up to nak_limit times */
|
/* If NAK, tries to re-send up to nak_limit times */
|
||||||
/* If nak_limit == 0, do not count NAKs, exit after timeout */
|
/* If nak_limit == 0, do not count NAKs, exit after timeout */
|
||||||
/* If bus timeout, re-sends up to USB_RETRY_LIMIT times */
|
/* If bus timeout, re-sends up to USB_RETRY_LIMIT times */
|
||||||
|
|
||||||
/* return codes 0x00-0x0f are HRSLT( 0x00 being success ), 0xff means timeout */
|
/* return codes 0x00-0x0f are HRSLT( 0x00 being success ), 0xff means timeout */
|
||||||
uint8_t USB::dispatchPkt( uint8_t token, uint8_t ep, uint16_t nak_limit )
|
uint8_t USB::dispatchPkt(uint8_t token, uint8_t ep, uint16_t nak_limit) {
|
||||||
{
|
|
||||||
unsigned long timeout = millis() + USB_XFER_TIMEOUT;
|
unsigned long timeout = millis() + USB_XFER_TIMEOUT;
|
||||||
uint8_t tmpdata;
|
uint8_t tmpdata;
|
||||||
uint8_t rcode;
|
uint8_t rcode = hrSUCCESS;
|
||||||
uint8_t retry_count = 0;
|
uint8_t retry_count = 0;
|
||||||
uint16_t nak_count = 0;
|
uint16_t nak_count = 0;
|
||||||
|
|
||||||
while( timeout > millis() )
|
while (timeout > millis()) {
|
||||||
{
|
|
||||||
regWr(rHXFR, (token | ep)); //launch the transfer
|
regWr(rHXFR, (token | ep)); //launch the transfer
|
||||||
rcode = USB_ERROR_TRANSFER_TIMEOUT;
|
rcode = USB_ERROR_TRANSFER_TIMEOUT;
|
||||||
|
|
||||||
|
@ -371,8 +362,7 @@ uint8_t USB::dispatchPkt( uint8_t token, uint8_t ep, uint16_t nak_limit )
|
||||||
{
|
{
|
||||||
tmpdata = regRd(rHIRQ);
|
tmpdata = regRd(rHIRQ);
|
||||||
|
|
||||||
if( tmpdata & bmHXFRDNIRQ )
|
if (tmpdata & bmHXFRDNIRQ) {
|
||||||
{
|
|
||||||
regWr(rHIRQ, bmHXFRDNIRQ); //clear the interrupt
|
regWr(rHIRQ, bmHXFRDNIRQ); //clear the interrupt
|
||||||
rcode = 0x00;
|
rcode = 0x00;
|
||||||
break;
|
break;
|
||||||
|
@ -385,13 +375,11 @@ uint8_t USB::dispatchPkt( uint8_t token, uint8_t ep, uint16_t nak_limit )
|
||||||
|
|
||||||
rcode = (regRd(rHRSL) & 0x0f); //analyze transfer result
|
rcode = (regRd(rHRSL) & 0x0f); //analyze transfer result
|
||||||
|
|
||||||
switch( rcode )
|
switch (rcode) {
|
||||||
{
|
|
||||||
case hrNAK:
|
case hrNAK:
|
||||||
nak_count++;
|
nak_count++;
|
||||||
if (nak_limit && (nak_count == nak_limit))
|
if (nak_limit && (nak_count == nak_limit))
|
||||||
return ( rcode);
|
return ( rcode);
|
||||||
//delay(1);
|
|
||||||
break;
|
break;
|
||||||
case hrTIMEOUT:
|
case hrTIMEOUT:
|
||||||
retry_count++;
|
retry_count++;
|
||||||
|
@ -412,7 +400,7 @@ void USB::Task( void ) //USB state machine
|
||||||
uint8_t rcode;
|
uint8_t rcode;
|
||||||
uint8_t tmpdata;
|
uint8_t tmpdata;
|
||||||
static unsigned long delay = 0;
|
static unsigned long delay = 0;
|
||||||
USB_DEVICE_DESCRIPTOR buf;
|
//USB_DEVICE_DESCRIPTOR buf;
|
||||||
bool lowspeed = false;
|
bool lowspeed = false;
|
||||||
|
|
||||||
MAX3421E::Task();
|
MAX3421E::Task();
|
||||||
|
@ -420,8 +408,7 @@ void USB::Task( void ) //USB state machine
|
||||||
tmpdata = getVbusState();
|
tmpdata = getVbusState();
|
||||||
|
|
||||||
/* modify USB task state if Vbus changed */
|
/* modify USB task state if Vbus changed */
|
||||||
switch( tmpdata )
|
switch (tmpdata) {
|
||||||
{
|
|
||||||
case SE1: //illegal state
|
case SE1: //illegal state
|
||||||
usb_task_state = USB_DETACHED_SUBSTATE_ILLEGAL;
|
usb_task_state = USB_DETACHED_SUBSTATE_ILLEGAL;
|
||||||
lowspeed = false;
|
lowspeed = false;
|
||||||
|
@ -434,8 +421,7 @@ void USB::Task( void ) //USB state machine
|
||||||
case LSHOST:
|
case LSHOST:
|
||||||
lowspeed = true;
|
lowspeed = true;
|
||||||
case FSHOST: //attached
|
case FSHOST: //attached
|
||||||
if(( usb_task_state & USB_STATE_MASK ) == USB_STATE_DETACHED )
|
if ((usb_task_state & USB_STATE_MASK) == USB_STATE_DETACHED) {
|
||||||
{
|
|
||||||
delay = millis() + USB_SETTLE_DELAY;
|
delay = millis() + USB_SETTLE_DELAY;
|
||||||
usb_task_state = USB_ATTACHED_SUBSTATE_SETTLE;
|
usb_task_state = USB_ATTACHED_SUBSTATE_SETTLE;
|
||||||
}
|
}
|
||||||
|
@ -460,7 +446,7 @@ void USB::Task( void ) //USB state machine
|
||||||
break;
|
break;
|
||||||
case USB_DETACHED_SUBSTATE_ILLEGAL: //just sit here
|
case USB_DETACHED_SUBSTATE_ILLEGAL: //just sit here
|
||||||
break;
|
break;
|
||||||
case USB_ATTACHED_SUBSTATE_SETTLE: //setlle time for just attached device
|
case USB_ATTACHED_SUBSTATE_SETTLE: //settle time for just attached device
|
||||||
if (delay < millis())
|
if (delay < millis())
|
||||||
usb_task_state = USB_ATTACHED_SUBSTATE_RESET_DEVICE;
|
usb_task_state = USB_ATTACHED_SUBSTATE_RESET_DEVICE;
|
||||||
break;
|
break;
|
||||||
|
@ -469,8 +455,7 @@ void USB::Task( void ) //USB state machine
|
||||||
usb_task_state = USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE;
|
usb_task_state = USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE;
|
||||||
break;
|
break;
|
||||||
case USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE:
|
case USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE:
|
||||||
if(( regRd( rHCTL ) & bmBUSRST ) == 0 )
|
if ((regRd(rHCTL) & bmBUSRST) == 0) {
|
||||||
{
|
|
||||||
tmpdata = regRd(rMODE) | bmSOFKAENAB; //start SOF generation
|
tmpdata = regRd(rMODE) | bmSOFKAENAB; //start SOF generation
|
||||||
regWr(rMODE, tmpdata);
|
regWr(rMODE, tmpdata);
|
||||||
usb_task_state = USB_ATTACHED_SUBSTATE_WAIT_SOF;
|
usb_task_state = USB_ATTACHED_SUBSTATE_WAIT_SOF;
|
||||||
|
@ -487,15 +472,12 @@ void USB::Task( void ) //USB state machine
|
||||||
case USB_STATE_CONFIGURING:
|
case USB_STATE_CONFIGURING:
|
||||||
rcode = Configuring(0, 0, lowspeed);
|
rcode = Configuring(0, 0, lowspeed);
|
||||||
|
|
||||||
if (rcode)
|
if (rcode) {
|
||||||
{
|
if (rcode != USB_DEV_CONFIG_ERROR_DEVICE_INIT_INCOMPLETE) {
|
||||||
if (rcode != USB_DEV_CONFIG_ERROR_DEVICE_INIT_INCOMPLETE)
|
|
||||||
{
|
|
||||||
usb_error = rcode;
|
usb_error = rcode;
|
||||||
usb_task_state = USB_STATE_ERROR;
|
usb_task_state = USB_STATE_ERROR;
|
||||||
}
|
}
|
||||||
}
|
} else
|
||||||
else
|
|
||||||
usb_task_state = USB_STATE_RUNNING;
|
usb_task_state = USB_STATE_RUNNING;
|
||||||
break;
|
break;
|
||||||
case USB_STATE_RUNNING:
|
case USB_STATE_RUNNING:
|
||||||
|
@ -505,9 +487,8 @@ void USB::Task( void ) //USB state machine
|
||||||
} // switch( usb_task_state )
|
} // switch( usb_task_state )
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t USB::DefaultAddressing(uint8_t parent, uint8_t port, bool lowspeed)
|
uint8_t USB::DefaultAddressing(uint8_t parent, uint8_t port, bool lowspeed) {
|
||||||
{
|
//uint8_t buf[12];
|
||||||
uint8_t buf[12];
|
|
||||||
uint8_t rcode;
|
uint8_t rcode;
|
||||||
UsbDevice *p0 = NULL, *p = NULL;
|
UsbDevice *p0 = NULL, *p = NULL;
|
||||||
|
|
||||||
|
@ -538,8 +519,7 @@ uint8_t USB::DefaultAddressing(uint8_t parent, uint8_t port, bool lowspeed)
|
||||||
// Assign new address to the device
|
// Assign new address to the device
|
||||||
rcode = setAddr(0, 0, bAddress);
|
rcode = setAddr(0, 0, bAddress);
|
||||||
|
|
||||||
if (rcode)
|
if (rcode) {
|
||||||
{
|
|
||||||
addrPool.FreeAddress(bAddress);
|
addrPool.FreeAddress(bAddress);
|
||||||
bAddress = 0;
|
bAddress = 0;
|
||||||
return rcode;
|
return rcode;
|
||||||
|
@ -547,25 +527,21 @@ uint8_t USB::DefaultAddressing(uint8_t parent, uint8_t port, bool lowspeed)
|
||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
uint8_t USB::Configuring(uint8_t parent, uint8_t port, bool lowspeed)
|
uint8_t USB::Configuring(uint8_t parent, uint8_t port, bool lowspeed) {
|
||||||
{
|
//static uint8_t dev_index = 0;
|
||||||
static uint8_t dev_index = 0;
|
|
||||||
uint8_t rcode = 0;
|
uint8_t rcode = 0;
|
||||||
|
|
||||||
for (; devConfigIndex<USB_NUMDEVICES; devConfigIndex++)
|
for (; devConfigIndex < USB_NUMDEVICES; devConfigIndex++) {
|
||||||
{
|
|
||||||
if (!devConfig[devConfigIndex])
|
if (!devConfig[devConfigIndex])
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
rcode = devConfig[devConfigIndex]->Init(parent, port, lowspeed);
|
rcode = devConfig[devConfigIndex]->Init(parent, port, lowspeed);
|
||||||
|
|
||||||
if (!rcode)
|
if (!rcode) {
|
||||||
{
|
|
||||||
devConfigIndex = 0;
|
devConfigIndex = 0;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (!(rcode == USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED || rcode == USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE))
|
if (!(rcode == USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED || rcode == USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE)) {
|
||||||
{
|
|
||||||
// in case of an error dev_index should be reset to 0
|
// in case of an error dev_index should be reset to 0
|
||||||
// in order to start from the very beginning the
|
// in order to start from the very beginning the
|
||||||
// next time the program gets here
|
// next time the program gets here
|
||||||
|
@ -583,30 +559,30 @@ uint8_t USB::Configuring(uint8_t parent, uint8_t port, bool lowspeed)
|
||||||
return rcode;
|
return rcode;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t USB::ReleaseDevice(uint8_t addr)
|
uint8_t USB::ReleaseDevice(uint8_t addr) {
|
||||||
{
|
|
||||||
if (!addr)
|
if (!addr)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
for (uint8_t i = 0; i < USB_NUMDEVICES; i++)
|
for (uint8_t i = 0; i < USB_NUMDEVICES; i++)
|
||||||
if (devConfig[i]->GetAddress() == addr)
|
if (devConfig[i]->GetAddress() == addr)
|
||||||
return devConfig[i]->Release();
|
return devConfig[i]->Release();
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 1 //!defined(USB_METHODS_INLINE)
|
#if 1 //!defined(USB_METHODS_INLINE)
|
||||||
//get device descriptor
|
//get device descriptor
|
||||||
uint8_t USB::getDevDescr( uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* dataptr )
|
|
||||||
{
|
uint8_t USB::getDevDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* dataptr) {
|
||||||
return ( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, 0x00, USB_DESCRIPTOR_DEVICE, 0x0000, nbytes, nbytes, dataptr, NULL));
|
return ( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, 0x00, USB_DESCRIPTOR_DEVICE, 0x0000, nbytes, nbytes, dataptr, NULL));
|
||||||
}
|
}
|
||||||
//get configuration descriptor
|
//get configuration descriptor
|
||||||
uint8_t USB::getConfDescr( uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t conf, uint8_t* dataptr )
|
|
||||||
{
|
uint8_t USB::getConfDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t conf, uint8_t* dataptr) {
|
||||||
return ( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, conf, USB_DESCRIPTOR_CONFIGURATION, 0x0000, nbytes, nbytes, dataptr, NULL));
|
return ( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, conf, USB_DESCRIPTOR_CONFIGURATION, 0x0000, nbytes, nbytes, dataptr, NULL));
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t USB::getConfDescr( uint8_t addr, uint8_t ep, uint8_t conf, USBReadParser *p )
|
uint8_t USB::getConfDescr(uint8_t addr, uint8_t ep, uint8_t conf, USBReadParser *p) {
|
||||||
{
|
|
||||||
const uint8_t bufSize = 64;
|
const uint8_t bufSize = 64;
|
||||||
uint8_t buf[bufSize];
|
uint8_t buf[bufSize];
|
||||||
|
|
||||||
|
@ -616,25 +592,25 @@ uint8_t USB::getConfDescr( uint8_t addr, uint8_t ep, uint8_t conf, USBReadParser
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
uint16_t total = ((USB_CONFIGURATION_DESCRIPTOR*) buf)->wTotalLength;
|
uint16_t total = ((USB_CONFIGURATION_DESCRIPTOR*) buf)->wTotalLength;
|
||||||
delay(100);
|
|
||||||
//USBTRACE2("\r\ntotal conf.size:", total);
|
//USBTRACE2("\r\ntotal conf.size:", total);
|
||||||
|
|
||||||
return ( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, conf, USB_DESCRIPTOR_CONFIGURATION, 0x0000, total, bufSize, buf, p));
|
return ( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, conf, USB_DESCRIPTOR_CONFIGURATION, 0x0000, total, bufSize, buf, p));
|
||||||
}
|
}
|
||||||
|
|
||||||
//get string descriptor
|
//get string descriptor
|
||||||
uint8_t USB::getStrDescr( uint8_t addr, uint8_t ep, uint16_t ns, uint8_t index, uint16_t langid, uint8_t* dataptr )
|
|
||||||
{
|
uint8_t USB::getStrDescr(uint8_t addr, uint8_t ep, uint16_t ns, uint8_t index, uint16_t langid, uint8_t* dataptr) {
|
||||||
return ( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, index, USB_DESCRIPTOR_STRING, langid, ns, ns, dataptr, NULL));
|
return ( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, index, USB_DESCRIPTOR_STRING, langid, ns, ns, dataptr, NULL));
|
||||||
}
|
}
|
||||||
//set address
|
//set address
|
||||||
uint8_t USB::setAddr( uint8_t oldaddr, uint8_t ep, uint8_t newaddr )
|
|
||||||
{
|
uint8_t USB::setAddr(uint8_t oldaddr, uint8_t ep, uint8_t newaddr) {
|
||||||
return ( ctrlReq(oldaddr, ep, bmREQ_SET, USB_REQUEST_SET_ADDRESS, newaddr, 0x00, 0x0000, 0x0000, 0x0000, NULL, NULL));
|
return ( ctrlReq(oldaddr, ep, bmREQ_SET, USB_REQUEST_SET_ADDRESS, newaddr, 0x00, 0x0000, 0x0000, 0x0000, NULL, NULL));
|
||||||
}
|
}
|
||||||
//set configuration
|
//set configuration
|
||||||
uint8_t USB::setConf( uint8_t addr, uint8_t ep, uint8_t conf_value )
|
|
||||||
{
|
uint8_t USB::setConf(uint8_t addr, uint8_t ep, uint8_t conf_value) {
|
||||||
return ( ctrlReq(addr, ep, bmREQ_SET, USB_REQUEST_SET_CONFIGURATION, conf_value, 0x00, 0x0000, 0x0000, 0x0000, NULL, NULL));
|
return ( ctrlReq(addr, ep, bmREQ_SET, USB_REQUEST_SET_CONFIGURATION, conf_value, 0x00, 0x0000, 0x0000, 0x0000, NULL, NULL));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
85
Usb.h
85
Usb.h
|
@ -44,28 +44,18 @@ e-mail : support@circuitsathome.com
|
||||||
#include "hexdump.h"
|
#include "hexdump.h"
|
||||||
#include "message.h"
|
#include "message.h"
|
||||||
|
|
||||||
|
extern int UsbDEBUGlvl;
|
||||||
/* shield pins. First parameter - SS pin, second parameter - INT pin */
|
/* shield pins. First parameter - SS pin, second parameter - INT pin */
|
||||||
|
|
||||||
#if defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)
|
|
||||||
#define BOARD_TEENSY_PLUS_PLUS
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef BOARD_BLACK_WIDDOW
|
#ifdef BOARD_BLACK_WIDDOW
|
||||||
typedef MAX3421e<P6, P3> MAX3421E; // Black Widow
|
typedef MAX3421e<P6, P3> MAX3421E; // Black Widow
|
||||||
#elif defined(BOARD_TEENSY_PLUS_PLUS)
|
|
||||||
typedef MAX3421e<P9, P8> MAX3421E; // Teensy++ 2.0 & 1.0
|
|
||||||
#elif defined(BOARD_MEGA_ADK)
|
|
||||||
typedef MAX3421e<P53, P54> MAX3421E; // Arduino Mega ADK
|
|
||||||
#elif defined(BOARD_BALANDUINO)
|
|
||||||
typedef MAX3421e<P20, P19> MAX3421E; // Balanduino
|
|
||||||
#else
|
#else
|
||||||
typedef MAX3421e<P10, P9> MAX3421E; // Official Arduinos (UNO, Duemilanove, Mega, 2560, Leonardo etc.)
|
typedef MAX3421e<P10, P9> MAX3421E; // Official Arduinos (UNO, Duemilanove, Mega, 2560
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//Debug macros. In 1.0 it is possible to move strings to PROGMEM by defining USBTRACE (Serial.print(F(s)))
|
//Debug macros. In 1.0 it is possible to move strings to PROGMEM by defining USBTRACE (Serial.print(F(s)))
|
||||||
#define USBTRACE(s) (Serial.print((s)))
|
#define USBTRACE(s) (Notify(PSTR(s), 0x80))
|
||||||
#define USBTRACE2(s,r) (Serial.print((s)), Serial.println((r),HEX))
|
#define USBTRACE2(s,r) (Notify(PSTR(s), 0x80), PrintHex((r), 0x80), Notify(PSTR("\r\n"), 0x80))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -113,8 +103,7 @@ typedef MAX3421e<P10, P9> MAX3421E; // Official Arduinos (UNO, Duemilanove, Me
|
||||||
#define USB_ERROR_EP_NOT_FOUND_IN_TBL 0xDB
|
#define USB_ERROR_EP_NOT_FOUND_IN_TBL 0xDB
|
||||||
#define USB_ERROR_TRANSFER_TIMEOUT 0xFF
|
#define USB_ERROR_TRANSFER_TIMEOUT 0xFF
|
||||||
|
|
||||||
class USBDeviceConfig
|
class USBDeviceConfig {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed) = 0;
|
virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed) = 0;
|
||||||
virtual uint8_t Release() = 0;
|
virtual uint8_t Release() = 0;
|
||||||
|
@ -150,38 +139,40 @@ public:
|
||||||
|
|
||||||
/* USB Setup Packet Structure */
|
/* USB Setup Packet Structure */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|
||||||
union { // offset description
|
union { // offset description
|
||||||
uint8_t bmRequestType; // 0 Bit-map of request type
|
uint8_t bmRequestType; // 0 Bit-map of request type
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
uint8_t recipient : 5; // Recipient of the request
|
uint8_t recipient : 5; // Recipient of the request
|
||||||
uint8_t type : 2; // Type of request
|
uint8_t type : 2; // Type of request
|
||||||
uint8_t direction : 1; // Direction of data X-fer
|
uint8_t direction : 1; // Direction of data X-fer
|
||||||
};
|
}__attribute__((packed));
|
||||||
} ReqType_u;
|
} ReqType_u;
|
||||||
uint8_t bRequest; // 1 Request
|
uint8_t bRequest; // 1 Request
|
||||||
|
|
||||||
union {
|
union {
|
||||||
uint16_t wValue; // 2 Depends on bRequest
|
uint16_t wValue; // 2 Depends on bRequest
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
uint8_t wValueLo;
|
uint8_t wValueLo;
|
||||||
uint8_t wValueHi;
|
uint8_t wValueHi;
|
||||||
};
|
}__attribute__((packed));
|
||||||
} wVal_u;
|
} wVal_u;
|
||||||
uint16_t wIndex; // 4 Depends on bRequest
|
uint16_t wIndex; // 4 Depends on bRequest
|
||||||
uint16_t wLength; // 6 Depends on bRequest
|
uint16_t wLength; // 6 Depends on bRequest
|
||||||
} SETUP_PKT, *PSETUP_PKT;
|
} SETUP_PKT, *PSETUP_PKT __attribute__((packed));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Base class for incomming data parser
|
// Base class for incomming data parser
|
||||||
class USBReadParser
|
|
||||||
{
|
class USBReadParser {
|
||||||
public:
|
public:
|
||||||
virtual void Parse(const uint16_t len, const uint8_t *pbuf, const uint16_t &offset) = 0;
|
virtual void Parse(const uint16_t len, const uint8_t *pbuf, const uint16_t &offset) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class USB : public MAX3421E {
|
||||||
class USB : public MAX3421E
|
|
||||||
{
|
|
||||||
AddressPoolImpl<USB_NUMDEVICES> addrPool;
|
AddressPoolImpl<USB_NUMDEVICES> addrPool;
|
||||||
USBDeviceConfig* devConfig[USB_NUMDEVICES];
|
USBDeviceConfig* devConfig[USB_NUMDEVICES];
|
||||||
uint8_t devConfigIndex;
|
uint8_t devConfigIndex;
|
||||||
|
@ -190,27 +181,29 @@ class USB : public MAX3421E
|
||||||
public:
|
public:
|
||||||
USB(void);
|
USB(void);
|
||||||
|
|
||||||
void SetHubPreMask() { bmHubPre |= bmHUBPRE; };
|
void SetHubPreMask() {
|
||||||
void ResetHubPreMask() { bmHubPre &= (~bmHUBPRE); };
|
bmHubPre |= bmHUBPRE;
|
||||||
|
};
|
||||||
|
|
||||||
AddressPool& GetAddressPool()
|
void ResetHubPreMask() {
|
||||||
{
|
bmHubPre &= (~bmHUBPRE);
|
||||||
|
};
|
||||||
|
|
||||||
|
AddressPool& GetAddressPool() {
|
||||||
return (AddressPool&) addrPool;
|
return (AddressPool&) addrPool;
|
||||||
};
|
};
|
||||||
uint8_t RegisterDeviceClass(USBDeviceConfig *pdev)
|
|
||||||
{
|
uint8_t RegisterDeviceClass(USBDeviceConfig *pdev) {
|
||||||
for (uint8_t i=0; i<USB_NUMDEVICES; i++)
|
for (uint8_t i = 0; i < USB_NUMDEVICES; i++) {
|
||||||
{
|
if (!devConfig[i]) {
|
||||||
if (!devConfig[i])
|
|
||||||
{
|
|
||||||
devConfig[i] = pdev;
|
devConfig[i] = pdev;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return USB_ERROR_UNABLE_TO_REGISTER_DEVICE_CLASS;
|
return USB_ERROR_UNABLE_TO_REGISTER_DEVICE_CLASS;
|
||||||
};
|
};
|
||||||
void ForEachUsbDevice(UsbDeviceHandleFunc pfunc)
|
|
||||||
{
|
void ForEachUsbDevice(UsbDeviceHandleFunc pfunc) {
|
||||||
addrPool.ForEachUsbDevice(pfunc);
|
addrPool.ForEachUsbDevice(pfunc);
|
||||||
};
|
};
|
||||||
uint8_t getUsbTaskState(void);
|
uint8_t getUsbTaskState(void);
|
||||||
|
@ -255,28 +248,28 @@ class USB : public MAX3421E
|
||||||
|
|
||||||
#if 0 //defined(USB_METHODS_INLINE)
|
#if 0 //defined(USB_METHODS_INLINE)
|
||||||
//get device descriptor
|
//get device descriptor
|
||||||
inline uint8_t USB::getDevDescr( uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* dataptr )
|
|
||||||
{
|
inline uint8_t USB::getDevDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* dataptr) {
|
||||||
return ( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, 0x00, USB_DESCRIPTOR_DEVICE, 0x0000, nbytes, dataptr));
|
return ( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, 0x00, USB_DESCRIPTOR_DEVICE, 0x0000, nbytes, dataptr));
|
||||||
}
|
}
|
||||||
//get configuration descriptor
|
//get configuration descriptor
|
||||||
inline uint8_t USB::getConfDescr( uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t conf, uint8_t* dataptr )
|
|
||||||
{
|
inline uint8_t USB::getConfDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t conf, uint8_t* dataptr) {
|
||||||
return ( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, conf, USB_DESCRIPTOR_CONFIGURATION, 0x0000, nbytes, dataptr));
|
return ( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, conf, USB_DESCRIPTOR_CONFIGURATION, 0x0000, nbytes, dataptr));
|
||||||
}
|
}
|
||||||
//get string descriptor
|
//get string descriptor
|
||||||
inline uint8_t USB::getStrDescr( uint8_t addr, uint8_t ep, uint16_t nuint8_ts, uint8_t index, uint16_t langid, uint8_t* dataptr )
|
|
||||||
{
|
inline uint8_t USB::getStrDescr(uint8_t addr, uint8_t ep, uint16_t nuint8_ts, uint8_t index, uint16_t langid, uint8_t* dataptr) {
|
||||||
return ( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, index, USB_DESCRIPTOR_STRING, langid, nuint8_ts, dataptr));
|
return ( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, index, USB_DESCRIPTOR_STRING, langid, nuint8_ts, dataptr));
|
||||||
}
|
}
|
||||||
//set address
|
//set address
|
||||||
inline uint8_t USB::setAddr( uint8_t oldaddr, uint8_t ep, uint8_t newaddr )
|
|
||||||
{
|
inline uint8_t USB::setAddr(uint8_t oldaddr, uint8_t ep, uint8_t newaddr) {
|
||||||
return ( ctrlReq(oldaddr, ep, bmREQ_SET, USB_REQUEST_SET_ADDRESS, newaddr, 0x00, 0x0000, 0x0000, NULL));
|
return ( ctrlReq(oldaddr, ep, bmREQ_SET, USB_REQUEST_SET_ADDRESS, newaddr, 0x00, 0x0000, 0x0000, NULL));
|
||||||
}
|
}
|
||||||
//set configuration
|
//set configuration
|
||||||
inline uint8_t USB::setConf( uint8_t addr, uint8_t ep, uint8_t conf_value )
|
|
||||||
{
|
inline uint8_t USB::setConf(uint8_t addr, uint8_t ep, uint8_t conf_value) {
|
||||||
return ( ctrlReq(addr, ep, bmREQ_SET, USB_REQUEST_SET_CONFIGURATION, conf_value, 0x00, 0x0000, 0x0000, NULL));
|
return ( ctrlReq(addr, ep, bmREQ_SET, USB_REQUEST_SET_CONFIGURATION, conf_value, 0x00, 0x0000, 0x0000, NULL));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
114
address.h
114
address.h
|
@ -24,28 +24,25 @@ e-mail : support@circuitsathome.com
|
||||||
|
|
||||||
/* NAK powers. To save space in endpoint data structure, amount of retries before giving up and returning 0x4 is stored in */
|
/* NAK powers. To save space in endpoint data structure, amount of retries before giving up and returning 0x4 is stored in */
|
||||||
/* bmNakPower as a power of 2. The actual nak_limit is then calculated as nak_limit = ( 2^bmNakPower - 1) */
|
/* bmNakPower as a power of 2. The actual nak_limit is then calculated as nak_limit = ( 2^bmNakPower - 1) */
|
||||||
#define USB_NAK_MAX_POWER 16 //NAK binary order maximum value
|
#define USB_NAK_MAX_POWER 15 //NAK binary order maximum value
|
||||||
#define USB_NAK_DEFAULT 14 //default 16K-1 NAKs before giving up
|
#define USB_NAK_DEFAULT 14 //default 32K-1 NAKs before giving up
|
||||||
#define USB_NAK_NOWAIT 1 //Single NAK stops transfer
|
#define USB_NAK_NOWAIT 1 //Single NAK stops transfer
|
||||||
#define USB_NAK_NONAK 0 //Do not count NAKs, stop retrying after USB Timeout
|
#define USB_NAK_NONAK 0 //Do not count NAKs, stop retrying after USB Timeout
|
||||||
|
|
||||||
struct EpInfo
|
struct EpInfo {
|
||||||
{
|
|
||||||
uint8_t epAddr; // Endpoint address
|
uint8_t epAddr; // Endpoint address
|
||||||
uint8_t maxPktSize; // Maximum packet size
|
uint8_t maxPktSize; // Maximum packet size
|
||||||
|
|
||||||
union
|
union {
|
||||||
{
|
|
||||||
uint8_t epAttribs;
|
uint8_t epAttribs;
|
||||||
|
|
||||||
struct
|
struct {
|
||||||
{
|
|
||||||
uint8_t bmSndToggle : 1; // Send toggle, when zero bmSNDTOG0, bmSNDTOG1 otherwise
|
uint8_t bmSndToggle : 1; // Send toggle, when zero bmSNDTOG0, bmSNDTOG1 otherwise
|
||||||
uint8_t bmRcvToggle : 1; // Send toggle, when zero bmRCVTOG0, bmRCVTOG1 otherwise
|
uint8_t bmRcvToggle : 1; // Send toggle, when zero bmRCVTOG0, bmRCVTOG1 otherwise
|
||||||
uint8_t bmNakPower : 6; // Binary order for NAK_LIMIT value
|
uint8_t bmNakPower : 6; // Binary order for NAK_LIMIT value
|
||||||
|
}__attribute__((packed));
|
||||||
};
|
};
|
||||||
};
|
}__attribute__((packed));
|
||||||
};
|
|
||||||
|
|
||||||
// 7 6 5 4 3 2 1 0
|
// 7 6 5 4 3 2 1 0
|
||||||
// ---------------------------------
|
// ---------------------------------
|
||||||
|
@ -56,36 +53,34 @@ struct EpInfo
|
||||||
// P - parent hub address
|
// P - parent hub address
|
||||||
// A - device address / port number in case of hub
|
// A - device address / port number in case of hub
|
||||||
//
|
//
|
||||||
struct UsbDeviceAddress
|
|
||||||
{
|
struct UsbDeviceAddress {
|
||||||
union
|
|
||||||
{
|
union {
|
||||||
struct
|
|
||||||
{
|
struct {
|
||||||
uint8_t bmAddress : 3; // device address/port number
|
uint8_t bmAddress : 3; // device address/port number
|
||||||
uint8_t bmParent : 3; // parent hub address
|
uint8_t bmParent : 3; // parent hub address
|
||||||
uint8_t bmHub : 1; // hub flag
|
uint8_t bmHub : 1; // hub flag
|
||||||
uint8_t bmReserved : 1; // reserved, must be zerro
|
uint8_t bmReserved : 1; // reserved, must be zerro
|
||||||
};
|
}__attribute__((packed));
|
||||||
uint8_t devAddress;
|
uint8_t devAddress;
|
||||||
};
|
};
|
||||||
};
|
}__attribute__((packed));
|
||||||
|
|
||||||
#define bmUSB_DEV_ADDR_ADDRESS 0x07
|
#define bmUSB_DEV_ADDR_ADDRESS 0x07
|
||||||
#define bmUSB_DEV_ADDR_PARENT 0x38
|
#define bmUSB_DEV_ADDR_PARENT 0x38
|
||||||
#define bmUSB_DEV_ADDR_HUB 0x40
|
#define bmUSB_DEV_ADDR_HUB 0x40
|
||||||
|
|
||||||
struct UsbDevice
|
struct UsbDevice {
|
||||||
{
|
|
||||||
EpInfo *epinfo; // endpoint info pointer
|
EpInfo *epinfo; // endpoint info pointer
|
||||||
uint8_t address; // address
|
uint8_t address; // address
|
||||||
uint8_t epcount; // number of endpoints
|
uint8_t epcount; // number of endpoints
|
||||||
bool lowspeed; // indicates if a device is the low speed one
|
bool lowspeed; // indicates if a device is the low speed one
|
||||||
// uint8_t devclass; // device class
|
// uint8_t devclass; // device class
|
||||||
};
|
}__attribute__((packed));
|
||||||
|
|
||||||
class AddressPool
|
class AddressPool {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
virtual UsbDevice* GetUsbDevicePtr(uint8_t addr) = 0;
|
virtual UsbDevice* GetUsbDevicePtr(uint8_t addr) = 0;
|
||||||
virtual uint8_t AllocAddress(uint8_t parent, bool is_hub = false, uint8_t port = 0) = 0;
|
virtual uint8_t AllocAddress(uint8_t parent, bool is_hub = false, uint8_t port = 0) = 0;
|
||||||
|
@ -98,8 +93,7 @@ typedef void (*UsbDeviceHandleFunc)(UsbDevice *pdev);
|
||||||
#define ADDR_ERROR_INVALID_ADDRESS 0xFF
|
#define ADDR_ERROR_INVALID_ADDRESS 0xFF
|
||||||
|
|
||||||
template <const uint8_t MAX_DEVICES_ALLOWED>
|
template <const uint8_t MAX_DEVICES_ALLOWED>
|
||||||
class AddressPoolImpl : public AddressPool
|
class AddressPoolImpl : public AddressPool {
|
||||||
{
|
|
||||||
EpInfo dev0ep; //Endpoint data structure used during enumeration for uninitialized device
|
EpInfo dev0ep; //Endpoint data structure used during enumeration for uninitialized device
|
||||||
|
|
||||||
uint8_t hubCounter; // hub counter is kept
|
uint8_t hubCounter; // hub counter is kept
|
||||||
|
@ -108,44 +102,41 @@ class AddressPoolImpl : public AddressPool
|
||||||
UsbDevice thePool[MAX_DEVICES_ALLOWED];
|
UsbDevice thePool[MAX_DEVICES_ALLOWED];
|
||||||
|
|
||||||
// Initializes address pool entry
|
// Initializes address pool entry
|
||||||
void InitEntry(uint8_t index)
|
|
||||||
{
|
void InitEntry(uint8_t index) {
|
||||||
thePool[index].address = 0;
|
thePool[index].address = 0;
|
||||||
thePool[index].epcount = 1;
|
thePool[index].epcount = 1;
|
||||||
thePool[index].lowspeed = 0;
|
thePool[index].lowspeed = 0;
|
||||||
thePool[index].epinfo = &dev0ep;
|
thePool[index].epinfo = &dev0ep;
|
||||||
};
|
};
|
||||||
// Returns thePool index for a given address
|
// Returns thePool index for a given address
|
||||||
uint8_t FindAddressIndex(uint8_t address = 0)
|
|
||||||
{
|
uint8_t FindAddressIndex(uint8_t address = 0) {
|
||||||
for (uint8_t i=1; i<MAX_DEVICES_ALLOWED; i++)
|
for (uint8_t i = 1; i < MAX_DEVICES_ALLOWED; i++) {
|
||||||
{
|
|
||||||
if (thePool[i].address == address)
|
if (thePool[i].address == address)
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
// Returns thePool child index for a given parent
|
// Returns thePool child index for a given parent
|
||||||
uint8_t FindChildIndex(UsbDeviceAddress addr, uint8_t start = 1)
|
|
||||||
{
|
uint8_t FindChildIndex(UsbDeviceAddress addr, uint8_t start = 1) {
|
||||||
for (uint8_t i=(start<1 || start>=MAX_DEVICES_ALLOWED) ? 1 : start; i<MAX_DEVICES_ALLOWED; i++)
|
for (uint8_t i = (start < 1 || start >= MAX_DEVICES_ALLOWED) ? 1 : start; i < MAX_DEVICES_ALLOWED; i++) {
|
||||||
{
|
|
||||||
if (((UsbDeviceAddress*) & thePool[i].address)->bmParent == addr.bmAddress)
|
if (((UsbDeviceAddress*) & thePool[i].address)->bmParent == addr.bmAddress)
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
// Frees address entry specified by index parameter
|
// Frees address entry specified by index parameter
|
||||||
void FreeAddressByIndex(uint8_t index)
|
|
||||||
{
|
void FreeAddressByIndex(uint8_t index) {
|
||||||
// Zerro field is reserved and should not be affected
|
// Zerro field is reserved and should not be affected
|
||||||
if (index == 0)
|
if (index == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// If a hub was switched off all port addresses should be freed
|
// If a hub was switched off all port addresses should be freed
|
||||||
if (((UsbDeviceAddress*)&thePool[index].address)->bmHub == 1)
|
if (((UsbDeviceAddress*) & thePool[index].address)->bmHub == 1) {
|
||||||
{
|
for (uint8_t i = 1; (i = FindChildIndex(*((UsbDeviceAddress*) & thePool[index].address), i));)
|
||||||
for (uint8_t i=1; i = FindChildIndex(*((UsbDeviceAddress*)&thePool[index].address), i); )
|
|
||||||
FreeAddressByIndex(i);
|
FreeAddressByIndex(i);
|
||||||
|
|
||||||
// If the hub had the last allocated address, hubCounter should be decremented
|
// If the hub had the last allocated address, hubCounter should be decremented
|
||||||
|
@ -155,8 +146,8 @@ class AddressPoolImpl : public AddressPool
|
||||||
InitEntry(index);
|
InitEntry(index);
|
||||||
}
|
}
|
||||||
// Initializes the whole address pool at once
|
// Initializes the whole address pool at once
|
||||||
void InitAllAddresses()
|
|
||||||
{
|
void InitAllAddresses() {
|
||||||
for (uint8_t i = 1; i < MAX_DEVICES_ALLOWED; i++)
|
for (uint8_t i = 1; i < MAX_DEVICES_ALLOWED; i++)
|
||||||
InitEntry(i);
|
InitEntry(i);
|
||||||
|
|
||||||
|
@ -164,8 +155,8 @@ class AddressPoolImpl : public AddressPool
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
AddressPoolImpl() : hubCounter(0)
|
|
||||||
{
|
AddressPoolImpl() : hubCounter(0) {
|
||||||
// Zero address is reserved
|
// Zero address is reserved
|
||||||
InitEntry(0);
|
InitEntry(0);
|
||||||
|
|
||||||
|
@ -179,8 +170,8 @@ public:
|
||||||
InitAllAddresses();
|
InitAllAddresses();
|
||||||
};
|
};
|
||||||
// Returns a pointer to a specified address entry
|
// Returns a pointer to a specified address entry
|
||||||
virtual UsbDevice* GetUsbDevicePtr(uint8_t addr)
|
|
||||||
{
|
virtual UsbDevice* GetUsbDevicePtr(uint8_t addr) {
|
||||||
if (!addr)
|
if (!addr)
|
||||||
return thePool;
|
return thePool;
|
||||||
|
|
||||||
|
@ -190,8 +181,8 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
// Performs an operation specified by pfunc for each addressed device
|
// Performs an operation specified by pfunc for each addressed device
|
||||||
void ForEachUsbDevice(UsbDeviceHandleFunc pfunc)
|
|
||||||
{
|
void ForEachUsbDevice(UsbDeviceHandleFunc pfunc) {
|
||||||
if (!pfunc)
|
if (!pfunc)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -200,8 +191,8 @@ public:
|
||||||
pfunc(thePool + i);
|
pfunc(thePool + i);
|
||||||
};
|
};
|
||||||
// Allocates new address
|
// Allocates new address
|
||||||
virtual uint8_t AllocAddress(uint8_t parent, bool is_hub = false, uint8_t port = 0)
|
|
||||||
{
|
virtual uint8_t AllocAddress(uint8_t parent, bool is_hub = false, uint8_t port = 0) {
|
||||||
/* if (parent != 0 && port == 0)
|
/* if (parent != 0 && port == 0)
|
||||||
Serial.println("PRT:0"); */
|
Serial.println("PRT:0"); */
|
||||||
|
|
||||||
|
@ -217,14 +208,11 @@ public:
|
||||||
if (!index) // if empty entry is not found
|
if (!index) // if empty entry is not found
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (parent == 0)
|
if (parent == 0) {
|
||||||
{
|
if (is_hub) {
|
||||||
if (is_hub)
|
|
||||||
{
|
|
||||||
thePool[index].address = 0x41;
|
thePool[index].address = 0x41;
|
||||||
hubCounter++;
|
hubCounter++;
|
||||||
}
|
} else
|
||||||
else
|
|
||||||
thePool[index].address = 1;
|
thePool[index].address = 1;
|
||||||
|
|
||||||
return thePool[index].address;
|
return thePool[index].address;
|
||||||
|
@ -234,13 +222,10 @@ public:
|
||||||
|
|
||||||
addr.bmParent = ((UsbDeviceAddress*) & parent)->bmAddress;
|
addr.bmParent = ((UsbDeviceAddress*) & parent)->bmAddress;
|
||||||
|
|
||||||
if (is_hub)
|
if (is_hub) {
|
||||||
{
|
|
||||||
addr.bmHub = 1;
|
addr.bmHub = 1;
|
||||||
addr.bmAddress = ++hubCounter;
|
addr.bmAddress = ++hubCounter;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
addr.bmHub = 0;
|
addr.bmHub = 0;
|
||||||
addr.bmAddress = port;
|
addr.bmAddress = port;
|
||||||
}
|
}
|
||||||
|
@ -256,11 +241,10 @@ public:
|
||||||
return thePool[index].address;
|
return thePool[index].address;
|
||||||
};
|
};
|
||||||
// Empties pool entry
|
// Empties pool entry
|
||||||
virtual void FreeAddress(uint8_t addr)
|
|
||||||
{
|
virtual void FreeAddress(uint8_t addr) {
|
||||||
// if the root hub is disconnected all the addresses should be initialized
|
// if the root hub is disconnected all the addresses should be initialized
|
||||||
if (addr == 0x41)
|
if (addr == 0x41) {
|
||||||
{
|
|
||||||
InitAllAddresses();
|
InitAllAddresses();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
121
adk.cpp
121
adk.cpp
|
@ -18,7 +18,6 @@ e-mail : support@circuitsathome.com
|
||||||
/* Google ADK interface */
|
/* Google ADK interface */
|
||||||
|
|
||||||
#include "adk.h"
|
#include "adk.h"
|
||||||
#define DEBUG // Uncomment to print data for debugging
|
|
||||||
|
|
||||||
const uint8_t ADK::epDataInIndex = 1;
|
const uint8_t ADK::epDataInIndex = 1;
|
||||||
const uint8_t ADK::epDataOutIndex = 2;
|
const uint8_t ADK::epDataOutIndex = 2;
|
||||||
|
@ -30,11 +29,6 @@ ADK::ADK(USB *p, const char* manufacturer,
|
||||||
const char* uri,
|
const char* uri,
|
||||||
const char* serial) :
|
const char* serial) :
|
||||||
|
|
||||||
pUsb(p), //pointer to USB class instance - mandatory
|
|
||||||
bAddress(0), //device address - mandatory
|
|
||||||
bNumEP(1), //if config descriptor needs to be parsed
|
|
||||||
ready(false),
|
|
||||||
|
|
||||||
/* ADK ID Strings */
|
/* ADK ID Strings */
|
||||||
|
|
||||||
manufacturer(manufacturer),
|
manufacturer(manufacturer),
|
||||||
|
@ -42,17 +36,23 @@ ADK::ADK(USB *p, const char* manufacturer,
|
||||||
description(description),
|
description(description),
|
||||||
version(version),
|
version(version),
|
||||||
uri(uri),
|
uri(uri),
|
||||||
serial(serial)
|
serial(serial),
|
||||||
|
pUsb(p), //pointer to USB class instance - mandatory
|
||||||
|
bAddress(0), //device address - mandatory
|
||||||
|
bConfNum(0), //configuration number
|
||||||
|
bNumEP(1), //if config descriptor needs to be parsed
|
||||||
|
ready(false)
|
||||||
{
|
{
|
||||||
// initialize endpoint data structures
|
// initialize endpoint data structures
|
||||||
for (uint8_t i = 0; i < ADK_MAX_ENDPOINTS; i++) {
|
for (uint8_t i = 0; i < ADK_MAX_ENDPOINTS; i++) {
|
||||||
epInfo[i].epAddr = 0;
|
epInfo[i].epAddr = 0;
|
||||||
epInfo[i].maxPktSize = (i) ? 0 : 8;
|
epInfo[i].maxPktSize = (i) ? 0 : 8;
|
||||||
epInfo[i].epAttribs = 0;
|
epInfo[i].epAttribs = (0xfc & (USB_NAK_MAX_POWER << 2));
|
||||||
epInfo[i].bmNakPower = (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER;
|
|
||||||
}//for(uint8_t i=0; i<ADK_MAX_ENDPOINTS; i++...
|
}//for(uint8_t i=0; i<ADK_MAX_ENDPOINTS; i++...
|
||||||
|
|
||||||
|
//set bulk-IN EP naklimit to 1
|
||||||
|
epInfo[epDataInIndex].epAttribs = (0xfc & (USB_NAK_NOWAIT << 2));
|
||||||
|
|
||||||
// register in USB subsystem
|
// register in USB subsystem
|
||||||
if (pUsb) {
|
if (pUsb) {
|
||||||
pUsb->RegisterDeviceClass(this); //set devConfig[] entry
|
pUsb->RegisterDeviceClass(this); //set devConfig[] entry
|
||||||
|
@ -60,8 +60,7 @@ ADK::ADK(USB *p, const char* manufacturer,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Connection initialization of an Android phone */
|
/* Connection initialization of an Android phone */
|
||||||
uint8_t ADK::Init(uint8_t parent, uint8_t port, bool lowspeed)
|
uint8_t ADK::Init(uint8_t parent, uint8_t port, bool lowspeed) {
|
||||||
{
|
|
||||||
|
|
||||||
uint8_t buf[sizeof (USB_DEVICE_DESCRIPTOR)];
|
uint8_t buf[sizeof (USB_DEVICE_DESCRIPTOR)];
|
||||||
uint8_t rcode;
|
uint8_t rcode;
|
||||||
|
@ -71,14 +70,12 @@ uint8_t ADK::Init(uint8_t parent, uint8_t port, bool lowspeed)
|
||||||
|
|
||||||
// get memory address of USB device address pool
|
// get memory address of USB device address pool
|
||||||
AddressPool &addrPool = pUsb->GetAddressPool();
|
AddressPool &addrPool = pUsb->GetAddressPool();
|
||||||
#ifdef DEBUG
|
|
||||||
USBTRACE("\r\nADK Init");
|
USBTRACE("\r\nADK Init");
|
||||||
#endif
|
|
||||||
// check if address has already been assigned to an instance
|
// check if address has already been assigned to an instance
|
||||||
if (bAddress) {
|
if (bAddress) {
|
||||||
#ifdef DEBUG
|
|
||||||
USBTRACE("\r\nAddress in use");
|
USBTRACE("\r\nAddress in use");
|
||||||
#endif
|
|
||||||
return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE;
|
return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,16 +83,12 @@ uint8_t ADK::Init(uint8_t parent, uint8_t port, bool lowspeed)
|
||||||
p = addrPool.GetUsbDevicePtr(0);
|
p = addrPool.GetUsbDevicePtr(0);
|
||||||
|
|
||||||
if (!p) {
|
if (!p) {
|
||||||
#ifdef DEBUG
|
|
||||||
USBTRACE("\r\nAddress not found");
|
USBTRACE("\r\nAddress not found");
|
||||||
#endif
|
|
||||||
return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
|
return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!p->epinfo) {
|
if (!p->epinfo) {
|
||||||
#ifdef DEBUG
|
|
||||||
USBTRACE("epinfo is null\r\n");
|
USBTRACE("epinfo is null\r\n");
|
||||||
#endif
|
|
||||||
return USB_ERROR_EPINFO_IS_NULL;
|
return USB_ERROR_EPINFO_IS_NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -154,9 +147,7 @@ uint8_t ADK::Init(uint8_t parent, uint8_t port, bool lowspeed)
|
||||||
//check if ADK device is already in accessory mode; if yes, configure and exit
|
//check if ADK device is already in accessory mode; if yes, configure and exit
|
||||||
if (((USB_DEVICE_DESCRIPTOR*) buf)->idVendor == ADK_VID &&
|
if (((USB_DEVICE_DESCRIPTOR*) buf)->idVendor == ADK_VID &&
|
||||||
(((USB_DEVICE_DESCRIPTOR*) buf)->idProduct == ADK_PID || ((USB_DEVICE_DESCRIPTOR*) buf)->idProduct == ADB_PID)) {
|
(((USB_DEVICE_DESCRIPTOR*) buf)->idProduct == ADK_PID || ((USB_DEVICE_DESCRIPTOR*) buf)->idProduct == ADB_PID)) {
|
||||||
#ifdef DEBUG
|
|
||||||
USBTRACE("\r\nAcc.mode device detected");
|
USBTRACE("\r\nAcc.mode device detected");
|
||||||
#endif
|
|
||||||
/* go through configurations, find first bulk-IN, bulk-OUT EP, fill epInfo and quit */
|
/* go through configurations, find first bulk-IN, bulk-OUT EP, fill epInfo and quit */
|
||||||
num_of_conf = ((USB_DEVICE_DESCRIPTOR*) buf)->bNumConfigurations;
|
num_of_conf = ((USB_DEVICE_DESCRIPTOR*) buf)->bNumConfigurations;
|
||||||
|
|
||||||
|
@ -164,18 +155,7 @@ uint8_t ADK::Init(uint8_t parent, uint8_t port, bool lowspeed)
|
||||||
|
|
||||||
for (uint8_t i = 0; i < num_of_conf; i++) {
|
for (uint8_t i = 0; i < num_of_conf; i++) {
|
||||||
ConfigDescParser < 0, 0, 0, 0 > confDescrParser(this);
|
ConfigDescParser < 0, 0, 0, 0 > confDescrParser(this);
|
||||||
delay(1);
|
|
||||||
rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser);
|
rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser);
|
||||||
#if defined(XOOM)
|
|
||||||
//added by Jaylen Scott Vanorden
|
|
||||||
if( rcode ) {
|
|
||||||
#ifdef DEBUG
|
|
||||||
USBTRACE2("\r\nGot 1st bad code for config: ", rcode);
|
|
||||||
#endif
|
|
||||||
// Try once more
|
|
||||||
rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if (rcode) {
|
if (rcode) {
|
||||||
goto FailGetConfDescr;
|
goto FailGetConfDescr;
|
||||||
}
|
}
|
||||||
|
@ -213,9 +193,8 @@ uint8_t ADK::Init(uint8_t parent, uint8_t port, bool lowspeed)
|
||||||
// USBTRACE2("\r\nAddr: ", epInfo[epDataInIndex].epAddr );
|
// USBTRACE2("\r\nAddr: ", epInfo[epDataInIndex].epAddr );
|
||||||
// USBTRACE2("\r\nMax.pkt.size: ", epInfo[epDataInIndex].maxPktSize );
|
// USBTRACE2("\r\nMax.pkt.size: ", epInfo[epDataInIndex].maxPktSize );
|
||||||
// USBTRACE2("\r\nAttr: ", epInfo[epDataInIndex].epAttribs );
|
// USBTRACE2("\r\nAttr: ", epInfo[epDataInIndex].epAttribs );
|
||||||
#ifdef DEBUG
|
|
||||||
USBTRACE("\r\nConfiguration successful");
|
USBTRACE("\r\nConfiguration successful");
|
||||||
#endif
|
|
||||||
ready = true;
|
ready = true;
|
||||||
return 0; //successful configuration
|
return 0; //successful configuration
|
||||||
}//if( buf->idVendor == ADK_VID...
|
}//if( buf->idVendor == ADK_VID...
|
||||||
|
@ -223,24 +202,11 @@ uint8_t ADK::Init(uint8_t parent, uint8_t port, bool lowspeed)
|
||||||
//probe device - get accessory protocol revision
|
//probe device - get accessory protocol revision
|
||||||
{
|
{
|
||||||
uint16_t adkproto = -1;
|
uint16_t adkproto = -1;
|
||||||
delay(1);
|
|
||||||
rcode = getProto((uint8_t*) & adkproto);
|
rcode = getProto((uint8_t*) & adkproto);
|
||||||
#if defined(XOOM)
|
|
||||||
//added by Jaylen Scott Vanorden
|
|
||||||
if( rcode ) {
|
|
||||||
#ifdef DEBUG
|
|
||||||
USBTRACE2("\r\nGot 1st bad code for proto: ", rcode);
|
|
||||||
#endif
|
|
||||||
// Try once more
|
|
||||||
rcode = getProto((uint8_t*)&adkproto );
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if (rcode) {
|
if (rcode) {
|
||||||
goto FailGetProto; //init fails
|
goto FailGetProto; //init fails
|
||||||
}
|
}
|
||||||
#ifdef DEBUG
|
|
||||||
USBTRACE2("\r\nADK protocol rev. ", adkproto);
|
USBTRACE2("\r\nADK protocol rev. ", adkproto);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//sending ID strings
|
//sending ID strings
|
||||||
|
@ -262,33 +228,23 @@ uint8_t ADK::Init(uint8_t parent, uint8_t port, bool lowspeed)
|
||||||
|
|
||||||
/* diagnostic messages */
|
/* diagnostic messages */
|
||||||
FailGetDevDescr:
|
FailGetDevDescr:
|
||||||
#ifdef DEBUG
|
|
||||||
USBTRACE("\r\ngetDevDescr:");
|
USBTRACE("\r\ngetDevDescr:");
|
||||||
#endif
|
|
||||||
goto Fail;
|
goto Fail;
|
||||||
|
|
||||||
FailSetDevTblEntry:
|
FailSetDevTblEntry:
|
||||||
#ifdef DEBUG
|
|
||||||
USBTRACE("\r\nsetDevTblEn:");
|
USBTRACE("\r\nsetDevTblEn:");
|
||||||
#endif
|
|
||||||
goto Fail;
|
goto Fail;
|
||||||
|
|
||||||
FailGetProto:
|
FailGetProto:
|
||||||
#ifdef DEBUG
|
|
||||||
USBTRACE("\r\ngetProto:");
|
USBTRACE("\r\ngetProto:");
|
||||||
#endif
|
|
||||||
goto Fail;
|
goto Fail;
|
||||||
|
|
||||||
FailSwAcc:
|
FailSwAcc:
|
||||||
#ifdef DEBUG
|
|
||||||
USBTRACE("\r\nswAcc:");
|
USBTRACE("\r\nswAcc:");
|
||||||
#endif
|
|
||||||
goto Fail;
|
goto Fail;
|
||||||
|
|
||||||
SwAttempt:
|
SwAttempt:
|
||||||
#ifdef DEBUG
|
|
||||||
USBTRACE("\r\nAccessory mode switch attempt");
|
USBTRACE("\r\nAccessory mode switch attempt");
|
||||||
#endif
|
|
||||||
goto Fail;
|
goto Fail;
|
||||||
|
|
||||||
FailGetConfDescr:
|
FailGetConfDescr:
|
||||||
|
@ -310,8 +266,7 @@ Fail:
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Extracts bulk-IN and bulk-OUT endpoint information from config descriptor */
|
/* Extracts bulk-IN and bulk-OUT endpoint information from config descriptor */
|
||||||
void ADK::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *pep)
|
void ADK::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *pep) {
|
||||||
{
|
|
||||||
//ErrorMessage<uint8_t>(PSTR("Conf.Val"), conf);
|
//ErrorMessage<uint8_t>(PSTR("Conf.Val"), conf);
|
||||||
//ErrorMessage<uint8_t>(PSTR("Iface Num"),iface);
|
//ErrorMessage<uint8_t>(PSTR("Iface Num"),iface);
|
||||||
//ErrorMessage<uint8_t>(PSTR("Alt.Set"), alt);
|
//ErrorMessage<uint8_t>(PSTR("Alt.Set"), alt);
|
||||||
|
@ -325,9 +280,9 @@ void ADK::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto
|
||||||
|
|
||||||
uint8_t index;
|
uint8_t index;
|
||||||
|
|
||||||
if ((pep->bmAttributes & 0x02) == 2) {
|
// if ((pep->bmAttributes & 0x02) == 2) {
|
||||||
index = ((pep->bEndpointAddress & 0x80) == 0x80) ? epDataInIndex : epDataOutIndex;
|
index = ((pep->bEndpointAddress & 0x80) == 0x80) ? epDataInIndex : epDataOutIndex;
|
||||||
}
|
// }
|
||||||
|
|
||||||
// Fill in the endpoint info structure
|
// Fill in the endpoint info structure
|
||||||
epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F);
|
epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F);
|
||||||
|
@ -339,8 +294,7 @@ void ADK::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Performs a cleanup after failed Init() attempt */
|
/* Performs a cleanup after failed Init() attempt */
|
||||||
uint8_t ADK::Release()
|
uint8_t ADK::Release() {
|
||||||
{
|
|
||||||
pUsb->GetAddressPool().FreeAddress(bAddress);
|
pUsb->GetAddressPool().FreeAddress(bAddress);
|
||||||
|
|
||||||
bNumEP = 1; //must have to be reset to 1
|
bNumEP = 1; //must have to be reset to 1
|
||||||
|
@ -350,34 +304,29 @@ uint8_t ADK::Release()
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t ADK::RcvData(uint16_t *bytes_rcvd, uint8_t *dataptr)
|
uint8_t ADK::RcvData(uint16_t *bytes_rcvd, uint8_t *dataptr) {
|
||||||
{
|
|
||||||
//USBTRACE2("\r\nAddr: ", bAddress );
|
//USBTRACE2("\r\nAddr: ", bAddress );
|
||||||
//USBTRACE2("\r\nEP: ",epInfo[epDataInIndex].epAddr);
|
//USBTRACE2("\r\nEP: ",epInfo[epDataInIndex].epAddr);
|
||||||
return pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, bytes_rcvd, dataptr);
|
return pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, bytes_rcvd, dataptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t ADK::SndData(uint16_t nbytes, uint8_t *dataptr)
|
uint8_t ADK::SndData(uint16_t nbytes, uint8_t *dataptr) {
|
||||||
{
|
|
||||||
return pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, nbytes, dataptr);
|
return pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, nbytes, dataptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ADK::PrintEndpointDescriptor( const USB_ENDPOINT_DESCRIPTOR* ep_ptr )
|
void ADK::PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr) {
|
||||||
{
|
Notify(PSTR("Endpoint descriptor:"), 0x80);
|
||||||
#ifdef DEBUG
|
Notify(PSTR("\r\nLength:\t\t"), 0x80);
|
||||||
Notify(PSTR("Endpoint descriptor:"));
|
PrintHex<uint8_t > (ep_ptr->bLength, 0x80);
|
||||||
Notify(PSTR("\r\nLength:\t\t"));
|
Notify(PSTR("\r\nType:\t\t"), 0x80);
|
||||||
PrintHex<uint8_t>(ep_ptr->bLength);
|
PrintHex<uint8_t > (ep_ptr->bDescriptorType, 0x80);
|
||||||
Notify(PSTR("\r\nType:\t\t"));
|
Notify(PSTR("\r\nAddress:\t"), 0x80);
|
||||||
PrintHex<uint8_t>(ep_ptr->bDescriptorType);
|
PrintHex<uint8_t > (ep_ptr->bEndpointAddress, 0x80);
|
||||||
Notify(PSTR("\r\nAddress:\t"));
|
Notify(PSTR("\r\nAttributes:\t"), 0x80);
|
||||||
PrintHex<uint8_t>(ep_ptr->bEndpointAddress);
|
PrintHex<uint8_t > (ep_ptr->bmAttributes, 0x80);
|
||||||
Notify(PSTR("\r\nAttributes:\t"));
|
Notify(PSTR("\r\nMaxPktSize:\t"), 0x80);
|
||||||
PrintHex<uint8_t>(ep_ptr->bmAttributes);
|
PrintHex<uint16_t > (ep_ptr->wMaxPacketSize, 0x80);
|
||||||
Notify(PSTR("\r\nMaxPktSize:\t"));
|
Notify(PSTR("\r\nPoll Intrv:\t"), 0x80);
|
||||||
PrintHex<uint16_t>(ep_ptr->wMaxPacketSize);
|
PrintHex<uint8_t > (ep_ptr->bInterval, 0x80);
|
||||||
Notify(PSTR("\r\nPoll Intrv:\t"));
|
Notify(PSTR("\r\n"), 0x80);
|
||||||
PrintHex<uint8_t>(ep_ptr->bInterval);
|
|
||||||
Notify(PSTR("\r\n"));
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
34
adk.h
34
adk.h
|
@ -44,10 +44,6 @@ e-mail : support@circuitsathome.com
|
||||||
#define ADK_PID 0x2D00
|
#define ADK_PID 0x2D00
|
||||||
#define ADB_PID 0x2D01
|
#define ADB_PID 0x2D01
|
||||||
|
|
||||||
#define XOOM //enables repeating getProto() and getConf() attempts
|
|
||||||
//necessary for slow devices such as Motorola XOOM
|
|
||||||
//defined by default, can be commented out to save memory
|
|
||||||
|
|
||||||
/* requests */
|
/* requests */
|
||||||
|
|
||||||
#define ADK_GETPROTO 51 //check USB accessory protocol version
|
#define ADK_GETPROTO 51 //check USB accessory protocol version
|
||||||
|
@ -68,8 +64,7 @@ e-mail : support@circuitsathome.com
|
||||||
|
|
||||||
class ADK;
|
class ADK;
|
||||||
|
|
||||||
class ADK : public USBDeviceConfig, public UsbConfigXtracter
|
class ADK : public USBDeviceConfig, public UsbConfigXtracter {
|
||||||
{
|
|
||||||
private:
|
private:
|
||||||
/* ID strings */
|
/* ID strings */
|
||||||
const char* manufacturer;
|
const char* manufacturer;
|
||||||
|
@ -117,28 +112,37 @@ public:
|
||||||
// USBDeviceConfig implementation
|
// USBDeviceConfig implementation
|
||||||
virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed);
|
virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed);
|
||||||
virtual uint8_t Release();
|
virtual uint8_t Release();
|
||||||
virtual uint8_t Poll(){}; //not implemented
|
|
||||||
virtual uint8_t GetAddress() { return bAddress; };
|
virtual uint8_t Poll() {
|
||||||
virtual bool isReady() { return ready; };
|
return 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
virtual uint8_t GetAddress() {
|
||||||
|
return bAddress;
|
||||||
|
};
|
||||||
|
|
||||||
|
virtual bool isReady() {
|
||||||
|
return ready;
|
||||||
|
};
|
||||||
|
|
||||||
//UsbConfigXtracter implementation
|
//UsbConfigXtracter implementation
|
||||||
virtual void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep);
|
virtual void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep);
|
||||||
}; //class ADK : public USBDeviceConfig ...
|
}; //class ADK : public USBDeviceConfig ...
|
||||||
|
|
||||||
/* get ADK protocol version */
|
/* get ADK protocol version */
|
||||||
|
|
||||||
/* returns 2 bytes in *adkproto */
|
/* returns 2 bytes in *adkproto */
|
||||||
inline uint8_t ADK::getProto( uint8_t* adkproto )
|
inline uint8_t ADK::getProto(uint8_t* adkproto) {
|
||||||
{
|
|
||||||
return ( pUsb->ctrlReq(bAddress, 0, bmREQ_ADK_GET, ADK_GETPROTO, 0, 0, 0, 2, 2, adkproto, NULL));
|
return ( pUsb->ctrlReq(bAddress, 0, bmREQ_ADK_GET, ADK_GETPROTO, 0, 0, 0, 2, 2, adkproto, NULL));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* send ADK string */
|
/* send ADK string */
|
||||||
inline uint8_t ADK::sendStr( uint8_t index, const char* str )
|
inline uint8_t ADK::sendStr(uint8_t index, const char* str) {
|
||||||
{
|
|
||||||
return ( pUsb->ctrlReq(bAddress, 0, bmREQ_ADK_SEND, ADK_SENDSTR, 0, 0, index, strlen(str) + 1, strlen(str) + 1, (uint8_t*) str, NULL));
|
return ( pUsb->ctrlReq(bAddress, 0, bmREQ_ADK_SEND, ADK_SENDSTR, 0, 0, index, strlen(str) + 1, strlen(str) + 1, (uint8_t*) str, NULL));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* switch to accessory mode */
|
/* switch to accessory mode */
|
||||||
inline uint8_t ADK::switchAcc( void )
|
inline uint8_t ADK::switchAcc(void) {
|
||||||
{
|
|
||||||
return ( pUsb->ctrlReq(bAddress, 0, bmREQ_ADK_SEND, ADK_ACCSTART, 0, 0, 0, 0, 0, NULL, NULL));
|
return ( pUsb->ctrlReq(bAddress, 0, bmREQ_ADK_SEND, ADK_ACCSTART, 0, 0, 0, 0, 0, NULL, NULL));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
170
avrpins.h
170
avrpins.h
|
@ -20,17 +20,6 @@ e-mail : support@circuitsathome.com
|
||||||
#ifndef _avrpins_h_
|
#ifndef _avrpins_h_
|
||||||
#define _avrpins_h_
|
#define _avrpins_h_
|
||||||
|
|
||||||
#if defined(__AVR_ATmega1280__) || (__AVR_ATmega2560__)
|
|
||||||
/* Uncomment the following if you have Arduino Mega ADK board with MAX3421e built-in */
|
|
||||||
//#define BOARD_MEGA_ADK
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Uncomment the following if you are using a Teensy 2.0 */
|
|
||||||
//#define BOARD_TEENSY
|
|
||||||
|
|
||||||
/* Uncomment the following if you are using a Sanguino */
|
|
||||||
//#define BOARD_SANGUINO
|
|
||||||
|
|
||||||
#include <avr/io.h>
|
#include <avr/io.h>
|
||||||
|
|
||||||
#ifdef PORTA
|
#ifdef PORTA
|
||||||
|
@ -122,6 +111,7 @@ e-mail : support@circuitsathome.com
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef USE_PORTA
|
#ifdef USE_PORTA
|
||||||
|
|
||||||
MAKE_PORT(PORTA, DDRA, PINA, Porta, 'A')
|
MAKE_PORT(PORTA, DDRA, PINA, Porta, 'A')
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_PORTB
|
#ifdef USE_PORTB
|
||||||
|
@ -174,56 +164,87 @@ MAKE_TCCR(TCCR2A, Tccr2a)
|
||||||
// this class represents one pin in a IO port.
|
// this class represents one pin in a IO port.
|
||||||
// It is fully static.
|
// It is fully static.
|
||||||
template<typename PORT, uint8_t PIN>
|
template<typename PORT, uint8_t PIN>
|
||||||
class TPin
|
class TPin {
|
||||||
{
|
|
||||||
// BOOST_STATIC_ASSERT(PIN < PORT::Width);
|
// BOOST_STATIC_ASSERT(PIN < PORT::Width);
|
||||||
public:
|
public:
|
||||||
typedef PORT Port;
|
typedef PORT Port;
|
||||||
enum{Number = PIN};
|
|
||||||
|
|
||||||
static void Set() { PORT::Set(1 << PIN); }
|
enum {
|
||||||
|
Number = PIN
|
||||||
|
};
|
||||||
|
|
||||||
|
static void Set() {
|
||||||
|
PORT::Set(1 << PIN);
|
||||||
|
}
|
||||||
|
|
||||||
static void Set(uint8_t val) {
|
static void Set(uint8_t val) {
|
||||||
if (val)
|
if (val)
|
||||||
Set();
|
Set();
|
||||||
else Clear();}
|
else Clear();
|
||||||
|
}
|
||||||
|
|
||||||
static void SetDir(uint8_t val) {
|
static void SetDir(uint8_t val) {
|
||||||
if (val)
|
if (val)
|
||||||
SetDirWrite();
|
SetDirWrite();
|
||||||
else SetDirRead();}
|
else SetDirRead();
|
||||||
|
}
|
||||||
|
|
||||||
static void Clear(){PORT::Clear(1 << PIN);}
|
static void Clear() {
|
||||||
|
PORT::Clear(1 << PIN);
|
||||||
|
}
|
||||||
|
|
||||||
static void Toggle(){PORT::Toggle(1 << PIN);}
|
static void Toggle() {
|
||||||
|
PORT::Toggle(1 << PIN);
|
||||||
|
}
|
||||||
|
|
||||||
static void SetDirRead(){PORT::DirClear(1 << PIN);}
|
static void SetDirRead() {
|
||||||
|
PORT::DirClear(1 << PIN);
|
||||||
|
}
|
||||||
|
|
||||||
static void SetDirWrite(){PORT::DirSet(1 << PIN);}
|
static void SetDirWrite() {
|
||||||
|
PORT::DirSet(1 << PIN);
|
||||||
|
}
|
||||||
|
|
||||||
static uint8_t IsSet(){return PORT::PinRead() & (uint8_t)(1 << PIN);}
|
static uint8_t IsSet() {
|
||||||
|
return PORT::PinRead() & (uint8_t) (1 << PIN);
|
||||||
|
}
|
||||||
|
|
||||||
static void WaiteForSet(){ while(IsSet()==0){} }
|
static void WaiteForSet() {
|
||||||
|
while (IsSet() == 0) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void WaiteForClear(){ while(IsSet()){} }
|
static void WaiteForClear() {
|
||||||
|
while (IsSet()) {
|
||||||
|
}
|
||||||
|
}
|
||||||
}; //class TPin...
|
}; //class TPin...
|
||||||
|
|
||||||
// this class represents one bit in TCCR port.
|
// this class represents one bit in TCCR port.
|
||||||
// used to set/clear TCCRx bits
|
// used to set/clear TCCRx bits
|
||||||
// It is fully static.
|
// It is fully static.
|
||||||
|
|
||||||
template<typename TCCR, uint8_t COM>
|
template<typename TCCR, uint8_t COM>
|
||||||
class TCom
|
class TCom {
|
||||||
{
|
|
||||||
// BOOST_STATIC_ASSERT(PIN < PORT::Width);
|
// BOOST_STATIC_ASSERT(PIN < PORT::Width);
|
||||||
public:
|
public:
|
||||||
typedef TCCR Tccr;
|
typedef TCCR Tccr;
|
||||||
enum{Com = COM};
|
|
||||||
|
|
||||||
static void Set() { TCCR::Set(1 << COM); }
|
enum {
|
||||||
|
Com = COM
|
||||||
|
};
|
||||||
|
|
||||||
static void Clear() { TCCR::Clear(1 << COM); }
|
static void Set() {
|
||||||
|
TCCR::Set(1 << COM);
|
||||||
|
}
|
||||||
|
|
||||||
static void Toggle() { TCCR::Toggle(1 << COM); }
|
static void Clear() {
|
||||||
|
TCCR::Clear(1 << COM);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Toggle() {
|
||||||
|
TCCR::Toggle(1 << COM);
|
||||||
|
}
|
||||||
}; //class TCom...
|
}; //class TCom...
|
||||||
|
|
||||||
//Short pin definitions
|
//Short pin definitions
|
||||||
|
@ -386,18 +407,20 @@ typedef TCom<Tccr2a, COM2B1> Tc2b; //P3
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
template<typename Tp_pin, typename Tc_bit>
|
template<typename Tp_pin, typename Tc_bit>
|
||||||
class Tp_Tc
|
class Tp_Tc {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
static void SetDir(uint8_t val) {
|
static void SetDir(uint8_t val) {
|
||||||
if (val)
|
if (val)
|
||||||
SetDirWrite();
|
SetDirWrite();
|
||||||
else SetDirRead();
|
else SetDirRead();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SetDirRead() {
|
static void SetDirRead() {
|
||||||
Tp_pin::SetDirRead(); //set pin direction
|
Tp_pin::SetDirRead(); //set pin direction
|
||||||
Tc_bit::Clear(); //disconnect pin from PWM
|
Tc_bit::Clear(); //disconnect pin from PWM
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SetDirWrite() {
|
static void SetDirWrite() {
|
||||||
Tp_pin::SetDirWrite();
|
Tp_pin::SetDirWrite();
|
||||||
Tc_bit::Clear();
|
Tc_bit::Clear();
|
||||||
|
@ -476,7 +499,6 @@ template<typename Tp_pin, typename Tc_bit>
|
||||||
#define P51 Pb2
|
#define P51 Pb2
|
||||||
#define P52 Pb1
|
#define P52 Pb1
|
||||||
#define P53 Pb0
|
#define P53 Pb0
|
||||||
#define P54 Pe6 // INT on Arduino ADK
|
|
||||||
|
|
||||||
#endif //"Mega" pin numbers
|
#endif //"Mega" pin numbers
|
||||||
|
|
||||||
|
@ -508,47 +530,7 @@ template<typename Tp_pin, typename Tc_bit>
|
||||||
|
|
||||||
#endif // "Classic" Arduino pin numbers
|
#endif // "Classic" Arduino pin numbers
|
||||||
|
|
||||||
#if !defined(BOARD_TEENSY) && defined(__AVR_ATmega32U4__)
|
#if defined(__AVR_ATmega32U4__)
|
||||||
// Arduino Leonardo pin numbers
|
|
||||||
|
|
||||||
#define P0 Pd2 // D0 - PD2
|
|
||||||
#define P1 Pd3 // D1 - PD3
|
|
||||||
#define P2 Pd1 // D2 - PD1
|
|
||||||
#define P3 Pd0 // D3 - PD0
|
|
||||||
#define P4 Pd4 // D4 - PD4
|
|
||||||
#define P5 Pc6 // D5 - PC6
|
|
||||||
#define P6 Pd7 // D6 - PD7
|
|
||||||
#define P7 Pe6 // D7 - PE6
|
|
||||||
|
|
||||||
#define P8 Pb4 // D8 - PB4
|
|
||||||
#define P9 Pb5 // D9 - PB5
|
|
||||||
#define P10 Pb6 // D10 - PB6
|
|
||||||
#define P11 Pb7 // D11 - PB7
|
|
||||||
#define P12 Pd6 // D12 - PD6
|
|
||||||
#define P13 Pc7 // D13 - PC7
|
|
||||||
|
|
||||||
#define P14 Pb3 // D14 - MISO - PB3
|
|
||||||
#define P15 Pb1 // D15 - SCK - PB1
|
|
||||||
#define P16 Pb2 // D16 - MOSI - PB2
|
|
||||||
#define P17 Pb0 // D17 - SS - PB0
|
|
||||||
|
|
||||||
#define P18 Pf7 // D18 - A0 - PF7
|
|
||||||
#define P19 Pf6 // D19 - A1 - PF6
|
|
||||||
#define P20 Pf5 // D20 - A2 - PF5
|
|
||||||
#define P21 Pf4 // D21 - A3 - PF4
|
|
||||||
#define P22 Pf1 // D22 - A4 - PF1
|
|
||||||
#define P23 Pf0 // D23 - A5 - PF0
|
|
||||||
|
|
||||||
#define P24 Pd4 // D24 / D4 - A6 - PD4
|
|
||||||
#define P25 Pd7 // D25 / D6 - A7 - PD7
|
|
||||||
#define P26 Pb4 // D26 / D8 - A8 - PB4
|
|
||||||
#define P27 Pb5 // D27 / D9 - A9 - PB5
|
|
||||||
#define P28 Pb6 // D28 / D10 - A10 - PB6
|
|
||||||
#define P29 Pd6 // D29 / D12 - A11 - PD6
|
|
||||||
|
|
||||||
#endif // Arduino Leonardo pin numbers
|
|
||||||
|
|
||||||
#if defined(BOARD_TEENSY) && defined(__AVR_ATmega32U4__)
|
|
||||||
// Teensy 2.0 pin numbers
|
// Teensy 2.0 pin numbers
|
||||||
// http://www.pjrc.com/teensy/pinout.html
|
// http://www.pjrc.com/teensy/pinout.html
|
||||||
#define P0 Pb0
|
#define P0 Pb0
|
||||||
|
@ -629,45 +611,7 @@ template<typename Tp_pin, typename Tc_bit>
|
||||||
#define P45 Pf7
|
#define P45 Pf7
|
||||||
#endif // Teensy++ 2.0
|
#endif // Teensy++ 2.0
|
||||||
|
|
||||||
#if !defined(BOARD_SANGUINO) && (defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__))
|
#if defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__)
|
||||||
#define BOARD_BALANDUINO
|
|
||||||
// Balanduino pin numbers
|
|
||||||
// http://balanduino.net/
|
|
||||||
#define P0 Pd0 /* 0 - PD0 */
|
|
||||||
#define P1 Pd1 /* 1 - PD1 */
|
|
||||||
#define P2 Pb2 /* 2 - PB2 */
|
|
||||||
#define P3 Pd6 /* 3 - PD6 */
|
|
||||||
#define P4 Pd7 /* 4 - PD7 */
|
|
||||||
#define P5 Pb3 /* 5 - PB3 */
|
|
||||||
#define P6 Pb4 /* 6 - PB4 */
|
|
||||||
#define P7 Pa0 /* 7 - PA0 */
|
|
||||||
#define P8 Pa1 /* 8 - PA1 */
|
|
||||||
#define P9 Pa2 /* 9 - PA2 */
|
|
||||||
#define P10 Pa3 /* 10 - PA3 */
|
|
||||||
#define P11 Pa4 /* 11 - PA4 */
|
|
||||||
#define P12 Pa5 /* 12 - PA5 */
|
|
||||||
#define P13 Pc0 /* 13 - PC0 */
|
|
||||||
#define P14 Pc1 /* 14 - PC1 */
|
|
||||||
#define P15 Pd2 /* 15 - PD2 */
|
|
||||||
#define P16 Pd3 /* 16 - PD3 */
|
|
||||||
#define P17 Pd4 /* 17 - PD4 */
|
|
||||||
#define P18 Pd5 /* 18 - PD5 */
|
|
||||||
#define P19 Pc2 /* 19 - PC2 */
|
|
||||||
#define P20 Pc3 /* 20 - PC3 */
|
|
||||||
#define P21 Pc4 /* 21 - PC4 */
|
|
||||||
#define P22 Pc5 /* 22 - PC5 */
|
|
||||||
#define P23 Pc6 /* 23 - PC6 */
|
|
||||||
#define P24 Pc7 /* 24 - PC7 */
|
|
||||||
#define P25 Pb0 /* 25 - PB0 */
|
|
||||||
#define P26 Pb1 /* 26 - PB1 */
|
|
||||||
#define P27 Pb5 /* 27 - PB5 */
|
|
||||||
#define P28 Pb6 /* 28 - PB6 */
|
|
||||||
#define P29 Pb7 /* 29 - PB7 */
|
|
||||||
#define P30 Pa6 /* 30 - PA6 */
|
|
||||||
#define P31 Pa7 /* 31 - PA7 */
|
|
||||||
#endif // Balanduino
|
|
||||||
|
|
||||||
#if defined(BOARD_SANGUINO) && (defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__))
|
|
||||||
// Sanguino pin numbers
|
// Sanguino pin numbers
|
||||||
// http://sanguino.cc/hardware
|
// http://sanguino.cc/hardware
|
||||||
#define P0 Pb0
|
#define P0 Pb0
|
||||||
|
|
126
cdcacm.cpp
126
cdcacm.cpp
|
@ -24,31 +24,26 @@ ACM::ACM(USB *p, CDCAsyncOper *pasync) :
|
||||||
pUsb(p),
|
pUsb(p),
|
||||||
pAsync(pasync),
|
pAsync(pasync),
|
||||||
bAddress(0),
|
bAddress(0),
|
||||||
qNextPollTime(0),
|
|
||||||
bPollEnable(false),
|
|
||||||
bControlIface(0),
|
bControlIface(0),
|
||||||
bDataIface(0),
|
bDataIface(0),
|
||||||
bNumEP(1),
|
bNumEP(1),
|
||||||
ready(false)
|
qNextPollTime(0),
|
||||||
{
|
bPollEnable(false) {
|
||||||
for(uint8_t i=0; i<ACM_MAX_ENDPOINTS; i++)
|
for (uint8_t i = 0; i < ACM_MAX_ENDPOINTS; i++) {
|
||||||
{
|
|
||||||
epInfo[i].epAddr = 0;
|
epInfo[i].epAddr = 0;
|
||||||
epInfo[i].maxPktSize = (i) ? 0 : 8;
|
epInfo[i].maxPktSize = (i) ? 0 : 8;
|
||||||
epInfo[i].epAttribs = 0;
|
epInfo[i].epAttribs = 0;
|
||||||
epInfo[i].bmNakPower = USB_NAK_NOWAIT;
|
//epInfo[i].bmNakPower = USB_NAK_NOWAIT;
|
||||||
//epInfo[i].bmNakPower = USB_NAK_MAX_POWER;
|
|
||||||
|
|
||||||
if (!i)
|
|
||||||
epInfo[i].bmNakPower = USB_NAK_MAX_POWER;
|
epInfo[i].bmNakPower = USB_NAK_MAX_POWER;
|
||||||
|
|
||||||
|
//if (!i)
|
||||||
|
epInfo[i].bmNakPower = USB_NAK_MAX_POWER;
|
||||||
}
|
}
|
||||||
if (pUsb)
|
if (pUsb)
|
||||||
pUsb->RegisterDeviceClass(this);
|
pUsb->RegisterDeviceClass(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t ACM::Init(uint8_t parent, uint8_t port, bool lowspeed)
|
uint8_t ACM::Init(uint8_t parent, uint8_t port, bool lowspeed) {
|
||||||
{
|
|
||||||
const uint8_t constBufSize = sizeof (USB_DEVICE_DESCRIPTOR);
|
const uint8_t constBufSize = sizeof (USB_DEVICE_DESCRIPTOR);
|
||||||
|
|
||||||
uint8_t buf[constBufSize];
|
uint8_t buf[constBufSize];
|
||||||
|
@ -70,8 +65,7 @@ uint8_t ACM::Init(uint8_t parent, uint8_t port, bool lowspeed)
|
||||||
if (!p)
|
if (!p)
|
||||||
return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
|
return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
|
||||||
|
|
||||||
if (!p->epinfo)
|
if (!p->epinfo) {
|
||||||
{
|
|
||||||
USBTRACE("epinfo\r\n");
|
USBTRACE("epinfo\r\n");
|
||||||
return USB_ERROR_EPINFO_IS_NULL;
|
return USB_ERROR_EPINFO_IS_NULL;
|
||||||
}
|
}
|
||||||
|
@ -105,8 +99,7 @@ uint8_t ACM::Init(uint8_t parent, uint8_t port, bool lowspeed)
|
||||||
// Assign new address to the device
|
// Assign new address to the device
|
||||||
rcode = pUsb->setAddr(0, 0, bAddress);
|
rcode = pUsb->setAddr(0, 0, bAddress);
|
||||||
|
|
||||||
if (rcode)
|
if (rcode) {
|
||||||
{
|
|
||||||
p->lowspeed = false;
|
p->lowspeed = false;
|
||||||
addrPool.FreeAddress(bAddress);
|
addrPool.FreeAddress(bAddress);
|
||||||
bAddress = 0;
|
bAddress = 0;
|
||||||
|
@ -135,8 +128,7 @@ uint8_t ACM::Init(uint8_t parent, uint8_t port, bool lowspeed)
|
||||||
|
|
||||||
USBTRACE2("NC:", num_of_conf);
|
USBTRACE2("NC:", num_of_conf);
|
||||||
|
|
||||||
for (uint8_t i=0; i<num_of_conf; i++)
|
for (uint8_t i = 0; i < num_of_conf; i++) {
|
||||||
{
|
|
||||||
ConfigDescParser< USB_CLASS_COM_AND_CDC_CTRL,
|
ConfigDescParser< USB_CLASS_COM_AND_CDC_CTRL,
|
||||||
CDC_SUBCLASS_ACM,
|
CDC_SUBCLASS_ACM,
|
||||||
CDC_PROTOCOL_ITU_T_V_250,
|
CDC_PROTOCOL_ITU_T_V_250,
|
||||||
|
@ -148,8 +140,15 @@ uint8_t ACM::Init(uint8_t parent, uint8_t port, bool lowspeed)
|
||||||
CP_MASK_COMPARE_CLASS> CdcDataParser(this);
|
CP_MASK_COMPARE_CLASS> CdcDataParser(this);
|
||||||
|
|
||||||
rcode = pUsb->getConfDescr(bAddress, 0, i, &CdcControlParser);
|
rcode = pUsb->getConfDescr(bAddress, 0, i, &CdcControlParser);
|
||||||
|
|
||||||
|
if (rcode)
|
||||||
|
goto FailGetConfDescr;
|
||||||
|
|
||||||
rcode = pUsb->getConfDescr(bAddress, 0, i, &CdcDataParser);
|
rcode = pUsb->getConfDescr(bAddress, 0, i, &CdcDataParser);
|
||||||
|
|
||||||
|
if (rcode)
|
||||||
|
goto FailGetConfDescr;
|
||||||
|
|
||||||
if (bNumEP > 1)
|
if (bNumEP > 1)
|
||||||
break;
|
break;
|
||||||
} // for
|
} // for
|
||||||
|
@ -174,7 +173,6 @@ uint8_t ACM::Init(uint8_t parent, uint8_t port, bool lowspeed)
|
||||||
goto FailOnInit;
|
goto FailOnInit;
|
||||||
|
|
||||||
USBTRACE("ACM configured\r\n");
|
USBTRACE("ACM configured\r\n");
|
||||||
ready = true;
|
|
||||||
|
|
||||||
//bPollEnable = true;
|
//bPollEnable = true;
|
||||||
|
|
||||||
|
@ -202,17 +200,17 @@ FailOnInit:
|
||||||
goto Fail;
|
goto Fail;
|
||||||
|
|
||||||
Fail:
|
Fail:
|
||||||
Serial.println(rcode, HEX);
|
PrintHex<uint8_t > (rcode, 0x80);
|
||||||
|
Notify(PSTR("\r\n"), 0x80);
|
||||||
|
// Serial.println(rcode, HEX);
|
||||||
Release();
|
Release();
|
||||||
return rcode;
|
return rcode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ACM::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *pep) {
|
||||||
void ACM::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *pep)
|
ErrorMessage<uint8_t > (PSTR("Conf.Val"), conf);
|
||||||
{
|
ErrorMessage<uint8_t > (PSTR("Iface Num"), iface);
|
||||||
//ErrorMessage<uint8_t>(PSTR("Conf.Val"), conf);
|
ErrorMessage<uint8_t > (PSTR("Alt.Set"), alt);
|
||||||
//ErrorMessage<uint8_t>(PSTR("Iface Num"),iface);
|
|
||||||
//ErrorMessage<uint8_t>(PSTR("Alt.Set"), alt);
|
|
||||||
|
|
||||||
bConfNum = conf;
|
bConfNum = conf;
|
||||||
|
|
||||||
|
@ -229,15 +227,14 @@ void ACM::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto
|
||||||
// Fill in the endpoint info structure
|
// Fill in the endpoint info structure
|
||||||
epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F);
|
epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F);
|
||||||
epInfo[index].maxPktSize = (uint8_t) pep->wMaxPacketSize;
|
epInfo[index].maxPktSize = (uint8_t) pep->wMaxPacketSize;
|
||||||
//epInfo[index].epAttribs = 0;
|
epInfo[index].epAttribs = 0;
|
||||||
|
|
||||||
bNumEP++;
|
bNumEP++;
|
||||||
|
|
||||||
//PrintEndpointDescriptor(pep);
|
PrintEndpointDescriptor(pep);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t ACM::Release()
|
uint8_t ACM::Release() {
|
||||||
{
|
|
||||||
pUsb->GetAddressPool().FreeAddress(bAddress);
|
pUsb->GetAddressPool().FreeAddress(bAddress);
|
||||||
|
|
||||||
bControlIface = 0;
|
bControlIface = 0;
|
||||||
|
@ -247,12 +244,10 @@ uint8_t ACM::Release()
|
||||||
bAddress = 0;
|
bAddress = 0;
|
||||||
qNextPollTime = 0;
|
qNextPollTime = 0;
|
||||||
bPollEnable = false;
|
bPollEnable = false;
|
||||||
ready = false;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t ACM::Poll()
|
uint8_t ACM::Poll() {
|
||||||
{
|
|
||||||
uint8_t rcode = 0;
|
uint8_t rcode = 0;
|
||||||
|
|
||||||
if (!bPollEnable)
|
if (!bPollEnable)
|
||||||
|
@ -288,72 +283,55 @@ uint8_t ACM::Poll()
|
||||||
return rcode;
|
return rcode;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t ACM::RcvData(uint16_t *bytes_rcvd, uint8_t *dataptr)
|
uint8_t ACM::RcvData(uint16_t *bytes_rcvd, uint8_t *dataptr) {
|
||||||
{
|
|
||||||
return pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, bytes_rcvd, dataptr);
|
return pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, bytes_rcvd, dataptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t ACM::SndData(uint16_t nbytes, uint8_t *dataptr)
|
uint8_t ACM::SndData(uint16_t nbytes, uint8_t *dataptr) {
|
||||||
{
|
|
||||||
return pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, nbytes, dataptr);
|
return pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, nbytes, dataptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* untested */
|
uint8_t ACM::SetCommFeature(uint16_t fid, uint8_t nbytes, uint8_t *dataptr) {
|
||||||
uint8_t ACM::GetNotif( uint16_t *bytes_rcvd, uint8_t *dataptr )
|
|
||||||
{
|
|
||||||
return pUsb->inTransfer(bAddress, epInfo[epInterruptInIndex].epAddr, bytes_rcvd, dataptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t ACM::SetCommFeature(uint16_t fid, uint8_t nbytes, uint8_t *dataptr)
|
|
||||||
{
|
|
||||||
return ( pUsb->ctrlReq(bAddress, 0, bmREQ_CDCOUT, CDC_SET_COMM_FEATURE, (fid & 0xff), (fid >> 8), bControlIface, nbytes, nbytes, dataptr, NULL));
|
return ( pUsb->ctrlReq(bAddress, 0, bmREQ_CDCOUT, CDC_SET_COMM_FEATURE, (fid & 0xff), (fid >> 8), bControlIface, nbytes, nbytes, dataptr, NULL));
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t ACM::GetCommFeature(uint16_t fid, uint8_t nbytes, uint8_t *dataptr)
|
uint8_t ACM::GetCommFeature(uint16_t fid, uint8_t nbytes, uint8_t *dataptr) {
|
||||||
{
|
|
||||||
return ( pUsb->ctrlReq(bAddress, 0, bmREQ_CDCIN, CDC_GET_COMM_FEATURE, (fid & 0xff), (fid >> 8), bControlIface, nbytes, nbytes, dataptr, NULL));
|
return ( pUsb->ctrlReq(bAddress, 0, bmREQ_CDCIN, CDC_GET_COMM_FEATURE, (fid & 0xff), (fid >> 8), bControlIface, nbytes, nbytes, dataptr, NULL));
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t ACM::ClearCommFeature(uint16_t fid)
|
uint8_t ACM::ClearCommFeature(uint16_t fid) {
|
||||||
{
|
|
||||||
return ( pUsb->ctrlReq(bAddress, 0, bmREQ_CDCOUT, CDC_CLEAR_COMM_FEATURE, (fid & 0xff), (fid >> 8), bControlIface, 0, 0, NULL, NULL));
|
return ( pUsb->ctrlReq(bAddress, 0, bmREQ_CDCOUT, CDC_CLEAR_COMM_FEATURE, (fid & 0xff), (fid >> 8), bControlIface, 0, 0, NULL, NULL));
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t ACM::SetLineCoding(const LINE_CODING *dataptr)
|
uint8_t ACM::SetLineCoding(const LINE_CODING *dataptr) {
|
||||||
{
|
|
||||||
return ( pUsb->ctrlReq(bAddress, 0, bmREQ_CDCOUT, CDC_SET_LINE_CODING, 0x00, 0x00, bControlIface, sizeof (LINE_CODING), sizeof (LINE_CODING), (uint8_t*) dataptr, NULL));
|
return ( pUsb->ctrlReq(bAddress, 0, bmREQ_CDCOUT, CDC_SET_LINE_CODING, 0x00, 0x00, bControlIface, sizeof (LINE_CODING), sizeof (LINE_CODING), (uint8_t*) dataptr, NULL));
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t ACM::GetLineCoding(LINE_CODING *dataptr)
|
uint8_t ACM::GetLineCoding(LINE_CODING *dataptr) {
|
||||||
{
|
|
||||||
return ( pUsb->ctrlReq(bAddress, 0, bmREQ_CDCIN, CDC_GET_LINE_CODING, 0x00, 0x00, bControlIface, sizeof (LINE_CODING), sizeof (LINE_CODING), (uint8_t*) dataptr, NULL));
|
return ( pUsb->ctrlReq(bAddress, 0, bmREQ_CDCIN, CDC_GET_LINE_CODING, 0x00, 0x00, bControlIface, sizeof (LINE_CODING), sizeof (LINE_CODING), (uint8_t*) dataptr, NULL));
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t ACM::SetControlLineState(uint8_t state)
|
uint8_t ACM::SetControlLineState(uint8_t state) {
|
||||||
{
|
|
||||||
return ( pUsb->ctrlReq(bAddress, 0, bmREQ_CDCOUT, CDC_SET_CONTROL_LINE_STATE, state, 0, bControlIface, 0, 0, NULL, NULL));
|
return ( pUsb->ctrlReq(bAddress, 0, bmREQ_CDCOUT, CDC_SET_CONTROL_LINE_STATE, state, 0, bControlIface, 0, 0, NULL, NULL));
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t ACM::SendBreak(uint16_t duration)
|
uint8_t ACM::SendBreak(uint16_t duration) {
|
||||||
{
|
|
||||||
return ( pUsb->ctrlReq(bAddress, 0, bmREQ_CDCOUT, CDC_SEND_BREAK, (duration & 0xff), (duration >> 8), bControlIface, 0, 0, NULL, NULL));
|
return ( pUsb->ctrlReq(bAddress, 0, bmREQ_CDCOUT, CDC_SEND_BREAK, (duration & 0xff), (duration >> 8), bControlIface, 0, 0, NULL, NULL));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ACM::PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr) {
|
||||||
void ACM::PrintEndpointDescriptor( const USB_ENDPOINT_DESCRIPTOR* ep_ptr )
|
Notify(PSTR("Endpoint descriptor:"), 0x80);
|
||||||
{
|
Notify(PSTR("\r\nLength:\t\t"), 0x80);
|
||||||
Notify(PSTR("Endpoint descriptor:"));
|
PrintHex<uint8_t > (ep_ptr->bLength, 0x80);
|
||||||
Notify(PSTR("\r\nLength:\t\t"));
|
Notify(PSTR("\r\nType:\t\t"), 0x80);
|
||||||
PrintHex<uint8_t>(ep_ptr->bLength);
|
PrintHex<uint8_t > (ep_ptr->bDescriptorType, 0x80);
|
||||||
Notify(PSTR("\r\nType:\t\t"));
|
Notify(PSTR("\r\nAddress:\t"), 0x80);
|
||||||
PrintHex<uint8_t>(ep_ptr->bDescriptorType);
|
PrintHex<uint8_t > (ep_ptr->bEndpointAddress, 0x80);
|
||||||
Notify(PSTR("\r\nAddress:\t"));
|
Notify(PSTR("\r\nAttributes:\t"), 0x80);
|
||||||
PrintHex<uint8_t>(ep_ptr->bEndpointAddress);
|
PrintHex<uint8_t > (ep_ptr->bmAttributes, 0x80);
|
||||||
Notify(PSTR("\r\nAttributes:\t"));
|
Notify(PSTR("\r\nMaxPktSize:\t"), 0x80);
|
||||||
PrintHex<uint8_t>(ep_ptr->bmAttributes);
|
PrintHex<uint16_t > (ep_ptr->wMaxPacketSize, 0x80);
|
||||||
Notify(PSTR("\r\nMaxPktSize:\t"));
|
Notify(PSTR("\r\nPoll Intrv:\t"), 0x80);
|
||||||
PrintHex<uint16_t>(ep_ptr->wMaxPacketSize);
|
PrintHex<uint8_t > (ep_ptr->bInterval, 0x80);
|
||||||
Notify(PSTR("\r\nPoll Intrv:\t"));
|
Notify(PSTR("\r\n"), 0x80);
|
||||||
PrintHex<uint8_t>(ep_ptr->bInterval);
|
|
||||||
Notify(PSTR("\r\n"));
|
|
||||||
}
|
}
|
||||||
|
|
48
cdcacm.h
48
cdcacm.h
|
@ -89,20 +89,9 @@ e-mail : support@circuitsathome.com
|
||||||
#define CDC_GET_LINE_PARMS 0x35
|
#define CDC_GET_LINE_PARMS 0x35
|
||||||
#define CDC_DIAL_DIGITS 0x36
|
#define CDC_DIAL_DIGITS 0x36
|
||||||
|
|
||||||
//Class-Specific Notification Codes
|
|
||||||
#define NETWORK_CONNECTION 0x00
|
|
||||||
#define RESPONSE_AVAILABLE 0x01
|
|
||||||
#define AUX_JACK_HOOK_STATE 0x08
|
|
||||||
#define RING_DETECT 0x09
|
|
||||||
#define SERIAL_STATE 0x20
|
|
||||||
#define CALL_STATE_CHANGE 0x28
|
|
||||||
#define LINE_STATE_CHANGE 0x29
|
|
||||||
#define CONNECTION_SPEED_CHANGE 0x2a
|
|
||||||
|
|
||||||
|
|
||||||
// CDC Functional Descriptor Structures
|
// CDC Functional Descriptor Structures
|
||||||
typedef struct
|
|
||||||
{
|
typedef struct {
|
||||||
uint8_t bFunctionLength;
|
uint8_t bFunctionLength;
|
||||||
uint8_t bDescriptorType;
|
uint8_t bDescriptorType;
|
||||||
uint8_t bDescriptorSubtype;
|
uint8_t bDescriptorSubtype;
|
||||||
|
@ -110,8 +99,7 @@ typedef struct
|
||||||
uint8_t bDataInterface;
|
uint8_t bDataInterface;
|
||||||
} CALL_MGMNT_FUNC_DESCR;
|
} CALL_MGMNT_FUNC_DESCR;
|
||||||
|
|
||||||
typedef struct
|
typedef struct {
|
||||||
{
|
|
||||||
uint8_t bFunctionLength;
|
uint8_t bFunctionLength;
|
||||||
uint8_t bDescriptorType;
|
uint8_t bDescriptorType;
|
||||||
uint8_t bDescriptorSubtype;
|
uint8_t bDescriptorSubtype;
|
||||||
|
@ -119,8 +107,7 @@ typedef struct
|
||||||
} ACM_FUNC_DESCR, DLM_FUNC_DESCR, TEL_OPER_MODES_FUNC_DESCR,
|
} ACM_FUNC_DESCR, DLM_FUNC_DESCR, TEL_OPER_MODES_FUNC_DESCR,
|
||||||
TEL_CALL_STATE_REP_CPBL_FUNC_DESCR;
|
TEL_CALL_STATE_REP_CPBL_FUNC_DESCR;
|
||||||
|
|
||||||
typedef struct
|
typedef struct {
|
||||||
{
|
|
||||||
uint8_t bFunctionLength;
|
uint8_t bFunctionLength;
|
||||||
uint8_t bDescriptorType;
|
uint8_t bDescriptorType;
|
||||||
uint8_t bDescriptorSubtype;
|
uint8_t bDescriptorSubtype;
|
||||||
|
@ -128,28 +115,16 @@ typedef struct
|
||||||
uint8_t bNumRingerPatterns;
|
uint8_t bNumRingerPatterns;
|
||||||
} TEL_RINGER_FUNC_DESCR;
|
} TEL_RINGER_FUNC_DESCR;
|
||||||
|
|
||||||
typedef struct
|
typedef struct {
|
||||||
{
|
|
||||||
uint32_t dwDTERate; // Data Terminal Rate in bits per second
|
uint32_t dwDTERate; // Data Terminal Rate in bits per second
|
||||||
uint8_t bCharFormat; // 0 - 1 stop bit, 1 - 1.5 stop bits, 2 - 2 stop bits
|
uint8_t bCharFormat; // 0 - 1 stop bit, 1 - 1.5 stop bits, 2 - 2 stop bits
|
||||||
uint8_t bParityType; // 0 - None, 1 - Odd, 2 - Even, 3 - Mark, 4 - Space
|
uint8_t bParityType; // 0 - None, 1 - Odd, 2 - Even, 3 - Mark, 4 - Space
|
||||||
uint8_t bDataBits; // Data bits (5, 6, 7, 8 or 16)
|
uint8_t bDataBits; // Data bits (5, 6, 7, 8 or 16)
|
||||||
} LINE_CODING;
|
} LINE_CODING;
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
uint8_t bmRequestType; // 0xa1 for class-specific notifications
|
|
||||||
uint8_t bNotification;
|
|
||||||
uint16_t wValue;
|
|
||||||
uint16_t wIndex;
|
|
||||||
uint16_t wLength;
|
|
||||||
uint16_t bmState; //UART state bitmap for SERIAL_STATE, other notifications variable length
|
|
||||||
} CLASS_NOTIFICATION;
|
|
||||||
|
|
||||||
class ACM;
|
class ACM;
|
||||||
|
|
||||||
class CDCAsyncOper
|
class CDCAsyncOper {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
virtual uint8_t OnInit(ACM *pacm) = 0;
|
virtual uint8_t OnInit(ACM *pacm) = 0;
|
||||||
//virtual void OnDataRcvd(ACM *pacm, uint8_t nbytes, uint8_t *dataptr) = 0;
|
//virtual void OnDataRcvd(ACM *pacm, uint8_t nbytes, uint8_t *dataptr) = 0;
|
||||||
|
@ -159,8 +134,7 @@ public:
|
||||||
|
|
||||||
#define ACM_MAX_ENDPOINTS 4
|
#define ACM_MAX_ENDPOINTS 4
|
||||||
|
|
||||||
class ACM : public USBDeviceConfig, public UsbConfigXtracter
|
class ACM : public USBDeviceConfig, public UsbConfigXtracter {
|
||||||
{
|
|
||||||
protected:
|
protected:
|
||||||
static const uint8_t epDataInIndex; // DataIn endpoint index
|
static const uint8_t epDataInIndex; // DataIn endpoint index
|
||||||
static const uint8_t epDataOutIndex; // DataOUT endpoint index
|
static const uint8_t epDataOutIndex; // DataOUT endpoint index
|
||||||
|
@ -175,7 +149,6 @@ protected:
|
||||||
uint8_t bNumEP; // total number of EP in the configuration
|
uint8_t bNumEP; // total number of EP in the configuration
|
||||||
uint32_t qNextPollTime; // next poll time
|
uint32_t qNextPollTime; // next poll time
|
||||||
bool bPollEnable; // poll enable flag
|
bool bPollEnable; // poll enable flag
|
||||||
bool ready; //device ready indicator
|
|
||||||
|
|
||||||
EpInfo epInfo[ACM_MAX_ENDPOINTS];
|
EpInfo epInfo[ACM_MAX_ENDPOINTS];
|
||||||
|
|
||||||
|
@ -191,7 +164,6 @@ public:
|
||||||
uint8_t GetLineCoding(LINE_CODING *dataptr);
|
uint8_t GetLineCoding(LINE_CODING *dataptr);
|
||||||
uint8_t SetControlLineState(uint8_t state);
|
uint8_t SetControlLineState(uint8_t state);
|
||||||
uint8_t SendBreak(uint16_t duration);
|
uint8_t SendBreak(uint16_t duration);
|
||||||
uint8_t GetNotif( uint16_t *bytes_rcvd, uint8_t *dataptr );
|
|
||||||
|
|
||||||
// Methods for recieving and sending data
|
// Methods for recieving and sending data
|
||||||
uint8_t RcvData(uint16_t *nbytesptr, uint8_t *dataptr);
|
uint8_t RcvData(uint16_t *nbytesptr, uint8_t *dataptr);
|
||||||
|
@ -201,8 +173,10 @@ public:
|
||||||
virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed);
|
virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed);
|
||||||
virtual uint8_t Release();
|
virtual uint8_t Release();
|
||||||
virtual uint8_t Poll();
|
virtual uint8_t Poll();
|
||||||
virtual uint8_t GetAddress() { return bAddress; };
|
|
||||||
virtual bool isReady() { return ready; };
|
virtual uint8_t GetAddress() {
|
||||||
|
return bAddress;
|
||||||
|
};
|
||||||
|
|
||||||
// UsbConfigXtracter implementation
|
// UsbConfigXtracter implementation
|
||||||
virtual void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep);
|
virtual void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep);
|
||||||
|
|
120
cdcftdi.cpp
120
cdcftdi.cpp
|
@ -25,10 +25,8 @@ FTDI::FTDI(USB *p, FTDIAsyncOper *pasync) :
|
||||||
pUsb(p),
|
pUsb(p),
|
||||||
bAddress(0),
|
bAddress(0),
|
||||||
bNumEP(1),
|
bNumEP(1),
|
||||||
wFTDIType(0)
|
wFTDIType(0) {
|
||||||
{
|
for (uint8_t i = 0; i < FTDI_MAX_ENDPOINTS; i++) {
|
||||||
for(uint8_t i=0; i<FTDI_MAX_ENDPOINTS; i++)
|
|
||||||
{
|
|
||||||
epInfo[i].epAddr = 0;
|
epInfo[i].epAddr = 0;
|
||||||
epInfo[i].maxPktSize = (i) ? 0 : 8;
|
epInfo[i].maxPktSize = (i) ? 0 : 8;
|
||||||
epInfo[i].epAttribs = 0;
|
epInfo[i].epAttribs = 0;
|
||||||
|
@ -40,19 +38,18 @@ FTDI::FTDI(USB *p, FTDIAsyncOper *pasync) :
|
||||||
pUsb->RegisterDeviceClass(this);
|
pUsb->RegisterDeviceClass(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t FTDI::Init(uint8_t parent, uint8_t port, bool lowspeed)
|
uint8_t FTDI::Init(uint8_t parent, uint8_t port, bool lowspeed) {
|
||||||
{
|
|
||||||
const uint8_t constBufSize = sizeof (USB_DEVICE_DESCRIPTOR);
|
const uint8_t constBufSize = sizeof (USB_DEVICE_DESCRIPTOR);
|
||||||
|
|
||||||
uint8_t buf[constBufSize];
|
uint8_t buf[constBufSize];
|
||||||
uint8_t rcode;
|
uint8_t rcode;
|
||||||
UsbDevice *p = NULL;
|
UsbDevice *p = NULL;
|
||||||
EpInfo *oldep_ptr = NULL;
|
EpInfo *oldep_ptr = NULL;
|
||||||
uint8_t len = 0;
|
//uint8_t len = 0;
|
||||||
uint16_t cd_len = 0;
|
//uint16_t cd_len = 0;
|
||||||
|
|
||||||
uint8_t num_of_conf; // number of configurations
|
uint8_t num_of_conf; // number of configurations
|
||||||
uint8_t num_of_intf; // number of interfaces
|
//uint8_t num_of_intf; // number of interfaces
|
||||||
|
|
||||||
AddressPool &addrPool = pUsb->GetAddressPool();
|
AddressPool &addrPool = pUsb->GetAddressPool();
|
||||||
|
|
||||||
|
@ -67,8 +64,7 @@ uint8_t FTDI::Init(uint8_t parent, uint8_t port, bool lowspeed)
|
||||||
if (!p)
|
if (!p)
|
||||||
return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
|
return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
|
||||||
|
|
||||||
if (!p->epinfo)
|
if (!p->epinfo) {
|
||||||
{
|
|
||||||
USBTRACE("epinfo\r\n");
|
USBTRACE("epinfo\r\n");
|
||||||
return USB_ERROR_EPINFO_IS_NULL;
|
return USB_ERROR_EPINFO_IS_NULL;
|
||||||
}
|
}
|
||||||
|
@ -108,8 +104,7 @@ uint8_t FTDI::Init(uint8_t parent, uint8_t port, bool lowspeed)
|
||||||
// Assign new address to the device
|
// Assign new address to the device
|
||||||
rcode = pUsb->setAddr(0, 0, bAddress);
|
rcode = pUsb->setAddr(0, 0, bAddress);
|
||||||
|
|
||||||
if (rcode)
|
if (rcode) {
|
||||||
{
|
|
||||||
p->lowspeed = false;
|
p->lowspeed = false;
|
||||||
addrPool.FreeAddress(bAddress);
|
addrPool.FreeAddress(bAddress);
|
||||||
bAddress = 0;
|
bAddress = 0;
|
||||||
|
@ -138,14 +133,20 @@ uint8_t FTDI::Init(uint8_t parent, uint8_t port, bool lowspeed)
|
||||||
|
|
||||||
USBTRACE2("NC:", num_of_conf);
|
USBTRACE2("NC:", num_of_conf);
|
||||||
|
|
||||||
for (uint8_t i=0; i<num_of_conf; i++)
|
for (uint8_t i = 0; i < num_of_conf; i++) {
|
||||||
{
|
|
||||||
HexDumper<USBReadParser, uint16_t, uint16_t> HexDump;
|
HexDumper<USBReadParser, uint16_t, uint16_t> HexDump;
|
||||||
ConfigDescParser < 0xFF, 0xFF, 0xFF, CP_MASK_COMPARE_ALL> confDescrParser(this);
|
ConfigDescParser < 0xFF, 0xFF, 0xFF, CP_MASK_COMPARE_ALL> confDescrParser(this);
|
||||||
|
|
||||||
rcode = pUsb->getConfDescr(bAddress, 0, i, &HexDump);
|
rcode = pUsb->getConfDescr(bAddress, 0, i, &HexDump);
|
||||||
|
|
||||||
|
if (rcode)
|
||||||
|
goto FailGetConfDescr;
|
||||||
|
|
||||||
rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser);
|
rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser);
|
||||||
|
|
||||||
|
if (rcode)
|
||||||
|
goto FailGetConfDescr;
|
||||||
|
|
||||||
if (bNumEP > 1)
|
if (bNumEP > 1)
|
||||||
break;
|
break;
|
||||||
} // for
|
} // for
|
||||||
|
@ -192,27 +193,19 @@ FailSetConfDescr:
|
||||||
USBTRACE("setConf:");
|
USBTRACE("setConf:");
|
||||||
goto Fail;
|
goto Fail;
|
||||||
|
|
||||||
FailSetBaudRate:
|
|
||||||
USBTRACE("SetBaudRate:");
|
|
||||||
goto Fail;
|
|
||||||
|
|
||||||
FailSetFlowControl:
|
|
||||||
USBTRACE("SetFlowControl:");
|
|
||||||
goto Fail;
|
|
||||||
|
|
||||||
FailOnInit:
|
FailOnInit:
|
||||||
USBTRACE("OnInit:");
|
USBTRACE("OnInit:");
|
||||||
goto Fail;
|
goto Fail;
|
||||||
|
|
||||||
Fail:
|
Fail:
|
||||||
Serial.println(rcode, HEX);
|
PrintHex<uint8_t > (rcode, 0x80);
|
||||||
|
Notify(PSTR("\r\n"), 0x80);
|
||||||
|
//Serial.println(rcode, HEX);
|
||||||
Release();
|
Release();
|
||||||
return rcode;
|
return rcode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FTDI::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *pep) {
|
||||||
void FTDI::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *pep)
|
|
||||||
{
|
|
||||||
ErrorMessage<uint8_t > (PSTR("Conf.Val"), conf);
|
ErrorMessage<uint8_t > (PSTR("Conf.Val"), conf);
|
||||||
ErrorMessage<uint8_t > (PSTR("Iface Num"), iface);
|
ErrorMessage<uint8_t > (PSTR("Iface Num"), iface);
|
||||||
ErrorMessage<uint8_t > (PSTR("Alt.Set"), alt);
|
ErrorMessage<uint8_t > (PSTR("Alt.Set"), alt);
|
||||||
|
@ -232,15 +225,14 @@ void FTDI::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t prot
|
||||||
// Fill in the endpoint info structure
|
// Fill in the endpoint info structure
|
||||||
epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F);
|
epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F);
|
||||||
epInfo[index].maxPktSize = (uint8_t) pep->wMaxPacketSize;
|
epInfo[index].maxPktSize = (uint8_t) pep->wMaxPacketSize;
|
||||||
//epInfo[index].epAttribs = 0;
|
epInfo[index].epAttribs = 0;
|
||||||
|
|
||||||
bNumEP++;
|
bNumEP++;
|
||||||
|
|
||||||
PrintEndpointDescriptor(pep);
|
PrintEndpointDescriptor(pep);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t FTDI::Release()
|
uint8_t FTDI::Release() {
|
||||||
{
|
|
||||||
pUsb->GetAddressPool().FreeAddress(bAddress);
|
pUsb->GetAddressPool().FreeAddress(bAddress);
|
||||||
|
|
||||||
bAddress = 0;
|
bAddress = 0;
|
||||||
|
@ -250,8 +242,7 @@ uint8_t FTDI::Release()
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t FTDI::Poll()
|
uint8_t FTDI::Poll() {
|
||||||
{
|
|
||||||
uint8_t rcode = 0;
|
uint8_t rcode = 0;
|
||||||
|
|
||||||
//if (!bPollEnable)
|
//if (!bPollEnable)
|
||||||
|
@ -266,28 +257,26 @@ uint8_t FTDI::Poll()
|
||||||
return rcode;
|
return rcode;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t FTDI::SetBaudRate(uint32_t baud)
|
uint8_t FTDI::SetBaudRate(uint32_t baud) {
|
||||||
{
|
|
||||||
uint16_t baud_value, baud_index = 0;
|
uint16_t baud_value, baud_index = 0;
|
||||||
uint32_t divisor3;
|
uint32_t divisor3;
|
||||||
|
|
||||||
divisor3 = 48000000 / 2 / baud; // divisor shifted 3 bits to the left
|
divisor3 = 48000000 / 2 / baud; // divisor shifted 3 bits to the left
|
||||||
|
|
||||||
if (wFTDIType == FT232AM)
|
if (wFTDIType == FT232AM) {
|
||||||
{
|
|
||||||
if ((divisor3 & 0x7) == 7)
|
if ((divisor3 & 0x7) == 7)
|
||||||
divisor3++; // round x.7/8 up to x+1
|
divisor3++; // round x.7/8 up to x+1
|
||||||
|
|
||||||
baud_value = divisor3 >> 3;
|
baud_value = divisor3 >> 3;
|
||||||
divisor3 &= 0x7;
|
divisor3 &= 0x7;
|
||||||
|
|
||||||
if (divisor3 == 1) baud_value |= 0xc000; else // 0.125
|
if (divisor3 == 1) baud_value |= 0xc000;
|
||||||
if (divisor3 >= 4) baud_value |= 0x4000; else // 0.5
|
else // 0.125
|
||||||
|
if (divisor3 >= 4) baud_value |= 0x4000;
|
||||||
|
else // 0.5
|
||||||
if (divisor3 != 0) baud_value |= 0x8000; // 0.25
|
if (divisor3 != 0) baud_value |= 0x8000; // 0.25
|
||||||
if (baud_value == 1) baud_value = 0; /* special case for maximum baud rate */
|
if (baud_value == 1) baud_value = 0; /* special case for maximum baud rate */
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
static const unsigned char divfrac [8] = {0, 3, 2, 0, 1, 1, 2, 3};
|
static const unsigned char divfrac [8] = {0, 3, 2, 0, 1, 1, 2, 3};
|
||||||
static const unsigned char divindex[8] = {0, 0, 0, 1, 0, 1, 1, 1};
|
static const unsigned char divindex[8] = {0, 0, 0, 1, 0, 1, 1, 1};
|
||||||
|
|
||||||
|
@ -296,7 +285,8 @@ uint8_t FTDI::SetBaudRate(uint32_t baud)
|
||||||
baud_index = divindex[divisor3 & 0x7];
|
baud_index = divindex[divisor3 & 0x7];
|
||||||
|
|
||||||
/* Deal with special cases for highest baud rates. */
|
/* Deal with special cases for highest baud rates. */
|
||||||
if (baud_value == 1) baud_value = 0; else // 1.0
|
if (baud_value == 1) baud_value = 0;
|
||||||
|
else // 1.0
|
||||||
if (baud_value == 0x4001) baud_value = 1; // 1.5
|
if (baud_value == 0x4001) baud_value = 1; // 1.5
|
||||||
}
|
}
|
||||||
USBTRACE2("baud_value:", baud_value);
|
USBTRACE2("baud_value:", baud_value);
|
||||||
|
@ -304,45 +294,39 @@ uint8_t FTDI::SetBaudRate(uint32_t baud)
|
||||||
return pUsb->ctrlReq(bAddress, 0, bmREQ_FTDI_OUT, FTDI_SIO_SET_BAUD_RATE, baud_value & 0xff, baud_value >> 8, baud_index, 0, 0, NULL, NULL);
|
return pUsb->ctrlReq(bAddress, 0, bmREQ_FTDI_OUT, FTDI_SIO_SET_BAUD_RATE, baud_value & 0xff, baud_value >> 8, baud_index, 0, 0, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t FTDI::SetModemControl(uint16_t signal)
|
uint8_t FTDI::SetModemControl(uint16_t signal) {
|
||||||
{
|
|
||||||
return pUsb->ctrlReq(bAddress, 0, bmREQ_FTDI_OUT, FTDI_SIO_MODEM_CTRL, signal & 0xff, signal >> 8, 0, 0, 0, NULL, NULL);
|
return pUsb->ctrlReq(bAddress, 0, bmREQ_FTDI_OUT, FTDI_SIO_MODEM_CTRL, signal & 0xff, signal >> 8, 0, 0, 0, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t FTDI::SetFlowControl(uint8_t protocol, uint8_t xon, uint8_t xoff)
|
uint8_t FTDI::SetFlowControl(uint8_t protocol, uint8_t xon, uint8_t xoff) {
|
||||||
{
|
|
||||||
return pUsb->ctrlReq(bAddress, 0, bmREQ_FTDI_OUT, FTDI_SIO_SET_FLOW_CTRL, xon, xoff, protocol << 8, 0, 0, NULL, NULL);
|
return pUsb->ctrlReq(bAddress, 0, bmREQ_FTDI_OUT, FTDI_SIO_SET_FLOW_CTRL, xon, xoff, protocol << 8, 0, 0, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t FTDI::SetData(uint16_t databm)
|
uint8_t FTDI::SetData(uint16_t databm) {
|
||||||
{
|
|
||||||
return pUsb->ctrlReq(bAddress, 0, bmREQ_FTDI_OUT, FTDI_SIO_SET_DATA, databm & 0xff, databm >> 8, 0, 0, 0, NULL, NULL);
|
return pUsb->ctrlReq(bAddress, 0, bmREQ_FTDI_OUT, FTDI_SIO_SET_DATA, databm & 0xff, databm >> 8, 0, 0, 0, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t FTDI::RcvData(uint16_t *bytes_rcvd, uint8_t *dataptr)
|
uint8_t FTDI::RcvData(uint16_t *bytes_rcvd, uint8_t *dataptr) {
|
||||||
{
|
|
||||||
return pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, bytes_rcvd, dataptr);
|
return pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, bytes_rcvd, dataptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t FTDI::SndData(uint16_t nbytes, uint8_t *dataptr)
|
uint8_t FTDI::SndData(uint16_t nbytes, uint8_t *dataptr) {
|
||||||
{
|
|
||||||
return pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, nbytes, dataptr);
|
return pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, nbytes, dataptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FTDI::PrintEndpointDescriptor( const USB_ENDPOINT_DESCRIPTOR* ep_ptr )
|
void FTDI::PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr) {
|
||||||
{
|
Notify(PSTR("Endpoint descriptor:"), 0x80);
|
||||||
Notify(PSTR("Endpoint descriptor:"));
|
Notify(PSTR("\r\nLength:\t\t"), 0x80);
|
||||||
Notify(PSTR("\r\nLength:\t\t"));
|
PrintHex<uint8_t > (ep_ptr->bLength, 0x80);
|
||||||
PrintHex<uint8_t>(ep_ptr->bLength);
|
Notify(PSTR("\r\nType:\t\t"), 0x80);
|
||||||
Notify(PSTR("\r\nType:\t\t"));
|
PrintHex<uint8_t > (ep_ptr->bDescriptorType, 0x80);
|
||||||
PrintHex<uint8_t>(ep_ptr->bDescriptorType);
|
Notify(PSTR("\r\nAddress:\t"), 0x80);
|
||||||
Notify(PSTR("\r\nAddress:\t"));
|
PrintHex<uint8_t > (ep_ptr->bEndpointAddress, 0x80);
|
||||||
PrintHex<uint8_t>(ep_ptr->bEndpointAddress);
|
Notify(PSTR("\r\nAttributes:\t"), 0x80);
|
||||||
Notify(PSTR("\r\nAttributes:\t"));
|
PrintHex<uint8_t > (ep_ptr->bmAttributes, 0x80);
|
||||||
PrintHex<uint8_t>(ep_ptr->bmAttributes);
|
Notify(PSTR("\r\nMaxPktSize:\t"), 0x80);
|
||||||
Notify(PSTR("\r\nMaxPktSize:\t"));
|
PrintHex<uint16_t > (ep_ptr->wMaxPacketSize, 0x80);
|
||||||
PrintHex<uint16_t>(ep_ptr->wMaxPacketSize);
|
Notify(PSTR("\r\nPoll Intrv:\t"), 0x80);
|
||||||
Notify(PSTR("\r\nPoll Intrv:\t"));
|
PrintHex<uint8_t > (ep_ptr->bInterval, 0x80);
|
||||||
PrintHex<uint8_t>(ep_ptr->bInterval);
|
Notify(PSTR("\r\n"), 0x80);
|
||||||
Notify(PSTR("\r\n"));
|
|
||||||
}
|
}
|
||||||
|
|
11
cdcftdi.h
11
cdcftdi.h
|
@ -94,8 +94,7 @@ e-mail : support@circuitsathome.com
|
||||||
|
|
||||||
class FTDI;
|
class FTDI;
|
||||||
|
|
||||||
class FTDIAsyncOper
|
class FTDIAsyncOper {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
virtual uint8_t OnInit(FTDI *pftdi) = 0;
|
virtual uint8_t OnInit(FTDI *pftdi) = 0;
|
||||||
};
|
};
|
||||||
|
@ -105,8 +104,7 @@ public:
|
||||||
// so only three endpoints are allocated.
|
// so only three endpoints are allocated.
|
||||||
#define FTDI_MAX_ENDPOINTS 3
|
#define FTDI_MAX_ENDPOINTS 3
|
||||||
|
|
||||||
class FTDI : public USBDeviceConfig, public UsbConfigXtracter
|
class FTDI : public USBDeviceConfig, public UsbConfigXtracter {
|
||||||
{
|
|
||||||
static const uint8_t epDataInIndex; // DataIn endpoint index
|
static const uint8_t epDataInIndex; // DataIn endpoint index
|
||||||
static const uint8_t epDataOutIndex; // DataOUT endpoint index
|
static const uint8_t epDataOutIndex; // DataOUT endpoint index
|
||||||
static const uint8_t epInterruptInIndex; // InterruptIN endpoint index
|
static const uint8_t epInterruptInIndex; // InterruptIN endpoint index
|
||||||
|
@ -141,7 +139,10 @@ public:
|
||||||
virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed);
|
virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed);
|
||||||
virtual uint8_t Release();
|
virtual uint8_t Release();
|
||||||
virtual uint8_t Poll();
|
virtual uint8_t Poll();
|
||||||
virtual uint8_t GetAddress() { return bAddress; };
|
|
||||||
|
virtual uint8_t GetAddress() {
|
||||||
|
return bAddress;
|
||||||
|
};
|
||||||
|
|
||||||
// UsbConfigXtracter implementation
|
// UsbConfigXtracter implementation
|
||||||
virtual void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep);
|
virtual void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep);
|
||||||
|
|
|
@ -17,13 +17,11 @@ e-mail : support@circuitsathome.com
|
||||||
#include "cdcprolific.h"
|
#include "cdcprolific.h"
|
||||||
|
|
||||||
PL2303::PL2303(USB *p, CDCAsyncOper *pasync) :
|
PL2303::PL2303(USB *p, CDCAsyncOper *pasync) :
|
||||||
ACM(p, pasync)
|
ACM(p, pasync),
|
||||||
//wPLType(0)
|
wPLType(0) {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t PL2303::Init(uint8_t parent, uint8_t port, bool lowspeed)
|
uint8_t PL2303::Init(uint8_t parent, uint8_t port, bool lowspeed) {
|
||||||
{
|
|
||||||
const uint8_t constBufSize = sizeof (USB_DEVICE_DESCRIPTOR);
|
const uint8_t constBufSize = sizeof (USB_DEVICE_DESCRIPTOR);
|
||||||
|
|
||||||
uint8_t buf[constBufSize];
|
uint8_t buf[constBufSize];
|
||||||
|
@ -31,7 +29,6 @@ uint8_t PL2303::Init(uint8_t parent, uint8_t port, bool lowspeed)
|
||||||
UsbDevice *p = NULL;
|
UsbDevice *p = NULL;
|
||||||
EpInfo *oldep_ptr = NULL;
|
EpInfo *oldep_ptr = NULL;
|
||||||
uint8_t num_of_conf; // number of configurations
|
uint8_t num_of_conf; // number of configurations
|
||||||
enum pl2303_type pltype = unknown;
|
|
||||||
|
|
||||||
AddressPool &addrPool = pUsb->GetAddressPool();
|
AddressPool &addrPool = pUsb->GetAddressPool();
|
||||||
|
|
||||||
|
@ -46,8 +43,7 @@ uint8_t PL2303::Init(uint8_t parent, uint8_t port, bool lowspeed)
|
||||||
if (!p)
|
if (!p)
|
||||||
return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
|
return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
|
||||||
|
|
||||||
if (!p->epinfo)
|
if (!p->epinfo) {
|
||||||
{
|
|
||||||
USBTRACE("epinfo\r\n");
|
USBTRACE("epinfo\r\n");
|
||||||
return USB_ERROR_EPINFO_IS_NULL;
|
return USB_ERROR_EPINFO_IS_NULL;
|
||||||
}
|
}
|
||||||
|
@ -69,24 +65,11 @@ uint8_t PL2303::Init(uint8_t parent, uint8_t port, bool lowspeed)
|
||||||
if (rcode)
|
if (rcode)
|
||||||
goto FailGetDevDescr;
|
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;
|
return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;
|
||||||
}
|
|
||||||
|
|
||||||
/* determine chip variant */
|
// Save type of PL chip
|
||||||
|
wPLType = ((USB_DEVICE_DESCRIPTOR*) buf)->bcdDevice;
|
||||||
if (((USB_DEVICE_DESCRIPTOR*)buf)->bDeviceClass == 0x02 ) {
|
|
||||||
pltype = type_0;
|
|
||||||
}
|
|
||||||
else if (((USB_DEVICE_DESCRIPTOR*)buf)->bMaxPacketSize0 == 0x40 ) {
|
|
||||||
pltype = rev_HX;
|
|
||||||
}
|
|
||||||
else if (((USB_DEVICE_DESCRIPTOR*)buf)->bDeviceClass == 0x00) {
|
|
||||||
pltype = type_1;
|
|
||||||
}
|
|
||||||
else if (((USB_DEVICE_DESCRIPTOR*)buf)->bDeviceClass == 0xff) {
|
|
||||||
pltype = type_1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Allocate new address according to device class
|
// Allocate new address according to device class
|
||||||
bAddress = addrPool.AllocAddress(parent, false, port);
|
bAddress = addrPool.AllocAddress(parent, false, port);
|
||||||
|
@ -100,8 +83,7 @@ uint8_t PL2303::Init(uint8_t parent, uint8_t port, bool lowspeed)
|
||||||
// Assign new address to the device
|
// Assign new address to the device
|
||||||
rcode = pUsb->setAddr(0, 0, bAddress);
|
rcode = pUsb->setAddr(0, 0, bAddress);
|
||||||
|
|
||||||
if (rcode)
|
if (rcode) {
|
||||||
{
|
|
||||||
p->lowspeed = false;
|
p->lowspeed = false;
|
||||||
addrPool.FreeAddress(bAddress);
|
addrPool.FreeAddress(bAddress);
|
||||||
bAddress = 0;
|
bAddress = 0;
|
||||||
|
@ -130,14 +112,20 @@ uint8_t PL2303::Init(uint8_t parent, uint8_t port, bool lowspeed)
|
||||||
|
|
||||||
USBTRACE2("NC:", num_of_conf);
|
USBTRACE2("NC:", num_of_conf);
|
||||||
|
|
||||||
for( uint8_t i=0; i<num_of_conf; i++ )
|
for (uint8_t i = 0; i < num_of_conf; i++) {
|
||||||
{
|
HexDumper<USBReadParser, uint16_t, uint16_t> HexDump;
|
||||||
//HexDumper<USBReadParser, uint16_t, uint16_t> HexDump;
|
|
||||||
ConfigDescParser < 0xFF, 0, 0, CP_MASK_COMPARE_CLASS> confDescrParser(this);
|
ConfigDescParser < 0xFF, 0, 0, CP_MASK_COMPARE_CLASS> confDescrParser(this);
|
||||||
|
|
||||||
//rcode = pUsb->getConfDescr(bAddress, 0, i, &HexDump);
|
rcode = pUsb->getConfDescr(bAddress, 0, i, &HexDump);
|
||||||
|
|
||||||
|
if (rcode)
|
||||||
|
goto FailGetConfDescr;
|
||||||
|
|
||||||
rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser);
|
rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser);
|
||||||
|
|
||||||
|
if (rcode)
|
||||||
|
goto FailGetConfDescr;
|
||||||
|
|
||||||
if (bNumEP > 1)
|
if (bNumEP > 1)
|
||||||
break;
|
break;
|
||||||
} // for
|
} // for
|
||||||
|
@ -156,29 +144,6 @@ uint8_t PL2303::Init(uint8_t parent, uint8_t port, bool lowspeed)
|
||||||
if (rcode)
|
if (rcode)
|
||||||
goto FailSetConfDescr;
|
goto FailSetConfDescr;
|
||||||
|
|
||||||
#if defined(PL2303_COMPAT)
|
|
||||||
/* shamanic dance - sending Prolific init data as-is */
|
|
||||||
vendorRead( 0x84, 0x84, 0, buf );
|
|
||||||
vendorWrite( 0x04, 0x04, 0 );
|
|
||||||
vendorRead( 0x84, 0x84, 0, buf );
|
|
||||||
vendorRead( 0x83, 0x83, 0, buf );
|
|
||||||
vendorRead( 0x84, 0x84, 0, buf );
|
|
||||||
vendorWrite( 0x04, 0x04, 1 );
|
|
||||||
vendorRead( 0x84, 0x84, 0, buf);
|
|
||||||
vendorRead( 0x83, 0x83, 0, buf);
|
|
||||||
vendorWrite( 0, 0, 1 );
|
|
||||||
vendorWrite( 1, 0, 0 );
|
|
||||||
if ( pltype == rev_HX ) {
|
|
||||||
vendorWrite( 2, 0, 0x44 );
|
|
||||||
vendorWrite( 0x06, 0x06, 0 ); //from W7 init
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
vendorWrite( 2, 0, 0x24 );
|
|
||||||
}
|
|
||||||
/* shamanic dance end */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* calling post-init callback */
|
|
||||||
rcode = pAsync->OnInit(this);
|
rcode = pAsync->OnInit(this);
|
||||||
|
|
||||||
if (rcode)
|
if (rcode)
|
||||||
|
@ -186,8 +151,7 @@ uint8_t PL2303::Init(uint8_t parent, uint8_t port, bool lowspeed)
|
||||||
|
|
||||||
USBTRACE("PL configured\r\n");
|
USBTRACE("PL configured\r\n");
|
||||||
|
|
||||||
//bPollEnable = true;
|
bPollEnable = true;
|
||||||
ready = true;
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
FailGetDevDescr:
|
FailGetDevDescr:
|
||||||
|
@ -206,20 +170,14 @@ FailSetConfDescr:
|
||||||
USBTRACE("setConf:");
|
USBTRACE("setConf:");
|
||||||
goto Fail;
|
goto Fail;
|
||||||
|
|
||||||
FailSetControlLineState:
|
|
||||||
USBTRACE("SetControlLineState:");
|
|
||||||
goto Fail;
|
|
||||||
|
|
||||||
FailSetLineCoding:
|
|
||||||
USBTRACE("SetLineCoding:");
|
|
||||||
goto Fail;
|
|
||||||
|
|
||||||
FailOnInit:
|
FailOnInit:
|
||||||
USBTRACE("OnInit:");
|
USBTRACE("OnInit:");
|
||||||
goto Fail;
|
goto Fail;
|
||||||
|
|
||||||
Fail:
|
Fail:
|
||||||
Serial.println(rcode, HEX);
|
PrintHex<uint8_t > (rcode, 0x80);
|
||||||
|
Notify(PSTR("\r\n"), 0x80);
|
||||||
|
//Serial.println(rcode, HEX);
|
||||||
Release();
|
Release();
|
||||||
return rcode;
|
return rcode;
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,11 +38,11 @@ e-mail : support@circuitsathome.com
|
||||||
#include "confdescparser.h"
|
#include "confdescparser.h"
|
||||||
#include "cdcacm.h"
|
#include "cdcacm.h"
|
||||||
|
|
||||||
//#define PL2303_COMPAT //uncomment it if you have compatibility problems
|
|
||||||
|
|
||||||
#define PL_VID 0x067B
|
#define PL_VID 0x067B
|
||||||
#define PL_PID ( 0x2303 || 0x0609 )
|
#define PL_PID ( 0x2303 || 0x0609 )
|
||||||
|
|
||||||
|
//#define PL_PID 0x0609
|
||||||
|
|
||||||
#define PROLIFIC_REV_H 0x0202
|
#define PROLIFIC_REV_H 0x0202
|
||||||
#define PROLIFIC_REV_X 0x0300
|
#define PROLIFIC_REV_X 0x0300
|
||||||
#define PROLIFIC_REV_HX_CHIP_D 0x0400
|
#define PROLIFIC_REV_HX_CHIP_D 0x0400
|
||||||
|
@ -76,9 +76,7 @@ e-mail : support@circuitsathome.com
|
||||||
#define kCONTROL_DTR 0x01
|
#define kCONTROL_DTR 0x01
|
||||||
#define kCONTROL_RTS 0x02
|
#define kCONTROL_RTS 0x02
|
||||||
|
|
||||||
|
enum tXO_State {
|
||||||
enum tXO_State
|
|
||||||
{
|
|
||||||
kXOnSent = -2,
|
kXOnSent = -2,
|
||||||
kXOffSent = -1,
|
kXOffSent = -1,
|
||||||
kXO_Idle = 0,
|
kXO_Idle = 0,
|
||||||
|
@ -125,10 +123,8 @@ enum tXO_State
|
||||||
#define RESET_DOWNSTREAM_DATA_PIPE 0x08
|
#define RESET_DOWNSTREAM_DATA_PIPE 0x08
|
||||||
#define RESET_UPSTREAM_DATA_PIPE 0x09
|
#define RESET_UPSTREAM_DATA_PIPE 0x09
|
||||||
|
|
||||||
enum pl2303_type
|
enum pl2303_type {
|
||||||
{
|
|
||||||
unknown,
|
unknown,
|
||||||
type_0,
|
|
||||||
type_1, /* don't know the difference between type 0 and */
|
type_1, /* don't know the difference between type 0 and */
|
||||||
rev_X, /* type 1, until someone from prolific tells us... */
|
rev_X, /* type 1, until someone from prolific tells us... */
|
||||||
rev_HX, /* HX version of the pl2303 chip */
|
rev_HX, /* HX version of the pl2303 chip */
|
||||||
|
@ -138,13 +134,8 @@ enum pl2303_type
|
||||||
|
|
||||||
#define PL_MAX_ENDPOINTS 4
|
#define PL_MAX_ENDPOINTS 4
|
||||||
|
|
||||||
//class PL2303;
|
class PL2303 : public ACM {
|
||||||
|
uint16_t wPLType; // Type of chip
|
||||||
class PL2303 : public ACM
|
|
||||||
{
|
|
||||||
|
|
||||||
//uint16_t wPLType; // Type of chip
|
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PL2303(USB *pusb, CDCAsyncOper *pasync);
|
PL2303(USB *pusb, CDCAsyncOper *pasync);
|
||||||
|
@ -157,23 +148,6 @@ public:
|
||||||
|
|
||||||
//// UsbConfigXtracter implementation
|
//// UsbConfigXtracter implementation
|
||||||
//virtual void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep);
|
//virtual void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep);
|
||||||
|
|
||||||
private:
|
|
||||||
/* Prolific proprietary requests */
|
|
||||||
uint8_t vendorRead( uint8_t val_lo, uint8_t val_hi, uint16_t index, uint8_t* buf );
|
|
||||||
uint8_t vendorWrite( uint8_t val_lo, uint8_t val_hi, uint8_t index );
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* vendor read request */
|
|
||||||
inline uint8_t PL2303::vendorRead( uint8_t val_lo, uint8_t val_hi, uint16_t index, uint8_t* buf )
|
|
||||||
{
|
|
||||||
return( pUsb->ctrlReq(bAddress, 0, VENDOR_READ_REQUEST_TYPE, VENDOR_READ_REQUEST, val_lo, val_hi, index, 1, 1, buf, NULL ));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* vendor write request */
|
|
||||||
inline uint8_t PL2303::vendorWrite( uint8_t val_lo, uint8_t val_hi, uint8_t index )
|
|
||||||
{
|
|
||||||
return( pUsb->ctrlReq(bAddress, 0, VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, val_lo, val_hi, index, 0, 0, NULL, NULL ));
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // __CDCPROLIFIC_H__
|
#endif // __CDCPROLIFIC_H__
|
|
@ -27,8 +27,7 @@ e-mail : support@circuitsathome.com
|
||||||
|
|
||||||
//#include "hid.h"
|
//#include "hid.h"
|
||||||
|
|
||||||
class UsbConfigXtracter
|
class UsbConfigXtracter {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
//virtual void ConfigXtract(const USB_CONFIGURATION_DESCRIPTOR *conf) = 0;
|
//virtual void ConfigXtract(const USB_CONFIGURATION_DESCRIPTOR *conf) = 0;
|
||||||
//virtual void InterfaceXtract(uint8_t conf, const USB_INTERFACE_DESCRIPTOR *iface) = 0;
|
//virtual void InterfaceXtract(uint8_t conf, const USB_INTERFACE_DESCRIPTOR *iface) = 0;
|
||||||
|
@ -41,9 +40,9 @@ public:
|
||||||
#define CP_MASK_COMPARE_ALL 7
|
#define CP_MASK_COMPARE_ALL 7
|
||||||
|
|
||||||
// Configuration Descriptor Parser Class Template
|
// Configuration Descriptor Parser Class Template
|
||||||
|
|
||||||
template <const uint8_t CLASS_ID, const uint8_t SUBCLASS_ID, const uint8_t PROTOCOL_ID, const uint8_t MASK>
|
template <const uint8_t CLASS_ID, const uint8_t SUBCLASS_ID, const uint8_t PROTOCOL_ID, const uint8_t MASK>
|
||||||
class ConfigDescParser : public USBReadParser
|
class ConfigDescParser : public USBReadParser {
|
||||||
{
|
|
||||||
UsbConfigXtracter *theXtractor;
|
UsbConfigXtracter *theXtractor;
|
||||||
MultiValueBuffer theBuffer;
|
MultiValueBuffer theBuffer;
|
||||||
MultiByteValueParser valParser;
|
MultiByteValueParser valParser;
|
||||||
|
@ -72,19 +71,17 @@ public:
|
||||||
|
|
||||||
template <const uint8_t CLASS_ID, const uint8_t SUBCLASS_ID, const uint8_t PROTOCOL_ID, const uint8_t MASK>
|
template <const uint8_t CLASS_ID, const uint8_t SUBCLASS_ID, const uint8_t PROTOCOL_ID, const uint8_t MASK>
|
||||||
ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::ConfigDescParser(UsbConfigXtracter *xtractor) :
|
ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::ConfigDescParser(UsbConfigXtracter *xtractor) :
|
||||||
|
theXtractor(xtractor),
|
||||||
stateParseDescr(0),
|
stateParseDescr(0),
|
||||||
dscrLen(0),
|
dscrLen(0),
|
||||||
dscrType(0),
|
dscrType(0) {
|
||||||
theXtractor(xtractor)
|
|
||||||
{
|
|
||||||
theBuffer.pValue = varBuffer;
|
theBuffer.pValue = varBuffer;
|
||||||
valParser.Initialize(&theBuffer);
|
valParser.Initialize(&theBuffer);
|
||||||
theSkipper.Initialize(&theBuffer);
|
theSkipper.Initialize(&theBuffer);
|
||||||
};
|
};
|
||||||
|
|
||||||
template <const uint8_t CLASS_ID, const uint8_t SUBCLASS_ID, const uint8_t PROTOCOL_ID, const uint8_t MASK>
|
template <const uint8_t CLASS_ID, const uint8_t SUBCLASS_ID, const uint8_t PROTOCOL_ID, const uint8_t MASK>
|
||||||
void ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::Parse(const uint16_t len, const uint8_t *pbuf, const uint16_t &offset)
|
void ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::Parse(const uint16_t len, const uint8_t *pbuf, const uint16_t &offset) {
|
||||||
{
|
|
||||||
uint16_t cntdn = (uint16_t) len;
|
uint16_t cntdn = (uint16_t) len;
|
||||||
uint8_t *p = (uint8_t*) pbuf;
|
uint8_t *p = (uint8_t*) pbuf;
|
||||||
|
|
||||||
|
@ -92,13 +89,12 @@ void ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::Parse(const uin
|
||||||
if (!ParseDescriptor(&p, &cntdn))
|
if (!ParseDescriptor(&p, &cntdn))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Parser for the configuration descriptor. Takes values for class, subclass, protocol fields in interface descriptor and
|
/* Parser for the configuration descriptor. Takes values for class, subclass, protocol fields in interface descriptor and
|
||||||
compare masks for them. When the match is found, calls EndpointXtract passing buffer containing endpoint descriptor */
|
compare masks for them. When the match is found, calls EndpointXtract passing buffer containing endpoint descriptor */
|
||||||
template <const uint8_t CLASS_ID, const uint8_t SUBCLASS_ID, const uint8_t PROTOCOL_ID, const uint8_t MASK>
|
template <const uint8_t CLASS_ID, const uint8_t SUBCLASS_ID, const uint8_t PROTOCOL_ID, const uint8_t MASK>
|
||||||
bool ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::ParseDescriptor(uint8_t **pp, uint16_t *pcntdn)
|
bool ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::ParseDescriptor(uint8_t **pp, uint16_t *pcntdn) {
|
||||||
{
|
switch (stateParseDescr) {
|
||||||
switch (stateParseDescr)
|
|
||||||
{
|
|
||||||
case 0:
|
case 0:
|
||||||
theBuffer.valueSize = 2;
|
theBuffer.valueSize = 2;
|
||||||
valParser.Initialize(&theBuffer);
|
valParser.Initialize(&theBuffer);
|
||||||
|
@ -110,7 +106,7 @@ bool ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::ParseDescriptor
|
||||||
dscrType = *((uint8_t*) theBuffer.pValue + 1);
|
dscrType = *((uint8_t*) theBuffer.pValue + 1);
|
||||||
stateParseDescr = 2;
|
stateParseDescr = 2;
|
||||||
case 2:
|
case 2:
|
||||||
// This is a sort of hack. Assuming that two bytes are already in the buffer
|
// This is a sort of hack. Assuming that two bytes are allready in the buffer
|
||||||
// the pointer is positioned two bytes ahead in order for the rest of descriptor
|
// the pointer is positioned two bytes ahead in order for the rest of descriptor
|
||||||
// to be read right after the size and the type fields.
|
// to be read right after the size and the type fields.
|
||||||
// This should be used carefuly. varBuffer should be used directly to handle data
|
// This should be used carefuly. varBuffer should be used directly to handle data
|
||||||
|
@ -118,8 +114,7 @@ bool ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::ParseDescriptor
|
||||||
theBuffer.pValue = varBuffer + 2;
|
theBuffer.pValue = varBuffer + 2;
|
||||||
stateParseDescr = 3;
|
stateParseDescr = 3;
|
||||||
case 3:
|
case 3:
|
||||||
switch (dscrType)
|
switch (dscrType) {
|
||||||
{
|
|
||||||
case USB_DESCRIPTOR_INTERFACE:
|
case USB_DESCRIPTOR_INTERFACE:
|
||||||
isGoodInterface = false;
|
isGoodInterface = false;
|
||||||
case USB_DESCRIPTOR_CONFIGURATION:
|
case USB_DESCRIPTOR_CONFIGURATION:
|
||||||
|
@ -135,8 +130,7 @@ bool ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::ParseDescriptor
|
||||||
valParser.Initialize(&theBuffer);
|
valParser.Initialize(&theBuffer);
|
||||||
stateParseDescr = 4;
|
stateParseDescr = 4;
|
||||||
case 4:
|
case 4:
|
||||||
switch (dscrType)
|
switch (dscrType) {
|
||||||
{
|
|
||||||
case USB_DESCRIPTOR_CONFIGURATION:
|
case USB_DESCRIPTOR_CONFIGURATION:
|
||||||
if (!valParser.Parse(pp, pcntdn))
|
if (!valParser.Parse(pp, pcntdn))
|
||||||
return false;
|
return false;
|
||||||
|
@ -180,23 +174,22 @@ bool ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::ParseDescriptor
|
||||||
}
|
}
|
||||||
|
|
||||||
template <const uint8_t CLASS_ID, const uint8_t SUBCLASS_ID, const uint8_t PROTOCOL_ID, const uint8_t MASK>
|
template <const uint8_t CLASS_ID, const uint8_t SUBCLASS_ID, const uint8_t PROTOCOL_ID, const uint8_t MASK>
|
||||||
void ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::PrintHidDescriptor(const USB_HID_DESCRIPTOR *pDesc)
|
void ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::PrintHidDescriptor(const USB_HID_DESCRIPTOR *pDesc) {
|
||||||
{
|
Notify(PSTR("\r\n\r\nHID Descriptor:\r\n"), 0x80);
|
||||||
Notify(PSTR("\r\n\r\nHID Descriptor:\r\n"));
|
Notify(PSTR("bDescLength:\t\t"), 0x80);
|
||||||
Notify(PSTR("bDescLength:\t\t"));
|
PrintHex<uint8_t > (pDesc->bLength, 0x80);
|
||||||
PrintHex<uint8_t>(pDesc->bLength);
|
|
||||||
|
|
||||||
Notify(PSTR("\r\nbDescriptorType:\t"));
|
Notify(PSTR("\r\nbDescriptorType:\t"), 0x80);
|
||||||
PrintHex<uint8_t>(pDesc->bDescriptorType);
|
PrintHex<uint8_t > (pDesc->bDescriptorType, 0x80);
|
||||||
|
|
||||||
Notify(PSTR("\r\nbcdHID:\t\t\t"));
|
Notify(PSTR("\r\nbcdHID:\t\t\t"), 0x80);
|
||||||
PrintHex<uint16_t>(pDesc->bcdHID);
|
PrintHex<uint16_t > (pDesc->bcdHID, 0x80);
|
||||||
|
|
||||||
Notify(PSTR("\r\nbCountryCode:\t\t"));
|
Notify(PSTR("\r\nbCountryCode:\t\t"), 0x80);
|
||||||
PrintHex<uint8_t>(pDesc->bCountryCode);
|
PrintHex<uint8_t > (pDesc->bCountryCode, 0x80);
|
||||||
|
|
||||||
Notify(PSTR("\r\nbNumDescriptors:\t"));
|
Notify(PSTR("\r\nbNumDescriptors:\t"), 0x80);
|
||||||
PrintHex<uint8_t>(pDesc->bNumDescriptors);
|
PrintHex<uint8_t > (pDesc->bNumDescriptors, 0x80);
|
||||||
|
|
||||||
//Notify(PSTR("\r\nbDescrType:\t\t"));
|
//Notify(PSTR("\r\nbDescrType:\t\t"));
|
||||||
//PrintHex<uint8_t>(pDesc->bDescrType);
|
//PrintHex<uint8_t>(pDesc->bDescrType);
|
||||||
|
@ -204,17 +197,16 @@ void ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::PrintHidDescrip
|
||||||
//Notify(PSTR("\r\nwDescriptorLength:\t"));
|
//Notify(PSTR("\r\nwDescriptorLength:\t"));
|
||||||
//PrintHex<uint16_t>(pDesc->wDescriptorLength);
|
//PrintHex<uint16_t>(pDesc->wDescriptorLength);
|
||||||
|
|
||||||
for (uint8_t i=0; i<pDesc->bNumDescriptors; i++)
|
for (uint8_t i = 0; i < pDesc->bNumDescriptors; i++) {
|
||||||
{
|
|
||||||
HID_CLASS_DESCRIPTOR_LEN_AND_TYPE *pLT = (HID_CLASS_DESCRIPTOR_LEN_AND_TYPE*)&(pDesc->bDescrType);
|
HID_CLASS_DESCRIPTOR_LEN_AND_TYPE *pLT = (HID_CLASS_DESCRIPTOR_LEN_AND_TYPE*)&(pDesc->bDescrType);
|
||||||
|
|
||||||
Notify(PSTR("\r\nbDescrType:\t\t"));
|
Notify(PSTR("\r\nbDescrType:\t\t"), 0x80);
|
||||||
PrintHex<uint8_t>(pLT[i].bDescrType);
|
PrintHex<uint8_t > (pLT[i].bDescrType, 0x80);
|
||||||
|
|
||||||
Notify(PSTR("\r\nwDescriptorLength:\t"));
|
Notify(PSTR("\r\nwDescriptorLength:\t"), 0x80);
|
||||||
PrintHex<uint16_t>(pLT[i].wDescriptorLength);
|
PrintHex<uint16_t > (pLT[i].wDescriptorLength, 0x80);
|
||||||
}
|
}
|
||||||
Notify(PSTR("\r\n"));
|
Notify(PSTR("\r\n"), 0x80);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
29
hexdump.h
29
hexdump.h
|
@ -22,33 +22,34 @@ e-mail : support@circuitsathome.com
|
||||||
#include "printhex.h"
|
#include "printhex.h"
|
||||||
|
|
||||||
template <class BASE_CLASS, class LEN_TYPE, class OFFSET_TYPE>
|
template <class BASE_CLASS, class LEN_TYPE, class OFFSET_TYPE>
|
||||||
class HexDumper : public BASE_CLASS
|
class HexDumper : public BASE_CLASS {
|
||||||
{
|
|
||||||
uint8_t byteCount;
|
uint8_t byteCount;
|
||||||
OFFSET_TYPE byteTotal;
|
OFFSET_TYPE byteTotal;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
HexDumper() : byteCount(0), byteTotal(0) {};
|
|
||||||
void Initialize() { byteCount = 0; byteTotal = 0; };
|
HexDumper() : byteCount(0), byteTotal(0) {
|
||||||
|
};
|
||||||
|
|
||||||
|
void Initialize() {
|
||||||
|
byteCount = 0;
|
||||||
|
byteTotal = 0;
|
||||||
|
};
|
||||||
|
|
||||||
virtual void Parse(const LEN_TYPE len, const uint8_t *pbuf, const OFFSET_TYPE &offset);
|
virtual void Parse(const LEN_TYPE len, const uint8_t *pbuf, const OFFSET_TYPE &offset);
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class BASE_CLASS, class LEN_TYPE, class OFFSET_TYPE>
|
template <class BASE_CLASS, class LEN_TYPE, class OFFSET_TYPE>
|
||||||
void HexDumper<BASE_CLASS, LEN_TYPE, OFFSET_TYPE>::Parse(const LEN_TYPE len, const uint8_t *pbuf, const OFFSET_TYPE &offset)
|
void HexDumper<BASE_CLASS, LEN_TYPE, OFFSET_TYPE>::Parse(const LEN_TYPE len, const uint8_t *pbuf, const OFFSET_TYPE &offset) {
|
||||||
{
|
for (LEN_TYPE j = 0; j < len; j++, byteCount++, byteTotal++) {
|
||||||
for (LEN_TYPE j=0; j<len; j++, byteCount++, byteTotal++)
|
if (!byteCount) {
|
||||||
{
|
SerialPrintHex<OFFSET_TYPE > (byteTotal);
|
||||||
if (!byteCount)
|
|
||||||
{
|
|
||||||
PrintHex<OFFSET_TYPE>(byteTotal);
|
|
||||||
Serial.print(": ");
|
Serial.print(": ");
|
||||||
}
|
}
|
||||||
PrintHex<uint8_t>(pbuf[j]);
|
SerialPrintHex<uint8_t > (pbuf[j]);
|
||||||
Serial.print(" ");
|
Serial.print(" ");
|
||||||
|
|
||||||
if (byteCount == 15)
|
if (byteCount == 15) {
|
||||||
{
|
|
||||||
Serial.println("");
|
Serial.println("");
|
||||||
byteCount = 0xFF;
|
byteCount = 0xFF;
|
||||||
}
|
}
|
||||||
|
|
90
hid.cpp
90
hid.cpp
|
@ -1,8 +1,8 @@
|
||||||
#include "hid.h"
|
#include "hid.h"
|
||||||
|
|
||||||
//get HID report descriptor
|
//get HID report descriptor
|
||||||
uint8_t HID::GetReportDescr( uint8_t ep, USBReadParser *parser )
|
|
||||||
{
|
uint8_t HID::GetReportDescr(uint8_t ep, USBReadParser *parser) {
|
||||||
const uint8_t constBufLen = 64;
|
const uint8_t constBufLen = 64;
|
||||||
uint8_t buf[constBufLen];
|
uint8_t buf[constBufLen];
|
||||||
|
|
||||||
|
@ -16,69 +16,67 @@ uint8_t HID::GetReportDescr( uint8_t ep, USBReadParser *parser )
|
||||||
//{
|
//{
|
||||||
// return( pUsb->ctrlReq( bAddress, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, 0x00, HID_DESCRIPTOR_HID, 0x0000, nbytes, dataptr ));
|
// return( pUsb->ctrlReq( bAddress, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, 0x00, HID_DESCRIPTOR_HID, 0x0000, nbytes, dataptr ));
|
||||||
//}
|
//}
|
||||||
uint8_t HID::SetReport( uint8_t ep, uint8_t iface, uint8_t report_type, uint8_t report_id, uint16_t nbytes, uint8_t* dataptr )
|
|
||||||
{
|
uint8_t HID::SetReport(uint8_t ep, uint8_t iface, uint8_t report_type, uint8_t report_id, uint16_t nbytes, uint8_t* dataptr) {
|
||||||
return ( pUsb->ctrlReq(bAddress, ep, bmREQ_HIDOUT, HID_REQUEST_SET_REPORT, report_id, report_type, iface, nbytes, nbytes, dataptr, NULL));
|
return ( pUsb->ctrlReq(bAddress, ep, bmREQ_HIDOUT, HID_REQUEST_SET_REPORT, report_id, report_type, iface, nbytes, nbytes, dataptr, NULL));
|
||||||
}
|
}
|
||||||
uint8_t HID::GetReport( uint8_t ep, uint8_t iface, uint8_t report_type, uint8_t report_id, uint16_t nbytes, uint8_t* dataptr )
|
|
||||||
{
|
uint8_t HID::GetReport(uint8_t ep, uint8_t iface, uint8_t report_type, uint8_t report_id, uint16_t nbytes, uint8_t* dataptr) {
|
||||||
return ( pUsb->ctrlReq(bAddress, ep, bmREQ_HIDIN, HID_REQUEST_GET_REPORT, report_id, report_type, iface, nbytes, nbytes, dataptr, NULL));
|
return ( pUsb->ctrlReq(bAddress, ep, bmREQ_HIDIN, HID_REQUEST_GET_REPORT, report_id, report_type, iface, nbytes, nbytes, dataptr, NULL));
|
||||||
}
|
}
|
||||||
uint8_t HID::GetIdle( uint8_t iface, uint8_t reportID, uint8_t* dataptr )
|
|
||||||
{
|
uint8_t HID::GetIdle(uint8_t iface, uint8_t reportID, uint8_t* dataptr) {
|
||||||
return ( pUsb->ctrlReq(bAddress, 0, bmREQ_HIDIN, HID_REQUEST_GET_IDLE, reportID, 0, iface, 0x0001, 0x0001, dataptr, NULL));
|
return ( pUsb->ctrlReq(bAddress, 0, bmREQ_HIDIN, HID_REQUEST_GET_IDLE, reportID, 0, iface, 0x0001, 0x0001, dataptr, NULL));
|
||||||
}
|
}
|
||||||
uint8_t HID::SetIdle( uint8_t iface, uint8_t reportID, uint8_t duration )
|
|
||||||
{
|
uint8_t HID::SetIdle(uint8_t iface, uint8_t reportID, uint8_t duration) {
|
||||||
return ( pUsb->ctrlReq(bAddress, 0, bmREQ_HIDOUT, HID_REQUEST_SET_IDLE, reportID, duration, iface, 0x0000, 0x0000, NULL, NULL));
|
return ( pUsb->ctrlReq(bAddress, 0, bmREQ_HIDOUT, HID_REQUEST_SET_IDLE, reportID, duration, iface, 0x0000, 0x0000, NULL, NULL));
|
||||||
}
|
}
|
||||||
uint8_t HID::SetProtocol( uint8_t iface, uint8_t protocol )
|
|
||||||
{
|
uint8_t HID::SetProtocol(uint8_t iface, uint8_t protocol) {
|
||||||
return ( pUsb->ctrlReq(bAddress, 0, bmREQ_HIDOUT, HID_REQUEST_SET_PROTOCOL, protocol, 0x00, iface, 0x0000, 0x0000, NULL, NULL));
|
return ( pUsb->ctrlReq(bAddress, 0, bmREQ_HIDOUT, HID_REQUEST_SET_PROTOCOL, protocol, 0x00, iface, 0x0000, 0x0000, NULL, NULL));
|
||||||
}
|
}
|
||||||
uint8_t HID::GetProtocol( uint8_t iface, uint8_t* dataptr )
|
|
||||||
{
|
uint8_t HID::GetProtocol(uint8_t iface, uint8_t* dataptr) {
|
||||||
return ( pUsb->ctrlReq(bAddress, 0, bmREQ_HIDIN, HID_REQUEST_GET_PROTOCOL, 0x00, 0x00, iface, 0x0001, 0x0001, dataptr, NULL));
|
return ( pUsb->ctrlReq(bAddress, 0, bmREQ_HIDIN, HID_REQUEST_GET_PROTOCOL, 0x00, 0x00, iface, 0x0001, 0x0001, dataptr, NULL));
|
||||||
}
|
}
|
||||||
|
|
||||||
void HID::PrintEndpointDescriptor( const USB_ENDPOINT_DESCRIPTOR* ep_ptr )
|
void HID::PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr) {
|
||||||
{
|
Notify(PSTR("Endpoint descriptor:"), 0x80);
|
||||||
Notify(PSTR("Endpoint descriptor:"));
|
Notify(PSTR("\r\nLength:\t\t"), 0x80);
|
||||||
Notify(PSTR("\r\nLength:\t\t"));
|
PrintHex<uint8_t > (ep_ptr->bLength, 0x80);
|
||||||
PrintHex<uint8_t>(ep_ptr->bLength);
|
Notify(PSTR("\r\nType:\t\t"), 0x80);
|
||||||
Notify(PSTR("\r\nType:\t\t"));
|
PrintHex<uint8_t > (ep_ptr->bDescriptorType, 0x80);
|
||||||
PrintHex<uint8_t>(ep_ptr->bDescriptorType);
|
Notify(PSTR("\r\nAddress:\t"), 0x80);
|
||||||
Notify(PSTR("\r\nAddress:\t"));
|
PrintHex<uint8_t > (ep_ptr->bEndpointAddress, 0x80);
|
||||||
PrintHex<uint8_t>(ep_ptr->bEndpointAddress);
|
Notify(PSTR("\r\nAttributes:\t"), 0x80);
|
||||||
Notify(PSTR("\r\nAttributes:\t"));
|
PrintHex<uint8_t > (ep_ptr->bmAttributes, 0x80);
|
||||||
PrintHex<uint8_t>(ep_ptr->bmAttributes);
|
Notify(PSTR("\r\nMaxPktSize:\t"), 0x80);
|
||||||
Notify(PSTR("\r\nMaxPktSize:\t"));
|
PrintHex<uint16_t > (ep_ptr->wMaxPacketSize, 0x80);
|
||||||
PrintHex<uint16_t>(ep_ptr->wMaxPacketSize);
|
Notify(PSTR("\r\nPoll Intrv:\t"), 0x80);
|
||||||
Notify(PSTR("\r\nPoll Intrv:\t"));
|
PrintHex<uint8_t > (ep_ptr->bInterval, 0x80);
|
||||||
PrintHex<uint8_t>(ep_ptr->bInterval);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void HID::PrintHidDescriptor(const USB_HID_DESCRIPTOR *pDesc)
|
void HID::PrintHidDescriptor(const USB_HID_DESCRIPTOR *pDesc) {
|
||||||
{
|
Notify(PSTR("\r\n\r\nHID Descriptor:\r\n"), 0x80);
|
||||||
Notify(PSTR("\r\n\r\nHID Descriptor:\r\n"));
|
Notify(PSTR("bDescLength:\t\t"), 0x80);
|
||||||
Notify(PSTR("bDescLength:\t\t"));
|
PrintHex<uint8_t > (pDesc->bLength, 0x80);
|
||||||
PrintHex<uint8_t>(pDesc->bLength);
|
|
||||||
|
|
||||||
Notify(PSTR("\r\nbDescriptorType:\t"));
|
Notify(PSTR("\r\nbDescriptorType:\t"), 0x80);
|
||||||
PrintHex<uint8_t>(pDesc->bDescriptorType);
|
PrintHex<uint8_t > (pDesc->bDescriptorType, 0x80);
|
||||||
|
|
||||||
Notify(PSTR("\r\nbcdHID:\t\t\t"));
|
Notify(PSTR("\r\nbcdHID:\t\t\t"), 0x80);
|
||||||
PrintHex<uint16_t>(pDesc->bcdHID);
|
PrintHex<uint16_t > (pDesc->bcdHID, 0x80);
|
||||||
|
|
||||||
Notify(PSTR("\r\nbCountryCode:\t\t"));
|
Notify(PSTR("\r\nbCountryCode:\t\t"), 0x80);
|
||||||
PrintHex<uint8_t>(pDesc->bCountryCode);
|
PrintHex<uint8_t > (pDesc->bCountryCode, 0x80);
|
||||||
|
|
||||||
Notify(PSTR("\r\nbNumDescriptors:\t"));
|
Notify(PSTR("\r\nbNumDescriptors:\t"), 0x80);
|
||||||
PrintHex<uint8_t>(pDesc->bNumDescriptors);
|
PrintHex<uint8_t > (pDesc->bNumDescriptors, 0x80);
|
||||||
|
|
||||||
Notify(PSTR("\r\nbDescrType:\t\t"));
|
Notify(PSTR("\r\nbDescrType:\t\t"), 0x80);
|
||||||
PrintHex<uint8_t>(pDesc->bDescrType);
|
PrintHex<uint8_t > (pDesc->bDescrType, 0x80);
|
||||||
|
|
||||||
Notify(PSTR("\r\nwDescriptorLength:\t"));
|
Notify(PSTR("\r\nwDescriptorLength:\t"), 0x80);
|
||||||
PrintHex<uint16_t>(pDesc->wDescriptorLength);
|
PrintHex<uint16_t > (pDesc->wDescriptorLength, 0x80);
|
||||||
}
|
}
|
||||||
|
|
20
hid.h
20
hid.h
|
@ -108,8 +108,7 @@ e-mail : support@circuitsathome.com
|
||||||
#define HID_PROTOCOL_KEYBOARD 0x01
|
#define HID_PROTOCOL_KEYBOARD 0x01
|
||||||
#define HID_PROTOCOL_MOUSE 0x02
|
#define HID_PROTOCOL_MOUSE 0x02
|
||||||
|
|
||||||
struct HidItemPrefix
|
struct HidItemPrefix {
|
||||||
{
|
|
||||||
uint8_t bSize : 2;
|
uint8_t bSize : 2;
|
||||||
uint8_t bType : 2;
|
uint8_t bType : 2;
|
||||||
uint8_t bTag : 4;
|
uint8_t bTag : 4;
|
||||||
|
@ -138,8 +137,7 @@ struct HidItemPrefix
|
||||||
#define HID_MAIN_ITEM_COLLECTION_USAGE_SWITCH 5
|
#define HID_MAIN_ITEM_COLLECTION_USAGE_SWITCH 5
|
||||||
#define HID_MAIN_ITEM_COLLECTION_USAGE_MODIFIER 6
|
#define HID_MAIN_ITEM_COLLECTION_USAGE_MODIFIER 6
|
||||||
|
|
||||||
struct MainItemIOFeature
|
struct MainItemIOFeature {
|
||||||
{
|
|
||||||
uint8_t bmIsConstantOrData : 1;
|
uint8_t bmIsConstantOrData : 1;
|
||||||
uint8_t bmIsArrayOrVariable : 1;
|
uint8_t bmIsArrayOrVariable : 1;
|
||||||
uint8_t bmIsRelativeOrAbsolute : 1;
|
uint8_t bmIsRelativeOrAbsolute : 1;
|
||||||
|
@ -152,8 +150,7 @@ struct MainItemIOFeature
|
||||||
|
|
||||||
class HID;
|
class HID;
|
||||||
|
|
||||||
class HIDReportParser
|
class HIDReportParser {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
virtual void Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf) = 0;
|
virtual void Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf) = 0;
|
||||||
};
|
};
|
||||||
|
@ -161,8 +158,7 @@ public:
|
||||||
#define MAX_REPORT_PARSERS 2
|
#define MAX_REPORT_PARSERS 2
|
||||||
#define HID_MAX_HID_CLASS_DESCRIPTORS 5
|
#define HID_MAX_HID_CLASS_DESCRIPTORS 5
|
||||||
|
|
||||||
class HID : public USBDeviceConfig, public UsbConfigXtracter
|
class HID : public USBDeviceConfig, public UsbConfigXtracter {
|
||||||
{
|
|
||||||
protected:
|
protected:
|
||||||
USB *pUsb; // USB class instance pointer
|
USB *pUsb; // USB class instance pointer
|
||||||
uint8_t bAddress; // address
|
uint8_t bAddress; // address
|
||||||
|
@ -181,9 +177,13 @@ protected:
|
||||||
virtual HIDReportParser* GetReportParser(uint8_t id);
|
virtual HIDReportParser* GetReportParser(uint8_t id);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
HID(USB *pusb) : pUsb(pusb) {};
|
|
||||||
|
|
||||||
const USB* GetUsb() { return pUsb; };
|
HID(USB *pusb) : pUsb(pusb) {
|
||||||
|
};
|
||||||
|
|
||||||
|
const USB* GetUsb() {
|
||||||
|
return pUsb;
|
||||||
|
};
|
||||||
virtual bool SetReportParser(uint8_t id, HIDReportParser *prs);
|
virtual bool SetReportParser(uint8_t id, HIDReportParser *prs);
|
||||||
|
|
||||||
uint8_t SetProtocol(uint8_t iface, uint8_t protocol);
|
uint8_t SetProtocol(uint8_t iface, uint8_t protocol);
|
||||||
|
|
53
hidboot.cpp
53
hidboot.cpp
|
@ -16,8 +16,7 @@ e-mail : support@circuitsathome.com
|
||||||
*/
|
*/
|
||||||
#include "hidboot.h"
|
#include "hidboot.h"
|
||||||
|
|
||||||
void MouseReportParser::Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf)
|
void MouseReportParser::Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf) {
|
||||||
{
|
|
||||||
MOUSEINFO *pmi = (MOUSEINFO*) buf;
|
MOUSEINFO *pmi = (MOUSEINFO*) buf;
|
||||||
|
|
||||||
if (prevState.mouseInfo.bmLeftButton == 0 && pmi->bmLeftButton == 1)
|
if (prevState.mouseInfo.bmLeftButton == 0 && pmi->bmLeftButton == 1)
|
||||||
|
@ -41,32 +40,29 @@ void MouseReportParser::Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *bu
|
||||||
if (prevState.mouseInfo.dX != pmi->dX || prevState.mouseInfo.dY != pmi->dY)
|
if (prevState.mouseInfo.dX != pmi->dX || prevState.mouseInfo.dY != pmi->dY)
|
||||||
OnMouseMove(pmi);
|
OnMouseMove(pmi);
|
||||||
|
|
||||||
for (uint8_t i=0; i<3; i++)
|
if (len > sizeof (MOUSEINFO))
|
||||||
|
for (uint8_t i = 0; i<sizeof (MOUSEINFO); i++)
|
||||||
prevState.bInfo[i] = buf[i];
|
prevState.bInfo[i] = buf[i];
|
||||||
};
|
};
|
||||||
|
|
||||||
void KeyboardReportParser::Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf)
|
void KeyboardReportParser::Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf) {
|
||||||
{
|
|
||||||
// On error - return
|
// On error - return
|
||||||
if (buf[2] == 1)
|
if (buf[2] == 1)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
KBDINFO *pki = (KBDINFO*)buf;
|
//KBDINFO *pki = (KBDINFO*)buf;
|
||||||
|
|
||||||
for (uint8_t i=2; i<8; i++)
|
for (uint8_t i = 2; i < 8; i++) {
|
||||||
{
|
|
||||||
bool down = false;
|
bool down = false;
|
||||||
bool up = false;
|
bool up = false;
|
||||||
|
|
||||||
for (uint8_t j=2; j<8; j++)
|
for (uint8_t j = 2; j < 8; j++) {
|
||||||
{
|
|
||||||
if (buf[i] == prevState.bInfo[j] && buf[i] != 1)
|
if (buf[i] == prevState.bInfo[j] && buf[i] != 1)
|
||||||
down = true;
|
down = true;
|
||||||
if (buf[j] == prevState.bInfo[i] && prevState.bInfo[i] != 1)
|
if (buf[j] == prevState.bInfo[i] && prevState.bInfo[i] != 1)
|
||||||
up = true;
|
up = true;
|
||||||
}
|
}
|
||||||
if (!down)
|
if (!down) {
|
||||||
{
|
|
||||||
HandleLockingKeys(hid, buf[i]);
|
HandleLockingKeys(hid, buf[i]);
|
||||||
OnKeyDown(*buf, buf[i]);
|
OnKeyDown(*buf, buf[i]);
|
||||||
}
|
}
|
||||||
|
@ -77,12 +73,10 @@ void KeyboardReportParser::Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t
|
||||||
prevState.bInfo[i] = buf[i];
|
prevState.bInfo[i] = buf[i];
|
||||||
};
|
};
|
||||||
|
|
||||||
uint8_t KeyboardReportParser::HandleLockingKeys(HID *hid, uint8_t key)
|
uint8_t KeyboardReportParser::HandleLockingKeys(HID *hid, uint8_t key) {
|
||||||
{
|
|
||||||
uint8_t old_keys = kbdLockingKeys.bLeds;
|
uint8_t old_keys = kbdLockingKeys.bLeds;
|
||||||
|
|
||||||
switch (key)
|
switch (key) {
|
||||||
{
|
|
||||||
case KEY_NUM_LOCK:
|
case KEY_NUM_LOCK:
|
||||||
kbdLockingKeys.kbdLeds.bmNumLock = ~kbdLockingKeys.kbdLeds.bmNumLock;
|
kbdLockingKeys.kbdLeds.bmNumLock = ~kbdLockingKeys.kbdLeds.bmNumLock;
|
||||||
break;
|
break;
|
||||||
|
@ -105,13 +99,11 @@ const uint8_t KeyboardReportParser::symKeysUp[] PROGMEM = { '_', '+', '{', '}',
|
||||||
const uint8_t KeyboardReportParser::symKeysLo[] PROGMEM = {'-', '=', '[', ']', '\\', ' ', ';', '\'', '`', ',', '.', '/'};
|
const uint8_t KeyboardReportParser::symKeysLo[] PROGMEM = {'-', '=', '[', ']', '\\', ' ', ';', '\'', '`', ',', '.', '/'};
|
||||||
const uint8_t KeyboardReportParser::padKeys[] PROGMEM = {'/', '*', '-', '+', 0x13};
|
const uint8_t KeyboardReportParser::padKeys[] PROGMEM = {'/', '*', '-', '+', 0x13};
|
||||||
|
|
||||||
uint8_t KeyboardReportParser::OemToAscii(uint8_t mod, uint8_t key)
|
uint8_t KeyboardReportParser::OemToAscii(uint8_t mod, uint8_t key) {
|
||||||
{
|
|
||||||
uint8_t shift = (mod & 0x22);
|
uint8_t shift = (mod & 0x22);
|
||||||
|
|
||||||
// [a-z]
|
// [a-z]
|
||||||
if (key > 0x03 && key < 0x1e)
|
if (key > 0x03 && key < 0x1e) {
|
||||||
{
|
|
||||||
// Upper case letters
|
// Upper case letters
|
||||||
if ((kbdLockingKeys.kbdLeds.bmCapsLock == 0 && (mod & 2)) ||
|
if ((kbdLockingKeys.kbdLeds.bmCapsLock == 0 && (mod & 2)) ||
|
||||||
(kbdLockingKeys.kbdLeds.bmCapsLock == 1 && (mod & 2) == 0))
|
(kbdLockingKeys.kbdLeds.bmCapsLock == 1 && (mod & 2) == 0))
|
||||||
|
@ -120,29 +112,22 @@ uint8_t KeyboardReportParser::OemToAscii(uint8_t mod, uint8_t key)
|
||||||
// Lower case letters
|
// Lower case letters
|
||||||
else
|
else
|
||||||
return (key - 4 + 'a');
|
return (key - 4 + 'a');
|
||||||
}
|
} // Numbers
|
||||||
// Numbers
|
else if (key > 0x1d && key < 0x27) {
|
||||||
else if (key > 0x1d && key < 0x27)
|
|
||||||
{
|
|
||||||
if (shift)
|
if (shift)
|
||||||
return ((uint8_t) pgm_read_byte(&numKeys[key - 0x1e]));
|
return ((uint8_t) pgm_read_byte(&numKeys[key - 0x1e]));
|
||||||
else
|
else
|
||||||
return (key - 0x1e + '1');
|
return (key - 0x1e + '1');
|
||||||
}
|
} // Keypad Numbers
|
||||||
// Keypad Numbers
|
else if (key > 0x58 && key < 0x62) {
|
||||||
else if (key > 0x58 && key < 0x62)
|
|
||||||
{
|
|
||||||
if (kbdLockingKeys.kbdLeds.bmNumLock == 1)
|
if (kbdLockingKeys.kbdLeds.bmNumLock == 1)
|
||||||
return (key - 0x59 + '1');
|
return (key - 0x59 + '1');
|
||||||
}
|
} else if (key > 0x2c && key < 0x39)
|
||||||
else if (key > 0x2c && key < 0x39)
|
|
||||||
return ((shift) ? (uint8_t) pgm_read_byte(&symKeysUp[key - 0x2d]) : (uint8_t) pgm_read_byte(&symKeysLo[key - 0x2d]));
|
return ((shift) ? (uint8_t) pgm_read_byte(&symKeysUp[key - 0x2d]) : (uint8_t) pgm_read_byte(&symKeysLo[key - 0x2d]));
|
||||||
else if (key > 0x53 && key < 0x59)
|
else if (key > 0x53 && key < 0x59)
|
||||||
return (uint8_t) pgm_read_byte(&padKeys[key - 0x54]);
|
return (uint8_t) pgm_read_byte(&padKeys[key - 0x54]);
|
||||||
else
|
else {
|
||||||
{
|
switch (key) {
|
||||||
switch (key)
|
|
||||||
{
|
|
||||||
case KEY_SPACE: return (0x20);
|
case KEY_SPACE: return (0x20);
|
||||||
case KEY_ENTER: return (0x13);
|
case KEY_ENTER: return (0x13);
|
||||||
case KEY_ZERO: return ((shift) ? ')': '0');
|
case KEY_ZERO: return ((shift) ? ')': '0');
|
||||||
|
|
151
hidboot.h
151
hidboot.h
|
@ -44,10 +44,9 @@ e-mail : support@circuitsathome.com
|
||||||
#define KEY_ENTER 0x28
|
#define KEY_ENTER 0x28
|
||||||
#define KEY_PERIOD 0x63
|
#define KEY_PERIOD 0x63
|
||||||
|
|
||||||
struct MOUSEINFO
|
struct MOUSEINFO {
|
||||||
{
|
|
||||||
struct
|
struct {
|
||||||
{
|
|
||||||
uint8_t bmLeftButton : 1;
|
uint8_t bmLeftButton : 1;
|
||||||
uint8_t bmRightButton : 1;
|
uint8_t bmRightButton : 1;
|
||||||
uint8_t bmMiddleButton : 1;
|
uint8_t bmMiddleButton : 1;
|
||||||
|
@ -57,29 +56,41 @@ struct MOUSEINFO
|
||||||
int8_t dY;
|
int8_t dY;
|
||||||
};
|
};
|
||||||
|
|
||||||
class MouseReportParser : public HIDReportParser
|
class MouseReportParser : public HIDReportParser {
|
||||||
{
|
|
||||||
union
|
union {
|
||||||
{
|
|
||||||
MOUSEINFO mouseInfo;
|
MOUSEINFO mouseInfo;
|
||||||
uint8_t bInfo[3];
|
uint8_t bInfo[sizeof (MOUSEINFO)];
|
||||||
} prevState;
|
} prevState;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual void Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf);
|
virtual void Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void OnMouseMove (MOUSEINFO *mi) {};
|
|
||||||
virtual void OnLeftButtonUp (MOUSEINFO *mi) {};
|
virtual void OnMouseMove(MOUSEINFO *mi) {
|
||||||
virtual void OnLeftButtonDown (MOUSEINFO *mi) {};
|
|
||||||
virtual void OnRightButtonUp (MOUSEINFO *mi) {};
|
|
||||||
virtual void OnRightButtonDown (MOUSEINFO *mi) {};
|
|
||||||
virtual void OnMiddleButtonUp (MOUSEINFO *mi) {};
|
|
||||||
virtual void OnMiddleButtonDown (MOUSEINFO *mi) {};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MODIFIERKEYS
|
virtual void OnLeftButtonUp(MOUSEINFO *mi) {
|
||||||
{
|
};
|
||||||
|
|
||||||
|
virtual void OnLeftButtonDown(MOUSEINFO *mi) {
|
||||||
|
};
|
||||||
|
|
||||||
|
virtual void OnRightButtonUp(MOUSEINFO *mi) {
|
||||||
|
};
|
||||||
|
|
||||||
|
virtual void OnRightButtonDown(MOUSEINFO *mi) {
|
||||||
|
};
|
||||||
|
|
||||||
|
virtual void OnMiddleButtonUp(MOUSEINFO *mi) {
|
||||||
|
};
|
||||||
|
|
||||||
|
virtual void OnMiddleButtonDown(MOUSEINFO *mi) {
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MODIFIERKEYS {
|
||||||
uint8_t bmLeftCtrl : 1;
|
uint8_t bmLeftCtrl : 1;
|
||||||
uint8_t bmLeftShift : 1;
|
uint8_t bmLeftShift : 1;
|
||||||
uint8_t bmLeftAlt : 1;
|
uint8_t bmLeftAlt : 1;
|
||||||
|
@ -90,10 +101,9 @@ struct MODIFIERKEYS
|
||||||
uint8_t bmRightGUI : 1;
|
uint8_t bmRightGUI : 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct KBDINFO
|
struct KBDINFO {
|
||||||
{
|
|
||||||
struct
|
struct {
|
||||||
{
|
|
||||||
uint8_t bmLeftCtrl : 1;
|
uint8_t bmLeftCtrl : 1;
|
||||||
uint8_t bmLeftShift : 1;
|
uint8_t bmLeftShift : 1;
|
||||||
uint8_t bmLeftAlt : 1;
|
uint8_t bmLeftAlt : 1;
|
||||||
|
@ -107,8 +117,7 @@ struct KBDINFO
|
||||||
uint8_t Keys[6];
|
uint8_t Keys[6];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct KBDLEDS
|
struct KBDLEDS {
|
||||||
{
|
|
||||||
uint8_t bmNumLock : 1;
|
uint8_t bmNumLock : 1;
|
||||||
uint8_t bmCapsLock : 1;
|
uint8_t bmCapsLock : 1;
|
||||||
uint8_t bmScrollLock : 1;
|
uint8_t bmScrollLock : 1;
|
||||||
|
@ -121,22 +130,20 @@ struct KBDLEDS
|
||||||
#define KEY_CAPS_LOCK 0x39
|
#define KEY_CAPS_LOCK 0x39
|
||||||
#define KEY_SCROLL_LOCK 0x47
|
#define KEY_SCROLL_LOCK 0x47
|
||||||
|
|
||||||
class KeyboardReportParser : public HIDReportParser
|
class KeyboardReportParser : public HIDReportParser {
|
||||||
{
|
|
||||||
static const uint8_t numKeys[];
|
static const uint8_t numKeys[];
|
||||||
static const uint8_t symKeysUp[];
|
static const uint8_t symKeysUp[];
|
||||||
static const uint8_t symKeysLo[];
|
static const uint8_t symKeysLo[];
|
||||||
static const uint8_t padKeys[];
|
static const uint8_t padKeys[];
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
union
|
|
||||||
{
|
union {
|
||||||
KBDINFO kbdInfo;
|
KBDINFO kbdInfo;
|
||||||
uint8_t bInfo[sizeof (KBDINFO)];
|
uint8_t bInfo[sizeof (KBDINFO)];
|
||||||
} prevState;
|
} prevState;
|
||||||
|
|
||||||
union
|
union {
|
||||||
{
|
|
||||||
KBDLEDS kbdLeds;
|
KBDLEDS kbdLeds;
|
||||||
uint8_t bLeds;
|
uint8_t bLeds;
|
||||||
} kbdLockingKeys;
|
} kbdLockingKeys;
|
||||||
|
@ -144,15 +151,21 @@ protected:
|
||||||
uint8_t OemToAscii(uint8_t mod, uint8_t key);
|
uint8_t OemToAscii(uint8_t mod, uint8_t key);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
KeyboardReportParser() { kbdLockingKeys.bLeds = 0; };
|
|
||||||
|
KeyboardReportParser() {
|
||||||
|
kbdLockingKeys.bLeds = 0;
|
||||||
|
};
|
||||||
|
|
||||||
virtual void Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf);
|
virtual void Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
uint8_t HandleLockingKeys(HID* hid, uint8_t key);
|
uint8_t HandleLockingKeys(HID* hid, uint8_t key);
|
||||||
|
|
||||||
virtual void OnKeyDown (uint8_t mod, uint8_t key) {};
|
virtual void OnKeyDown(uint8_t mod, uint8_t key) {
|
||||||
virtual void OnKeyUp (uint8_t mod, uint8_t key) {};
|
};
|
||||||
|
|
||||||
|
virtual void OnKeyUp(uint8_t mod, uint8_t key) {
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
#define totalEndpoints 2
|
#define totalEndpoints 2
|
||||||
|
@ -175,18 +188,26 @@ class HIDBoot : public HID //public USBDeviceConfig, public UsbConfigXtracter
|
||||||
|
|
||||||
void Initialize();
|
void Initialize();
|
||||||
|
|
||||||
virtual HIDReportParser* GetReportParser(uint8_t id) { return pRptParser; };
|
virtual HIDReportParser* GetReportParser(uint8_t id) {
|
||||||
|
return pRptParser;
|
||||||
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
HIDBoot(USB *p);
|
HIDBoot(USB *p);
|
||||||
|
|
||||||
virtual bool SetReportParser(uint8_t id, HIDReportParser *prs) { pRptParser = prs; };
|
virtual bool SetReportParser(uint8_t id, HIDReportParser *prs) {
|
||||||
|
pRptParser = prs;
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
// USBDeviceConfig implementation
|
// USBDeviceConfig implementation
|
||||||
virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed);
|
virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed);
|
||||||
virtual uint8_t Release();
|
virtual uint8_t Release();
|
||||||
virtual uint8_t Poll();
|
virtual uint8_t Poll();
|
||||||
virtual uint8_t GetAddress() { return bAddress; };
|
|
||||||
|
virtual uint8_t GetAddress() {
|
||||||
|
return bAddress;
|
||||||
|
};
|
||||||
|
|
||||||
// UsbConfigXtracter implementation
|
// UsbConfigXtracter implementation
|
||||||
virtual void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep);
|
virtual void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep);
|
||||||
|
@ -197,8 +218,7 @@ HIDBoot<BOOT_PROTOCOL>::HIDBoot(USB *p) :
|
||||||
HID(p),
|
HID(p),
|
||||||
qNextPollTime(0),
|
qNextPollTime(0),
|
||||||
bPollEnable(false),
|
bPollEnable(false),
|
||||||
pRptParser(NULL)
|
pRptParser(NULL) {
|
||||||
{
|
|
||||||
Initialize();
|
Initialize();
|
||||||
|
|
||||||
if (pUsb)
|
if (pUsb)
|
||||||
|
@ -206,10 +226,8 @@ HIDBoot<BOOT_PROTOCOL>::HIDBoot(USB *p) :
|
||||||
}
|
}
|
||||||
|
|
||||||
template <const uint8_t BOOT_PROTOCOL>
|
template <const uint8_t BOOT_PROTOCOL>
|
||||||
void HIDBoot<BOOT_PROTOCOL>::Initialize()
|
void HIDBoot<BOOT_PROTOCOL>::Initialize() {
|
||||||
{
|
for (uint8_t i = 0; i < totalEndpoints; i++) {
|
||||||
for(uint8_t i=0; i<totalEndpoints; i++)
|
|
||||||
{
|
|
||||||
epInfo[i].epAddr = 0;
|
epInfo[i].epAddr = 0;
|
||||||
epInfo[i].maxPktSize = (i) ? 0 : 8;
|
epInfo[i].maxPktSize = (i) ? 0 : 8;
|
||||||
epInfo[i].epAttribs = 0;
|
epInfo[i].epAttribs = 0;
|
||||||
|
@ -221,8 +239,7 @@ void HIDBoot<BOOT_PROTOCOL>::Initialize()
|
||||||
}
|
}
|
||||||
|
|
||||||
template <const uint8_t BOOT_PROTOCOL>
|
template <const uint8_t BOOT_PROTOCOL>
|
||||||
uint8_t HIDBoot<BOOT_PROTOCOL>::Init(uint8_t parent, uint8_t port, bool lowspeed)
|
uint8_t HIDBoot<BOOT_PROTOCOL>::Init(uint8_t parent, uint8_t port, bool lowspeed) {
|
||||||
{
|
|
||||||
const uint8_t constBufSize = sizeof (USB_DEVICE_DESCRIPTOR);
|
const uint8_t constBufSize = sizeof (USB_DEVICE_DESCRIPTOR);
|
||||||
|
|
||||||
uint8_t buf[constBufSize];
|
uint8_t buf[constBufSize];
|
||||||
|
@ -248,8 +265,7 @@ uint8_t HIDBoot<BOOT_PROTOCOL>::Init(uint8_t parent, uint8_t port, bool lowspeed
|
||||||
if (!p)
|
if (!p)
|
||||||
return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
|
return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
|
||||||
|
|
||||||
if (!p->epinfo)
|
if (!p->epinfo) {
|
||||||
{
|
|
||||||
USBTRACE("epinfo\r\n");
|
USBTRACE("epinfo\r\n");
|
||||||
return USB_ERROR_EPINFO_IS_NULL;
|
return USB_ERROR_EPINFO_IS_NULL;
|
||||||
}
|
}
|
||||||
|
@ -268,8 +284,7 @@ uint8_t HIDBoot<BOOT_PROTOCOL>::Init(uint8_t parent, uint8_t port, bool lowspeed
|
||||||
if (!rcode)
|
if (!rcode)
|
||||||
len = (buf[0] > constBufSize) ? constBufSize : buf[0];
|
len = (buf[0] > constBufSize) ? constBufSize : buf[0];
|
||||||
|
|
||||||
if( rcode )
|
if (rcode) {
|
||||||
{
|
|
||||||
// Restore p->epinfo
|
// Restore p->epinfo
|
||||||
p->epinfo = oldep_ptr;
|
p->epinfo = oldep_ptr;
|
||||||
|
|
||||||
|
@ -291,8 +306,7 @@ uint8_t HIDBoot<BOOT_PROTOCOL>::Init(uint8_t parent, uint8_t port, bool lowspeed
|
||||||
// Assign new address to the device
|
// Assign new address to the device
|
||||||
rcode = pUsb->setAddr(0, 0, bAddress);
|
rcode = pUsb->setAddr(0, 0, bAddress);
|
||||||
|
|
||||||
if (rcode)
|
if (rcode) {
|
||||||
{
|
|
||||||
p->lowspeed = false;
|
p->lowspeed = false;
|
||||||
addrPool.FreeAddress(bAddress);
|
addrPool.FreeAddress(bAddress);
|
||||||
bAddress = 0;
|
bAddress = 0;
|
||||||
|
@ -327,16 +341,13 @@ uint8_t HIDBoot<BOOT_PROTOCOL>::Init(uint8_t parent, uint8_t port, bool lowspeed
|
||||||
|
|
||||||
//USBTRACE2("NC:", num_of_conf);
|
//USBTRACE2("NC:", num_of_conf);
|
||||||
|
|
||||||
for (uint8_t i=0; i<num_of_conf; i++)
|
for (uint8_t i = 0; i < num_of_conf; i++) {
|
||||||
{
|
|
||||||
//HexDumper<USBReadParser, uint16_t, uint16_t> HexDump;
|
|
||||||
ConfigDescParser<
|
ConfigDescParser<
|
||||||
USB_CLASS_HID,
|
USB_CLASS_HID,
|
||||||
HID_BOOT_INTF_SUBCLASS,
|
HID_BOOT_INTF_SUBCLASS,
|
||||||
BOOT_PROTOCOL,
|
BOOT_PROTOCOL,
|
||||||
CP_MASK_COMPARE_ALL> confDescrParser(this);
|
CP_MASK_COMPARE_ALL> confDescrParser(this);
|
||||||
|
|
||||||
//rcode = pUsb->getConfDescr(bAddress, 0, i, &HexDump);
|
|
||||||
rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser);
|
rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser);
|
||||||
|
|
||||||
if (bNumEP > 1)
|
if (bNumEP > 1)
|
||||||
|
@ -367,8 +378,7 @@ uint8_t HIDBoot<BOOT_PROTOCOL>::Init(uint8_t parent, uint8_t port, bool lowspeed
|
||||||
if (rcode)
|
if (rcode)
|
||||||
goto FailSetProtocol;
|
goto FailSetProtocol;
|
||||||
|
|
||||||
if (BOOT_PROTOCOL == 1)
|
if (BOOT_PROTOCOL == 1) {
|
||||||
{
|
|
||||||
rcode = SetIdle(bIfaceNum, 0, 0);
|
rcode = SetIdle(bIfaceNum, 0, 0);
|
||||||
|
|
||||||
if (rcode)
|
if (rcode)
|
||||||
|
@ -404,29 +414,25 @@ FailSetConfDescr:
|
||||||
goto Fail;
|
goto Fail;
|
||||||
|
|
||||||
Fail:
|
Fail:
|
||||||
Serial.println(rcode, HEX);
|
PrintHex<uint8_t > (rcode, 0x80);
|
||||||
|
Notify(PSTR("\n"), 0x80);
|
||||||
|
// Serial.println(rcode, HEX);
|
||||||
Release();
|
Release();
|
||||||
return rcode;
|
return rcode;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <const uint8_t BOOT_PROTOCOL>
|
template <const uint8_t BOOT_PROTOCOL>
|
||||||
void HIDBoot<BOOT_PROTOCOL>::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *pep)
|
void HIDBoot<BOOT_PROTOCOL>::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 the first configuration satisfies, the others are not concidered.
|
||||||
if (bNumEP > 1 && conf != bConfNum)
|
if (bNumEP > 1 && conf != bConfNum)
|
||||||
return;
|
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;
|
bConfNum = conf;
|
||||||
bIfaceNum = iface;
|
bIfaceNum = iface;
|
||||||
|
|
||||||
uint8_t index;
|
uint8_t index;
|
||||||
|
|
||||||
if ((pep->bmAttributes & 0x03) == 3 && (pep->bEndpointAddress & 0x80) == 0x80)
|
if ((pep->bmAttributes & 0x03) == 3 && (pep->bEndpointAddress & 0x80) == 0x80) {
|
||||||
{
|
|
||||||
index = epInterruptInIndex;
|
index = epInterruptInIndex;
|
||||||
|
|
||||||
// Fill in the endpoint info structure
|
// Fill in the endpoint info structure
|
||||||
|
@ -435,15 +441,11 @@ void HIDBoot<BOOT_PROTOCOL>::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t
|
||||||
epInfo[index].epAttribs = 0;
|
epInfo[index].epAttribs = 0;
|
||||||
|
|
||||||
bNumEP++;
|
bNumEP++;
|
||||||
|
|
||||||
//PrintEndpointDescriptor(pep);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template <const uint8_t BOOT_PROTOCOL>
|
template <const uint8_t BOOT_PROTOCOL>
|
||||||
uint8_t HIDBoot<BOOT_PROTOCOL>::Release()
|
uint8_t HIDBoot<BOOT_PROTOCOL>::Release() {
|
||||||
{
|
|
||||||
pUsb->GetAddressPool().FreeAddress(bAddress);
|
pUsb->GetAddressPool().FreeAddress(bAddress);
|
||||||
|
|
||||||
bConfNum = 0;
|
bConfNum = 0;
|
||||||
|
@ -456,15 +458,13 @@ uint8_t HIDBoot<BOOT_PROTOCOL>::Release()
|
||||||
}
|
}
|
||||||
|
|
||||||
template <const uint8_t BOOT_PROTOCOL>
|
template <const uint8_t BOOT_PROTOCOL>
|
||||||
uint8_t HIDBoot<BOOT_PROTOCOL>::Poll()
|
uint8_t HIDBoot<BOOT_PROTOCOL>::Poll() {
|
||||||
{
|
|
||||||
uint8_t rcode = 0;
|
uint8_t rcode = 0;
|
||||||
|
|
||||||
if (!bPollEnable)
|
if (!bPollEnable)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (qNextPollTime <= millis())
|
if (qNextPollTime <= millis()) {
|
||||||
{
|
|
||||||
qNextPollTime = millis() + 10;
|
qNextPollTime = millis() + 10;
|
||||||
|
|
||||||
const uint8_t const_buff_len = 16;
|
const uint8_t const_buff_len = 16;
|
||||||
|
@ -474,8 +474,7 @@ uint8_t HIDBoot<BOOT_PROTOCOL>::Poll()
|
||||||
|
|
||||||
uint8_t rcode = pUsb->inTransfer(bAddress, epInfo[epInterruptInIndex].epAddr, &read, buf);
|
uint8_t rcode = pUsb->inTransfer(bAddress, epInfo[epInterruptInIndex].epAddr, &read, buf);
|
||||||
|
|
||||||
if (rcode)
|
if (rcode) {
|
||||||
{
|
|
||||||
if (rcode != hrNAK)
|
if (rcode != hrNAK)
|
||||||
USBTRACE2("Poll:", rcode);
|
USBTRACE2("Poll:", rcode);
|
||||||
return rcode;
|
return rcode;
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -37,8 +37,7 @@ e-mail : support@circuitsathome.com
|
||||||
#include "confdescparser.h"
|
#include "confdescparser.h"
|
||||||
#include "hid.h"
|
#include "hid.h"
|
||||||
|
|
||||||
class ReportDescParserBase : public USBReadParser
|
class ReportDescParserBase : public USBReadParser {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
typedef void (*UsagePageFunc)(uint16_t usage);
|
typedef void (*UsagePageFunc)(uint16_t usage);
|
||||||
|
|
||||||
|
@ -62,57 +61,57 @@ public:
|
||||||
|
|
||||||
static void PrintItemTitle(uint8_t prefix);
|
static void PrintItemTitle(uint8_t prefix);
|
||||||
|
|
||||||
static const char *usagePageTitles0[];
|
static const char * const usagePageTitles0[];
|
||||||
static const char *usagePageTitles1[];
|
static const char * const usagePageTitles1[];
|
||||||
static const char *genDesktopTitles0[];
|
static const char * const genDesktopTitles0[];
|
||||||
static const char *genDesktopTitles1[];
|
static const char * const genDesktopTitles1[];
|
||||||
static const char *genDesktopTitles2[];
|
static const char * const genDesktopTitles2[];
|
||||||
static const char *genDesktopTitles3[];
|
static const char * const genDesktopTitles3[];
|
||||||
static const char *genDesktopTitles4[];
|
static const char * const genDesktopTitles4[];
|
||||||
static const char *simuTitles0[];
|
static const char * const simuTitles0[];
|
||||||
static const char *simuTitles1[];
|
static const char * const simuTitles1[];
|
||||||
static const char *simuTitles2[];
|
static const char * const simuTitles2[];
|
||||||
static const char *vrTitles0[];
|
static const char * const vrTitles0[];
|
||||||
static const char *vrTitles1[];
|
static const char * const vrTitles1[];
|
||||||
static const char *sportsCtrlTitles0[];
|
static const char * const sportsCtrlTitles0[];
|
||||||
static const char *sportsCtrlTitles1[];
|
static const char * const sportsCtrlTitles1[];
|
||||||
static const char *sportsCtrlTitles2[];
|
static const char * const sportsCtrlTitles2[];
|
||||||
static const char *gameTitles0[];
|
static const char * const gameTitles0[];
|
||||||
static const char *gameTitles1[];
|
static const char * const gameTitles1[];
|
||||||
static const char *genDevCtrlTitles[];
|
static const char * const genDevCtrlTitles[];
|
||||||
static const char *ledTitles[];
|
static const char * const ledTitles[];
|
||||||
static const char *telTitles0[];
|
static const char * const telTitles0[];
|
||||||
static const char *telTitles1[];
|
static const char * const telTitles1[];
|
||||||
static const char *telTitles2[];
|
static const char * const telTitles2[];
|
||||||
static const char *telTitles3[];
|
static const char * const telTitles3[];
|
||||||
static const char *telTitles4[];
|
static const char * const telTitles4[];
|
||||||
static const char *telTitles5[];
|
static const char * const telTitles5[];
|
||||||
static const char *consTitles0[];
|
static const char * const consTitles0[];
|
||||||
static const char *consTitles1[];
|
static const char * const consTitles1[];
|
||||||
static const char *consTitles2[];
|
static const char * const consTitles2[];
|
||||||
static const char *consTitles3[];
|
static const char * const consTitles3[];
|
||||||
static const char *consTitles4[];
|
static const char * const consTitles4[];
|
||||||
static const char *consTitles5[];
|
static const char * const consTitles5[];
|
||||||
static const char *consTitles6[];
|
static const char * const consTitles6[];
|
||||||
static const char *consTitles7[];
|
static const char * const consTitles7[];
|
||||||
static const char *consTitles8[];
|
static const char * const consTitles8[];
|
||||||
static const char *consTitles9[];
|
static const char * const consTitles9[];
|
||||||
static const char *consTitlesA[];
|
static const char * const consTitlesA[];
|
||||||
static const char *consTitlesB[];
|
static const char * const consTitlesB[];
|
||||||
static const char *consTitlesC[];
|
static const char * const consTitlesC[];
|
||||||
static const char *consTitlesD[];
|
static const char * const consTitlesD[];
|
||||||
static const char *consTitlesE[];
|
static const char * const consTitlesE[];
|
||||||
static const char *digitTitles0[];
|
static const char * const digitTitles0[];
|
||||||
static const char *digitTitles1[];
|
static const char * const digitTitles1[];
|
||||||
static const char *digitTitles2[];
|
static const char * const digitTitles2[];
|
||||||
static const char *aplphanumTitles0[];
|
static const char * const aplphanumTitles0[];
|
||||||
static const char *aplphanumTitles1[];
|
static const char * const aplphanumTitles1[];
|
||||||
static const char *aplphanumTitles2[];
|
static const char * const aplphanumTitles2[];
|
||||||
static const char *medInstrTitles0[];
|
static const char * const medInstrTitles0[];
|
||||||
static const char *medInstrTitles1[];
|
static const char * const medInstrTitles1[];
|
||||||
static const char *medInstrTitles2[];
|
static const char * const medInstrTitles2[];
|
||||||
static const char *medInstrTitles3[];
|
static const char * const medInstrTitles3[];
|
||||||
static const char *medInstrTitles4[];
|
static const char * const medInstrTitles4[];
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static UsagePageFunc usagePageFunctions[];
|
static UsagePageFunc usagePageFunctions[];
|
||||||
|
@ -138,14 +137,14 @@ protected:
|
||||||
void SetUsagePage(uint16_t page);
|
void SetUsagePage(uint16_t page);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
ReportDescParserBase() :
|
ReportDescParserBase() :
|
||||||
itemParseState(0),
|
itemParseState(0),
|
||||||
itemSize(0),
|
itemSize(0),
|
||||||
itemPrefix(0),
|
itemPrefix(0),
|
||||||
rptSize(0),
|
rptSize(0),
|
||||||
rptCount(0),
|
rptCount(0),
|
||||||
pfUsage(NULL)
|
pfUsage(NULL) {
|
||||||
{
|
|
||||||
theBuffer.pValue = varBuffer;
|
theBuffer.pValue = varBuffer;
|
||||||
valParser.Initialize(&theBuffer);
|
valParser.Initialize(&theBuffer);
|
||||||
theSkipper.Initialize(&theBuffer);
|
theSkipper.Initialize(&theBuffer);
|
||||||
|
@ -153,20 +152,17 @@ public:
|
||||||
|
|
||||||
virtual void Parse(const uint16_t len, const uint8_t *pbuf, const uint16_t &offset);
|
virtual void Parse(const uint16_t len, const uint8_t *pbuf, const uint16_t &offset);
|
||||||
|
|
||||||
enum
|
enum {
|
||||||
{
|
|
||||||
enErrorSuccess = 0
|
enErrorSuccess = 0
|
||||||
, enErrorIncomplete // value or record is partialy read in buffer
|
, enErrorIncomplete // value or record is partialy read in buffer
|
||||||
, enErrorBufferTooSmall
|
, enErrorBufferTooSmall
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
class ReportDescParser : public ReportDescParserBase
|
class ReportDescParser : public ReportDescParserBase {
|
||||||
{
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class ReportDescParser2 : public ReportDescParserBase
|
class ReportDescParser2 : public ReportDescParserBase {
|
||||||
{
|
|
||||||
uint8_t rptId; // Report ID
|
uint8_t rptId; // Report ID
|
||||||
uint8_t useMin; // Usage Minimum
|
uint8_t useMin; // Usage Minimum
|
||||||
uint8_t useMax; // Usage Maximum
|
uint8_t useMax; // Usage Maximum
|
||||||
|
@ -181,13 +177,13 @@ protected:
|
||||||
virtual uint8_t ParseItem(uint8_t **pp, uint16_t *pcntdn);
|
virtual uint8_t ParseItem(uint8_t **pp, uint16_t *pcntdn);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
ReportDescParser2(uint16_t len, uint8_t *pbuf) :
|
ReportDescParser2(uint16_t len, uint8_t *pbuf) :
|
||||||
ReportDescParserBase(), bLen(len), pBuf(pbuf), rptId(0), useMin(0), useMax(0), fieldCount(0)
|
ReportDescParserBase(), rptId(0), useMin(0), useMax(0), fieldCount(0), pBuf(pbuf), bLen(len) {
|
||||||
{};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
class UniversalReportParser : public HIDReportParser
|
class UniversalReportParser : public HIDReportParser {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
virtual void Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf);
|
virtual void Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf);
|
||||||
};
|
};
|
||||||
|
|
126
hiduniversal.cpp
126
hiduniversal.cpp
|
@ -4,20 +4,16 @@ HIDUniversal::HIDUniversal(USB *p) :
|
||||||
HID(p),
|
HID(p),
|
||||||
qNextPollTime(0),
|
qNextPollTime(0),
|
||||||
bPollEnable(false),
|
bPollEnable(false),
|
||||||
bHasReportId(false)
|
bHasReportId(false) {
|
||||||
{
|
|
||||||
Initialize();
|
Initialize();
|
||||||
|
|
||||||
if (pUsb)
|
if (pUsb)
|
||||||
pUsb->RegisterDeviceClass(this);
|
pUsb->RegisterDeviceClass(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t HIDUniversal::GetHidClassDescrLen(uint8_t type, uint8_t num)
|
uint16_t HIDUniversal::GetHidClassDescrLen(uint8_t type, uint8_t num) {
|
||||||
{
|
for (uint8_t i = 0, n = 0; i < HID_MAX_HID_CLASS_DESCRIPTORS; i++) {
|
||||||
for (uint8_t i=0, n=0; i<HID_MAX_HID_CLASS_DESCRIPTORS; i++)
|
if (descrInfo[i].bDescrType == type) {
|
||||||
{
|
|
||||||
if (descrInfo[i].bDescrType == type)
|
|
||||||
{
|
|
||||||
if (n == num)
|
if (n == num)
|
||||||
return descrInfo[i].wDescriptorLength;
|
return descrInfo[i].wDescriptorLength;
|
||||||
n++;
|
n++;
|
||||||
|
@ -26,28 +22,23 @@ uint16_t HIDUniversal::GetHidClassDescrLen(uint8_t type, uint8_t num)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void HIDUniversal::Initialize()
|
void HIDUniversal::Initialize() {
|
||||||
{
|
for (uint8_t i = 0; i < MAX_REPORT_PARSERS; i++) {
|
||||||
for (uint8_t i=0; i<MAX_REPORT_PARSERS; i++)
|
|
||||||
{
|
|
||||||
rptParsers[i].rptId = 0;
|
rptParsers[i].rptId = 0;
|
||||||
rptParsers[i].rptParser = NULL;
|
rptParsers[i].rptParser = NULL;
|
||||||
}
|
}
|
||||||
for (uint8_t i=0; i<HID_MAX_HID_CLASS_DESCRIPTORS; i++)
|
for (uint8_t i = 0; i < HID_MAX_HID_CLASS_DESCRIPTORS; i++) {
|
||||||
{
|
|
||||||
descrInfo[i].bDescrType = 0;
|
descrInfo[i].bDescrType = 0;
|
||||||
descrInfo[i].wDescriptorLength = 0;
|
descrInfo[i].wDescriptorLength = 0;
|
||||||
}
|
}
|
||||||
for (uint8_t i=0; i<maxHidInterfaces; i++)
|
for (uint8_t i = 0; i < maxHidInterfaces; i++) {
|
||||||
{
|
|
||||||
hidInterfaces[i].bmInterface = 0;
|
hidInterfaces[i].bmInterface = 0;
|
||||||
hidInterfaces[i].bmProtocol = 0;
|
hidInterfaces[i].bmProtocol = 0;
|
||||||
|
|
||||||
for (uint8_t j = 0; j < maxEpPerInterface; j++)
|
for (uint8_t j = 0; j < maxEpPerInterface; j++)
|
||||||
hidInterfaces[i].epIndex[j] = 0;
|
hidInterfaces[i].epIndex[j] = 0;
|
||||||
}
|
}
|
||||||
for(uint8_t i=0; i<totalEndpoints; i++)
|
for (uint8_t i = 0; i < totalEndpoints; i++) {
|
||||||
{
|
|
||||||
epInfo[i].epAddr = 0;
|
epInfo[i].epAddr = 0;
|
||||||
epInfo[i].maxPktSize = (i) ? 0 : 8;
|
epInfo[i].maxPktSize = (i) ? 0 : 8;
|
||||||
epInfo[i].epAttribs = 0;
|
epInfo[i].epAttribs = 0;
|
||||||
|
@ -60,12 +51,9 @@ void HIDUniversal::Initialize()
|
||||||
ZeroMemory(constBuffLen, prevBuf);
|
ZeroMemory(constBuffLen, prevBuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HIDUniversal::SetReportParser(uint8_t id, HIDReportParser *prs)
|
bool HIDUniversal::SetReportParser(uint8_t id, HIDReportParser *prs) {
|
||||||
{
|
for (uint8_t i = 0; i < MAX_REPORT_PARSERS; i++) {
|
||||||
for (uint8_t i=0; i<MAX_REPORT_PARSERS; i++)
|
if (rptParsers[i].rptId == 0 && rptParsers[i].rptParser == NULL) {
|
||||||
{
|
|
||||||
if (rptParsers[i].rptId == 0 && rptParsers[i].rptParser == NULL)
|
|
||||||
{
|
|
||||||
rptParsers[i].rptId = id;
|
rptParsers[i].rptId = id;
|
||||||
rptParsers[i].rptParser = prs;
|
rptParsers[i].rptParser = prs;
|
||||||
return true;
|
return true;
|
||||||
|
@ -74,21 +62,18 @@ bool HIDUniversal::SetReportParser(uint8_t id, HIDReportParser *prs)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
HIDReportParser* HIDUniversal::GetReportParser(uint8_t id)
|
HIDReportParser* HIDUniversal::GetReportParser(uint8_t id) {
|
||||||
{
|
|
||||||
if (!bHasReportId)
|
if (!bHasReportId)
|
||||||
return ((rptParsers[0].rptParser) ? rptParsers[0].rptParser : NULL);
|
return ((rptParsers[0].rptParser) ? rptParsers[0].rptParser : NULL);
|
||||||
|
|
||||||
for (uint8_t i=0; i<MAX_REPORT_PARSERS; i++)
|
for (uint8_t i = 0; i < MAX_REPORT_PARSERS; i++) {
|
||||||
{
|
|
||||||
if (rptParsers[i].rptId == id)
|
if (rptParsers[i].rptId == id)
|
||||||
return rptParsers[i].rptParser;
|
return rptParsers[i].rptParser;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t HIDUniversal::Init(uint8_t parent, uint8_t port, bool lowspeed)
|
uint8_t HIDUniversal::Init(uint8_t parent, uint8_t port, bool lowspeed) {
|
||||||
{
|
|
||||||
const uint8_t constBufSize = sizeof (USB_DEVICE_DESCRIPTOR);
|
const uint8_t constBufSize = sizeof (USB_DEVICE_DESCRIPTOR);
|
||||||
|
|
||||||
uint8_t buf[constBufSize];
|
uint8_t buf[constBufSize];
|
||||||
|
@ -98,7 +83,7 @@ uint8_t HIDUniversal::Init(uint8_t parent, uint8_t port, bool lowspeed)
|
||||||
uint8_t len = 0;
|
uint8_t len = 0;
|
||||||
|
|
||||||
uint8_t num_of_conf; // number of configurations
|
uint8_t num_of_conf; // number of configurations
|
||||||
uint8_t num_of_intf; // number of interfaces
|
//uint8_t num_of_intf; // number of interfaces
|
||||||
|
|
||||||
AddressPool &addrPool = pUsb->GetAddressPool();
|
AddressPool &addrPool = pUsb->GetAddressPool();
|
||||||
|
|
||||||
|
@ -113,8 +98,7 @@ uint8_t HIDUniversal::Init(uint8_t parent, uint8_t port, bool lowspeed)
|
||||||
if (!p)
|
if (!p)
|
||||||
return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
|
return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
|
||||||
|
|
||||||
if (!p->epinfo)
|
if (!p->epinfo) {
|
||||||
{
|
|
||||||
USBTRACE("epinfo\r\n");
|
USBTRACE("epinfo\r\n");
|
||||||
return USB_ERROR_EPINFO_IS_NULL;
|
return USB_ERROR_EPINFO_IS_NULL;
|
||||||
}
|
}
|
||||||
|
@ -127,16 +111,13 @@ uint8_t HIDUniversal::Init(uint8_t parent, uint8_t port, bool lowspeed)
|
||||||
|
|
||||||
p->lowspeed = lowspeed;
|
p->lowspeed = lowspeed;
|
||||||
|
|
||||||
//delay(200);
|
|
||||||
|
|
||||||
// Get device descriptor
|
// Get device descriptor
|
||||||
rcode = pUsb->getDevDescr(0, 0, 8, (uint8_t*) buf);
|
rcode = pUsb->getDevDescr(0, 0, 8, (uint8_t*) buf);
|
||||||
|
|
||||||
if (!rcode)
|
if (!rcode)
|
||||||
len = (buf[0] > constBufSize) ? constBufSize : buf[0];
|
len = (buf[0] > constBufSize) ? constBufSize : buf[0];
|
||||||
|
|
||||||
if( rcode )
|
if (rcode) {
|
||||||
{
|
|
||||||
// Restore p->epinfo
|
// Restore p->epinfo
|
||||||
p->epinfo = oldep_ptr;
|
p->epinfo = oldep_ptr;
|
||||||
|
|
||||||
|
@ -158,8 +139,7 @@ uint8_t HIDUniversal::Init(uint8_t parent, uint8_t port, bool lowspeed)
|
||||||
// Assign new address to the device
|
// Assign new address to the device
|
||||||
rcode = pUsb->setAddr(0, 0, bAddress);
|
rcode = pUsb->setAddr(0, 0, bAddress);
|
||||||
|
|
||||||
if (rcode)
|
if (rcode) {
|
||||||
{
|
|
||||||
p->lowspeed = false;
|
p->lowspeed = false;
|
||||||
addrPool.FreeAddress(bAddress);
|
addrPool.FreeAddress(bAddress);
|
||||||
bAddress = 0;
|
bAddress = 0;
|
||||||
|
@ -178,8 +158,6 @@ uint8_t HIDUniversal::Init(uint8_t parent, uint8_t port, bool lowspeed)
|
||||||
|
|
||||||
p->lowspeed = lowspeed;
|
p->lowspeed = lowspeed;
|
||||||
|
|
||||||
delay(500);
|
|
||||||
|
|
||||||
if (len)
|
if (len)
|
||||||
rcode = pUsb->getDevDescr(bAddress, 0, len, (uint8_t*) buf);
|
rcode = pUsb->getDevDescr(bAddress, 0, len, (uint8_t*) buf);
|
||||||
|
|
||||||
|
@ -196,9 +174,7 @@ uint8_t HIDUniversal::Init(uint8_t parent, uint8_t port, bool lowspeed)
|
||||||
|
|
||||||
USBTRACE2("NC:", num_of_conf);
|
USBTRACE2("NC:", num_of_conf);
|
||||||
|
|
||||||
for (uint8_t i=0; i<num_of_conf; i++)
|
for (uint8_t i = 0; i < num_of_conf; i++) {
|
||||||
{
|
|
||||||
//delay(1000);
|
|
||||||
//HexDumper<USBReadParser, uint16_t, uint16_t> HexDump;
|
//HexDumper<USBReadParser, uint16_t, uint16_t> HexDump;
|
||||||
ConfigDescParser<USB_CLASS_HID, 0, 0,
|
ConfigDescParser<USB_CLASS_HID, 0, 0,
|
||||||
CP_MASK_COMPARE_CLASS> confDescrParser(this);
|
CP_MASK_COMPARE_CLASS> confDescrParser(this);
|
||||||
|
@ -206,6 +182,9 @@ uint8_t HIDUniversal::Init(uint8_t parent, uint8_t port, bool lowspeed)
|
||||||
//rcode = pUsb->getConfDescr(bAddress, 0, i, &HexDump);
|
//rcode = pUsb->getConfDescr(bAddress, 0, i, &HexDump);
|
||||||
rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser);
|
rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser);
|
||||||
|
|
||||||
|
if (rcode)
|
||||||
|
goto FailGetConfDescr;
|
||||||
|
|
||||||
if (bNumEP > 1)
|
if (bNumEP > 1)
|
||||||
break;
|
break;
|
||||||
} // for
|
} // for
|
||||||
|
@ -224,8 +203,7 @@ uint8_t HIDUniversal::Init(uint8_t parent, uint8_t port, bool lowspeed)
|
||||||
if (rcode)
|
if (rcode)
|
||||||
goto FailSetConfDescr;
|
goto FailSetConfDescr;
|
||||||
|
|
||||||
for (uint8_t i=0; i<bNumIface; i++)
|
for (uint8_t i = 0; i < bNumIface; i++) {
|
||||||
{
|
|
||||||
if (hidInterfaces[i].epIndex[epInterruptInIndex] == 0)
|
if (hidInterfaces[i].epIndex[epInterruptInIndex] == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -258,26 +236,19 @@ FailSetConfDescr:
|
||||||
USBTRACE("setConf:");
|
USBTRACE("setConf:");
|
||||||
goto Fail;
|
goto Fail;
|
||||||
|
|
||||||
FailSetProtocol:
|
|
||||||
USBTRACE("SetProto:");
|
|
||||||
goto Fail;
|
|
||||||
|
|
||||||
FailSetIdle:
|
FailSetIdle:
|
||||||
USBTRACE("SetIdle:");
|
USBTRACE("SetIdle:");
|
||||||
goto Fail;
|
goto Fail;
|
||||||
|
|
||||||
FailGetReportDescr:
|
|
||||||
USBTRACE("GetReportDescr:");
|
|
||||||
goto Fail;
|
|
||||||
|
|
||||||
Fail:
|
Fail:
|
||||||
Serial.println(rcode, HEX);
|
PrintHex<uint8_t > (rcode, 0x80);
|
||||||
|
Notify(PSTR("\r\n"), 0x80);
|
||||||
|
//Serial.println(rcode, HEX);
|
||||||
Release();
|
Release();
|
||||||
return rcode;
|
return rcode;
|
||||||
}
|
}
|
||||||
|
|
||||||
HIDUniversal::HIDInterface* HIDUniversal::FindInterface(uint8_t iface, uint8_t alt, uint8_t proto)
|
HIDUniversal::HIDInterface* HIDUniversal::FindInterface(uint8_t iface, uint8_t alt, uint8_t proto) {
|
||||||
{
|
|
||||||
for (uint8_t i = 0; i < bNumIface && i < maxHidInterfaces; i++)
|
for (uint8_t i = 0; i < bNumIface && i < maxHidInterfaces; i++)
|
||||||
if (hidInterfaces[i].bmInterface == iface && hidInterfaces[i].bmAltSet == alt
|
if (hidInterfaces[i].bmInterface == iface && hidInterfaces[i].bmAltSet == alt
|
||||||
&& hidInterfaces[i].bmProtocol == proto)
|
&& hidInterfaces[i].bmProtocol == proto)
|
||||||
|
@ -285,8 +256,7 @@ HIDUniversal::HIDInterface* HIDUniversal::FindInterface(uint8_t iface, uint8_t a
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void HIDUniversal::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *pep)
|
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 the first configuration satisfies, the others are not concidered.
|
||||||
if (bNumEP > 1 && conf != bConfNum)
|
if (bNumEP > 1 && conf != bConfNum)
|
||||||
return;
|
return;
|
||||||
|
@ -301,8 +271,7 @@ void HIDUniversal::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint
|
||||||
HIDInterface *piface = FindInterface(iface, alt, proto);
|
HIDInterface *piface = FindInterface(iface, alt, proto);
|
||||||
|
|
||||||
// Fill in interface structure in case of new interface
|
// Fill in interface structure in case of new interface
|
||||||
if (!piface)
|
if (!piface) {
|
||||||
{
|
|
||||||
piface = hidInterfaces + bNumIface;
|
piface = hidInterfaces + bNumIface;
|
||||||
piface->bmInterface = iface;
|
piface->bmInterface = iface;
|
||||||
piface->bmAltSet = alt;
|
piface->bmAltSet = alt;
|
||||||
|
@ -315,8 +284,7 @@ void HIDUniversal::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint
|
||||||
else
|
else
|
||||||
index = epInterruptOutIndex;
|
index = epInterruptOutIndex;
|
||||||
|
|
||||||
if (index)
|
if (index) {
|
||||||
{
|
|
||||||
// Fill in the endpoint info structure
|
// Fill in the endpoint info structure
|
||||||
epInfo[bNumEP].epAddr = (pep->bEndpointAddress & 0x0F);
|
epInfo[bNumEP].epAddr = (pep->bEndpointAddress & 0x0F);
|
||||||
epInfo[bNumEP].maxPktSize = (uint8_t) pep->wMaxPacketSize;
|
epInfo[bNumEP].maxPktSize = (uint8_t) pep->wMaxPacketSize;
|
||||||
|
@ -331,9 +299,7 @@ void HIDUniversal::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint
|
||||||
//PrintEndpointDescriptor(pep);
|
//PrintEndpointDescriptor(pep);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8_t HIDUniversal::Release() {
|
||||||
uint8_t HIDUniversal::Release()
|
|
||||||
{
|
|
||||||
pUsb->GetAddressPool().FreeAddress(bAddress);
|
pUsb->GetAddressPool().FreeAddress(bAddress);
|
||||||
|
|
||||||
bNumEP = 1;
|
bNumEP = 1;
|
||||||
|
@ -343,40 +309,35 @@ uint8_t HIDUniversal::Release()
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HIDUniversal::BuffersIdentical(uint8_t len, uint8_t *buf1, uint8_t *buf2)
|
bool HIDUniversal::BuffersIdentical(uint8_t len, uint8_t *buf1, uint8_t *buf2) {
|
||||||
{
|
|
||||||
for (uint8_t i = 0; i < len; i++)
|
for (uint8_t i = 0; i < len; i++)
|
||||||
if (buf1[i] != buf2[i])
|
if (buf1[i] != buf2[i])
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void HIDUniversal::ZeroMemory(uint8_t len, uint8_t *buf)
|
void HIDUniversal::ZeroMemory(uint8_t len, uint8_t *buf) {
|
||||||
{
|
|
||||||
for (uint8_t i = 0; i < len; i++)
|
for (uint8_t i = 0; i < len; i++)
|
||||||
buf[i] = 0;
|
buf[i] = 0;
|
||||||
}
|
}
|
||||||
void HIDUniversal::SaveBuffer(uint8_t len, uint8_t *src, uint8_t *dest)
|
|
||||||
{
|
void HIDUniversal::SaveBuffer(uint8_t len, uint8_t *src, uint8_t *dest) {
|
||||||
for (uint8_t i = 0; i < len; i++)
|
for (uint8_t i = 0; i < len; i++)
|
||||||
dest[i] = src[i];
|
dest[i] = src[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t HIDUniversal::Poll()
|
uint8_t HIDUniversal::Poll() {
|
||||||
{
|
|
||||||
uint8_t rcode = 0;
|
uint8_t rcode = 0;
|
||||||
|
|
||||||
if (!bPollEnable)
|
if (!bPollEnable)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (qNextPollTime <= millis())
|
if (qNextPollTime <= millis()) {
|
||||||
{
|
|
||||||
qNextPollTime = millis() + 50;
|
qNextPollTime = millis() + 50;
|
||||||
|
|
||||||
uint8_t buf[constBuffLen];
|
uint8_t buf[constBuffLen];
|
||||||
|
|
||||||
for (uint8_t i=0; i<bNumIface; i++)
|
for (uint8_t i = 0; i < bNumIface; i++) {
|
||||||
{
|
|
||||||
uint8_t index = hidInterfaces[i].epIndex[epInterruptInIndex];
|
uint8_t index = hidInterfaces[i].epIndex[epInterruptInIndex];
|
||||||
uint16_t read = (uint16_t) epInfo[index].maxPktSize;
|
uint16_t read = (uint16_t) epInfo[index].maxPktSize;
|
||||||
|
|
||||||
|
@ -384,8 +345,7 @@ uint8_t HIDUniversal::Poll()
|
||||||
|
|
||||||
uint8_t rcode = pUsb->inTransfer(bAddress, epInfo[index].epAddr, &read, buf);
|
uint8_t rcode = pUsb->inTransfer(bAddress, epInfo[index].epAddr, &read, buf);
|
||||||
|
|
||||||
if (rcode)
|
if (rcode) {
|
||||||
{
|
|
||||||
if (rcode != hrNAK)
|
if (rcode != hrNAK)
|
||||||
USBTRACE2("Poll:", rcode);
|
USBTRACE2("Poll:", rcode);
|
||||||
return rcode;
|
return rcode;
|
||||||
|
@ -401,12 +361,12 @@ uint8_t HIDUniversal::Poll()
|
||||||
if (identical)
|
if (identical)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
Serial.print("\r\nBuf: ");
|
Notify(PSTR("\r\nBuf: "), 0x80);
|
||||||
|
|
||||||
for (uint8_t i = 0; i < read; i++)
|
for (uint8_t i = 0; i < read; i++)
|
||||||
PrintHex<uint8_t>(buf[i]);
|
PrintHex<uint8_t > (buf[i], 0x80);
|
||||||
|
|
||||||
Serial.println("");
|
Notify(PSTR("\r\n"), 0x80);
|
||||||
|
|
||||||
HIDReportParser *prs = GetReportParser(((bHasReportId) ? *buf : 0));
|
HIDReportParser *prs = GetReportParser(((bHasReportId) ? *buf : 0));
|
||||||
|
|
||||||
|
|
|
@ -4,10 +4,9 @@
|
||||||
#include "hid.h"
|
#include "hid.h"
|
||||||
//#include "hidescriptorparser.h"
|
//#include "hidescriptorparser.h"
|
||||||
|
|
||||||
class HIDUniversal : public HID
|
class HIDUniversal : public HID {
|
||||||
{
|
|
||||||
struct ReportParser
|
struct ReportParser {
|
||||||
{
|
|
||||||
uint8_t rptId;
|
uint8_t rptId;
|
||||||
HIDReportParser *rptParser;
|
HIDReportParser *rptParser;
|
||||||
} rptParsers[MAX_REPORT_PARSERS];
|
} rptParsers[MAX_REPORT_PARSERS];
|
||||||
|
@ -20,10 +19,9 @@ class HIDUniversal : public HID
|
||||||
|
|
||||||
EpInfo epInfo[totalEndpoints];
|
EpInfo epInfo[totalEndpoints];
|
||||||
|
|
||||||
struct HIDInterface
|
struct HIDInterface {
|
||||||
{
|
|
||||||
struct
|
struct {
|
||||||
{
|
|
||||||
uint8_t bmInterface : 3;
|
uint8_t bmInterface : 3;
|
||||||
uint8_t bmAltSet : 3;
|
uint8_t bmAltSet : 3;
|
||||||
uint8_t bmProtocol : 2;
|
uint8_t bmProtocol : 2;
|
||||||
|
@ -54,7 +52,10 @@ protected:
|
||||||
|
|
||||||
// HID implementation
|
// HID implementation
|
||||||
virtual HIDReportParser* GetReportParser(uint8_t id);
|
virtual HIDReportParser* GetReportParser(uint8_t id);
|
||||||
virtual uint8_t OnInitSuccessful() { return 0; };
|
|
||||||
|
virtual uint8_t OnInitSuccessful() {
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
HIDUniversal(USB *p);
|
HIDUniversal(USB *p);
|
||||||
|
@ -66,7 +67,10 @@ public:
|
||||||
virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed);
|
virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed);
|
||||||
virtual uint8_t Release();
|
virtual uint8_t Release();
|
||||||
virtual uint8_t Poll();
|
virtual uint8_t Poll();
|
||||||
virtual uint8_t GetAddress() { return bAddress; };
|
|
||||||
|
virtual uint8_t GetAddress() {
|
||||||
|
return bAddress;
|
||||||
|
};
|
||||||
|
|
||||||
// UsbConfigXtracter implementation
|
// UsbConfigXtracter implementation
|
||||||
virtual void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep);
|
virtual void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep);
|
||||||
|
|
769
masstorage.cpp
769
masstorage.cpp
File diff suppressed because it is too large
Load diff
126
masstorage.h
126
masstorage.h
|
@ -2,8 +2,8 @@
|
||||||
#define __MASSTORAGE_H__
|
#define __MASSTORAGE_H__
|
||||||
|
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <avr/pgmspace.h>
|
|
||||||
#include "avrpins.h"
|
#include "avrpins.h"
|
||||||
|
#include <avr/pgmspace.h>
|
||||||
#include "max3421e.h"
|
#include "max3421e.h"
|
||||||
#include "usbhost.h"
|
#include "usbhost.h"
|
||||||
#include "usb_ch9.h"
|
#include "usb_ch9.h"
|
||||||
|
@ -19,7 +19,7 @@
|
||||||
#include "hexdump.h"
|
#include "hexdump.h"
|
||||||
#include "message.h"
|
#include "message.h"
|
||||||
|
|
||||||
#include "confdescparser.h"
|
#include <confdescparser.h>
|
||||||
|
|
||||||
#define SWAP(a, b) (((a) ^= (b)), ((b) ^= (a)), ((a) ^= (b)))
|
#define SWAP(a, b) (((a) ^= (b)), ((b) ^= (a)), ((a) ^= (b)))
|
||||||
|
|
||||||
|
@ -69,27 +69,44 @@
|
||||||
#define SCSI_CMD_WRITE_10 0x2A
|
#define SCSI_CMD_WRITE_10 0x2A
|
||||||
#define SCSI_CMD_MODE_SENSE_6 0x1A
|
#define SCSI_CMD_MODE_SENSE_6 0x1A
|
||||||
#define SCSI_CMD_MODE_SENSE_10 0x5A
|
#define SCSI_CMD_MODE_SENSE_10 0x5A
|
||||||
|
#define SCSI_CMD_START_STOP_UNIT 0x1B
|
||||||
|
|
||||||
|
#define SCSI_S_NOT_READY 0x02
|
||||||
|
#define SCSI_S_MEDIUM_ERROR 0x03
|
||||||
|
#define SCSI_S_ILLEGAL_REQUEST 0x05
|
||||||
|
#define SCSI_S_UNIT_ATTENTION 0x06
|
||||||
|
|
||||||
|
#define SCSI_ASC_MEDIUM_NOT_PRESENT 0x3A
|
||||||
|
#define SCSI_ASC_LBA_OUT_OF_RANGE 0x21
|
||||||
|
|
||||||
|
|
||||||
#define MASS_ERR_SUCCESS 0x00
|
#define MASS_ERR_SUCCESS 0x00
|
||||||
#define MASS_ERR_PHASE_ERROR 0x01
|
#define MASS_ERR_PHASE_ERROR 0x02
|
||||||
|
#define MASS_ERR_UNIT_NOT_READY 0x03
|
||||||
|
#define MASS_ERR_UNIT_BUSY 0x04
|
||||||
|
#define MASS_ERR_STALL 0x05
|
||||||
|
#define MASS_ERR_CMD_NOT_SUPPORTED 0x06
|
||||||
|
#define MASS_ERR_INVALID_CSW 0x07
|
||||||
|
#define MASS_ERR_NO_MEDIA 0x08
|
||||||
|
#define MASS_ERR_BAD_LBA 0x09
|
||||||
#define MASS_ERR_DEVICE_DISCONNECTED 0x11
|
#define MASS_ERR_DEVICE_DISCONNECTED 0x11
|
||||||
#define MASS_ERR_UNABLE_TO_RECOVER 0x12 // Reset recovery error
|
#define MASS_ERR_UNABLE_TO_RECOVER 0x12 // Reset recovery error
|
||||||
|
#define MASS_ERR_INVALID_LUN 0x13
|
||||||
|
#define MASS_ERR_GENERAL_SCSI_ERROR 0xFE
|
||||||
#define MASS_ERR_GENERAL_USB_ERROR 0xFF
|
#define MASS_ERR_GENERAL_USB_ERROR 0xFF
|
||||||
|
#define MASS_ERR_USER 0xA0 // For subclasses to define their own error codes
|
||||||
|
|
||||||
#define MASS_TRANS_FLG_CALLBACK 0x01 // Callback is involved
|
#define MASS_TRANS_FLG_CALLBACK 0x01 // Callback is involved
|
||||||
#define MASS_TRANS_FLG_NO_STALL_CHECK 0x02 // STALL condition is not checked
|
#define MASS_TRANS_FLG_NO_STALL_CHECK 0x02 // STALL condition is not checked
|
||||||
#define MASS_TRANS_FLG_NO_PHASE_CHECK 0x04 // PHASE_ERROR is not checked
|
#define MASS_TRANS_FLG_NO_PHASE_CHECK 0x04 // PHASE_ERROR is not checked
|
||||||
|
|
||||||
|
struct Capacity {
|
||||||
struct Capacity
|
|
||||||
{
|
|
||||||
uint8_t data[8];
|
uint8_t data[8];
|
||||||
//uint32_t dwBlockAddress;
|
//uint32_t dwBlockAddress;
|
||||||
//uint32_t dwBlockLength;
|
//uint32_t dwBlockLength;
|
||||||
};
|
}__attribute__((packed));
|
||||||
|
|
||||||
struct InquiryResponse
|
struct InquiryResponse {
|
||||||
{
|
|
||||||
uint8_t DeviceType : 5;
|
uint8_t DeviceType : 5;
|
||||||
uint8_t PeripheralQualifier : 3;
|
uint8_t PeripheralQualifier : 3;
|
||||||
|
|
||||||
|
@ -119,39 +136,38 @@ struct InquiryResponse
|
||||||
uint8_t VendorID[8];
|
uint8_t VendorID[8];
|
||||||
uint8_t ProductID[16];
|
uint8_t ProductID[16];
|
||||||
uint8_t RevisionID[4];
|
uint8_t RevisionID[4];
|
||||||
};
|
}__attribute__((packed));
|
||||||
|
|
||||||
struct CommandBlockWrapper
|
struct CommandBlockWrapperBase {
|
||||||
{
|
|
||||||
uint32_t dCBWSignature;
|
uint32_t dCBWSignature;
|
||||||
uint32_t dCBWTag;
|
uint32_t dCBWTag;
|
||||||
uint32_t dCBWDataTransferLength;
|
uint32_t dCBWDataTransferLength;
|
||||||
uint8_t bmCBWFlags;
|
uint8_t bmCBWFlags;
|
||||||
|
}__attribute__((packed));
|
||||||
|
|
||||||
struct
|
struct CommandBlockWrapper : public CommandBlockWrapperBase {
|
||||||
{
|
|
||||||
|
struct {
|
||||||
uint8_t bmCBWLUN : 4;
|
uint8_t bmCBWLUN : 4;
|
||||||
uint8_t bmReserved1 : 4;
|
uint8_t bmReserved1 : 4;
|
||||||
};
|
};
|
||||||
struct
|
|
||||||
{
|
struct {
|
||||||
uint8_t bmCBWCBLength : 4;
|
uint8_t bmCBWCBLength : 4;
|
||||||
uint8_t bmReserved2 : 4;
|
uint8_t bmReserved2 : 4;
|
||||||
};
|
};
|
||||||
|
|
||||||
uint8_t CBWCB[16];
|
uint8_t CBWCB[16];
|
||||||
} ;
|
}__attribute__((packed));
|
||||||
|
|
||||||
struct CommandStatusWrapper
|
struct CommandStatusWrapper {
|
||||||
{
|
|
||||||
uint32_t dCSWSignature;
|
uint32_t dCSWSignature;
|
||||||
uint32_t dCSWTag;
|
uint32_t dCSWTag;
|
||||||
uint32_t dCSWDataResidue;
|
uint32_t dCSWDataResidue;
|
||||||
uint8_t bCSWStatus;
|
uint8_t bCSWStatus;
|
||||||
};
|
}__attribute__((packed));
|
||||||
|
|
||||||
struct RequestSenseResponce
|
struct RequestSenseResponce {
|
||||||
{
|
|
||||||
uint8_t bResponseCode;
|
uint8_t bResponseCode;
|
||||||
uint8_t bSegmentNumber;
|
uint8_t bSegmentNumber;
|
||||||
|
|
||||||
|
@ -168,22 +184,11 @@ struct RequestSenseResponce
|
||||||
uint8_t bAdditionalSenseQualifier;
|
uint8_t bAdditionalSenseQualifier;
|
||||||
uint8_t bFieldReplaceableUnitCode;
|
uint8_t bFieldReplaceableUnitCode;
|
||||||
uint8_t SenseKeySpecific[3];
|
uint8_t SenseKeySpecific[3];
|
||||||
};
|
}__attribute__((packed));
|
||||||
|
|
||||||
//class BulkReadParser : public USBReadParser
|
|
||||||
//{
|
|
||||||
//protected:
|
|
||||||
// bool IsValidCSW(uint8_t size, uint8_t *pcsw);
|
|
||||||
// bool IsMeaningfulCSW(uint8_t size, uint8_t *pcsw);
|
|
||||||
//
|
|
||||||
//public:
|
|
||||||
// virtual void Parse(const uint16_t len, const uint8_t *pbuf, const uint16_t &offset) = 0;
|
|
||||||
//};
|
|
||||||
|
|
||||||
#define MASS_MAX_ENDPOINTS 3
|
#define MASS_MAX_ENDPOINTS 3
|
||||||
|
|
||||||
class BulkOnly : public USBDeviceConfig, public UsbConfigXtracter
|
class BulkOnly : public USBDeviceConfig, public UsbConfigXtracter {
|
||||||
{
|
|
||||||
protected:
|
protected:
|
||||||
static const uint8_t epDataInIndex; // DataIn endpoint index
|
static const uint8_t epDataInIndex; // DataIn endpoint index
|
||||||
static const uint8_t epDataOutIndex; // DataOUT endpoint index
|
static const uint8_t epDataOutIndex; // DataOUT endpoint index
|
||||||
|
@ -201,52 +206,71 @@ protected:
|
||||||
|
|
||||||
uint32_t dCBWTag; // Tag
|
uint32_t dCBWTag; // Tag
|
||||||
uint32_t dCBWDataTransferLength; // Data Transfer Length
|
uint32_t dCBWDataTransferLength; // Data Transfer Length
|
||||||
uint8_t bMaxLUN; // Max LUN
|
|
||||||
uint8_t bLastUsbError; // Last USB error
|
uint8_t bLastUsbError; // Last USB error
|
||||||
|
uint8_t bMaxLUN; // Max LUN
|
||||||
|
uint8_t bTheLUN; // Active LUN
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
//union TransFlags
|
|
||||||
//{
|
|
||||||
// uint8_t nValue;
|
|
||||||
|
|
||||||
// struct {
|
|
||||||
// uint8_t bmCallback : 1;
|
|
||||||
// uint8_t bmCheckPhaseErr : 1;
|
|
||||||
// uint8_t bmDummy : 6;
|
|
||||||
// };
|
|
||||||
//};
|
|
||||||
void PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr);
|
void PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr);
|
||||||
|
|
||||||
bool IsValidCBW(uint8_t size, uint8_t *pcbw);
|
bool IsValidCBW(uint8_t size, uint8_t *pcbw);
|
||||||
bool IsMeaningfulCBW(uint8_t size, uint8_t *pcbw);
|
bool IsMeaningfulCBW(uint8_t size, uint8_t *pcbw);
|
||||||
|
|
||||||
|
bool IsValidCSW(CommandStatusWrapper *pcsw, CommandBlockWrapperBase *pcbw);
|
||||||
|
|
||||||
uint8_t ClearEpHalt(uint8_t index);
|
uint8_t ClearEpHalt(uint8_t index);
|
||||||
uint8_t Transaction(CommandBlockWrapper *cbw, uint16_t bsize, void *buf, uint8_t flags);
|
uint8_t Transaction(CommandBlockWrapper *cbw, uint16_t bsize, void *buf, uint8_t flags);
|
||||||
uint8_t HandleUsbError(uint8_t index);
|
uint8_t HandleUsbError(uint8_t error, uint8_t index);
|
||||||
|
uint8_t HandleSCSIError(uint8_t status);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
BulkOnly(USB *p);
|
BulkOnly(USB *p);
|
||||||
uint8_t GetLastUsbError() { return bLastUsbError; };
|
|
||||||
|
uint8_t GetLastUsbError() {
|
||||||
|
return bLastUsbError;
|
||||||
|
};
|
||||||
|
|
||||||
|
uint8_t GetbMaxLUN() {
|
||||||
|
return bMaxLUN; // Max LUN
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t GetbTheLUN() {
|
||||||
|
return bTheLUN; // Active LUN
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t Reset();
|
uint8_t Reset();
|
||||||
uint8_t GetMaxLUN(uint8_t *max_lun);
|
uint8_t GetMaxLUN(uint8_t *max_lun);
|
||||||
|
uint8_t SetCurLUN(uint8_t lun);
|
||||||
|
|
||||||
uint8_t ResetRecovery();
|
uint8_t ResetRecovery();
|
||||||
uint8_t Inquiry(uint8_t lun, uint16_t size, uint8_t *buf);
|
uint8_t Inquiry(uint8_t lun, uint16_t size, uint8_t *buf);
|
||||||
uint8_t TestUnitReady(uint8_t lun);
|
uint8_t TestUnitReady(uint8_t lun);
|
||||||
uint8_t ReadCapacity(uint8_t lun, uint16_t size, uint8_t *buf);
|
uint8_t ReadCapacity(uint8_t lun, uint16_t size, uint8_t *buf);
|
||||||
uint8_t RequestSense(uint8_t lun, uint16_t size, uint8_t *buf);
|
uint8_t RequestSense(uint8_t lun, uint16_t size, uint8_t *buf);
|
||||||
//uint8_t Read(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t *buf);
|
uint8_t ModeSense(uint8_t lun, uint8_t pc, uint8_t page, uint8_t subpage, uint8_t len, uint8_t *buf);
|
||||||
uint8_t Read(uint8_t lun, uint32_t addr, uint16_t bsize, USBReadParser *prs);
|
uint8_t MediaCTL(uint8_t lun, uint8_t ctl);
|
||||||
|
uint8_t Read(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, uint8_t *buf);
|
||||||
|
uint8_t Read(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, USBReadParser *prs);
|
||||||
|
uint8_t Write(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, const uint8_t *buf);
|
||||||
|
|
||||||
// USBDeviceConfig implementation
|
// USBDeviceConfig implementation
|
||||||
virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed);
|
virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed);
|
||||||
virtual uint8_t Release();
|
virtual uint8_t Release();
|
||||||
virtual uint8_t Poll();
|
virtual uint8_t Poll();
|
||||||
virtual uint8_t GetAddress() { return bAddress; };
|
|
||||||
|
virtual uint8_t GetAddress() {
|
||||||
|
return bAddress;
|
||||||
|
};
|
||||||
|
|
||||||
// UsbConfigXtracter implementation
|
// UsbConfigXtracter implementation
|
||||||
virtual void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep);
|
virtual void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// Additional Initialization Method for Subclasses
|
||||||
|
|
||||||
|
virtual uint8_t OnInit() {
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // __MASSTORAGE_H__
|
#endif // __MASSTORAGE_H__
|
32
max_LCD.cpp
32
max_LCD.cpp
|
@ -49,14 +49,11 @@ e-mail : support@circuitsathome.com
|
||||||
|
|
||||||
static byte lcdPins; //copy of LCD pins
|
static byte lcdPins; //copy of LCD pins
|
||||||
|
|
||||||
Max_LCD::Max_LCD(USB *pusb) : pUsb(pusb)
|
Max_LCD::Max_LCD(USB *pusb) : pUsb(pusb) {
|
||||||
{
|
|
||||||
lcdPins = 0;
|
lcdPins = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Max_LCD::init() {
|
||||||
void Max_LCD::init()
|
|
||||||
{
|
|
||||||
_displayfunction = LCD_4BITMODE | LCD_1LINE | LCD_5x8DOTS;
|
_displayfunction = LCD_4BITMODE | LCD_1LINE | LCD_5x8DOTS;
|
||||||
|
|
||||||
// MAX3421E::gpioWr(0x55);
|
// MAX3421E::gpioWr(0x55);
|
||||||
|
@ -124,20 +121,17 @@ void Max_LCD::begin(uint8_t cols, uint8_t lines, uint8_t dotsize) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/********** high level commands, for the user! */
|
/********** high level commands, for the user! */
|
||||||
void Max_LCD::clear()
|
void Max_LCD::clear() {
|
||||||
{
|
|
||||||
command(LCD_CLEARDISPLAY); // clear display, set cursor position to zero
|
command(LCD_CLEARDISPLAY); // clear display, set cursor position to zero
|
||||||
delayMicroseconds(2000); // this command takes a long time!
|
delayMicroseconds(2000); // this command takes a long time!
|
||||||
}
|
}
|
||||||
|
|
||||||
void Max_LCD::home()
|
void Max_LCD::home() {
|
||||||
{
|
|
||||||
command(LCD_RETURNHOME); // set cursor position to zero
|
command(LCD_RETURNHOME); // set cursor position to zero
|
||||||
delayMicroseconds(2000); // this command takes a long time!
|
delayMicroseconds(2000); // this command takes a long time!
|
||||||
}
|
}
|
||||||
|
|
||||||
void Max_LCD::setCursor(uint8_t col, uint8_t row)
|
void Max_LCD::setCursor(uint8_t col, uint8_t row) {
|
||||||
{
|
|
||||||
int row_offsets[] = {0x00, 0x40, 0x14, 0x54};
|
int row_offsets[] = {0x00, 0x40, 0x14, 0x54};
|
||||||
if (row > _numlines) {
|
if (row > _numlines) {
|
||||||
row = _numlines - 1; // we count rows starting w/0
|
row = _numlines - 1; // we count rows starting w/0
|
||||||
|
@ -147,20 +141,24 @@ void Max_LCD::setCursor(uint8_t col, uint8_t row)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Turn the display on/off (quickly)
|
// Turn the display on/off (quickly)
|
||||||
|
|
||||||
void Max_LCD::noDisplay() {
|
void Max_LCD::noDisplay() {
|
||||||
_displaycontrol &= ~LCD_DISPLAYON;
|
_displaycontrol &= ~LCD_DISPLAYON;
|
||||||
command(LCD_DISPLAYCONTROL | _displaycontrol);
|
command(LCD_DISPLAYCONTROL | _displaycontrol);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Max_LCD::display() {
|
void Max_LCD::display() {
|
||||||
_displaycontrol |= LCD_DISPLAYON;
|
_displaycontrol |= LCD_DISPLAYON;
|
||||||
command(LCD_DISPLAYCONTROL | _displaycontrol);
|
command(LCD_DISPLAYCONTROL | _displaycontrol);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Turns the underline cursor on/off
|
// Turns the underline cursor on/off
|
||||||
|
|
||||||
void Max_LCD::noCursor() {
|
void Max_LCD::noCursor() {
|
||||||
_displaycontrol &= ~LCD_CURSORON;
|
_displaycontrol &= ~LCD_CURSORON;
|
||||||
command(LCD_DISPLAYCONTROL | _displaycontrol);
|
command(LCD_DISPLAYCONTROL | _displaycontrol);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Max_LCD::cursor() {
|
void Max_LCD::cursor() {
|
||||||
_displaycontrol |= LCD_CURSORON;
|
_displaycontrol |= LCD_CURSORON;
|
||||||
command(LCD_DISPLAYCONTROL | _displaycontrol);
|
command(LCD_DISPLAYCONTROL | _displaycontrol);
|
||||||
|
@ -168,42 +166,50 @@ void Max_LCD::cursor() {
|
||||||
|
|
||||||
|
|
||||||
// Turn on and off the blinking cursor
|
// Turn on and off the blinking cursor
|
||||||
|
|
||||||
void Max_LCD::noBlink() {
|
void Max_LCD::noBlink() {
|
||||||
_displaycontrol &= ~LCD_BLINKON;
|
_displaycontrol &= ~LCD_BLINKON;
|
||||||
command(LCD_DISPLAYCONTROL | _displaycontrol);
|
command(LCD_DISPLAYCONTROL | _displaycontrol);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Max_LCD::blink() {
|
void Max_LCD::blink() {
|
||||||
_displaycontrol |= LCD_BLINKON;
|
_displaycontrol |= LCD_BLINKON;
|
||||||
command(LCD_DISPLAYCONTROL | _displaycontrol);
|
command(LCD_DISPLAYCONTROL | _displaycontrol);
|
||||||
}
|
}
|
||||||
|
|
||||||
// These commands scroll the display without changing the RAM
|
// These commands scroll the display without changing the RAM
|
||||||
|
|
||||||
void Max_LCD::scrollDisplayLeft(void) {
|
void Max_LCD::scrollDisplayLeft(void) {
|
||||||
command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVELEFT);
|
command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVELEFT);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Max_LCD::scrollDisplayRight(void) {
|
void Max_LCD::scrollDisplayRight(void) {
|
||||||
command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVERIGHT);
|
command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVERIGHT);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is for text that flows Left to Right
|
// This is for text that flows Left to Right
|
||||||
|
|
||||||
void Max_LCD::leftToRight(void) {
|
void Max_LCD::leftToRight(void) {
|
||||||
_displaymode |= LCD_ENTRYLEFT;
|
_displaymode |= LCD_ENTRYLEFT;
|
||||||
command(LCD_ENTRYMODESET | _displaymode);
|
command(LCD_ENTRYMODESET | _displaymode);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is for text that flows Right to Left
|
// This is for text that flows Right to Left
|
||||||
|
|
||||||
void Max_LCD::rightToLeft(void) {
|
void Max_LCD::rightToLeft(void) {
|
||||||
_displaymode &= ~LCD_ENTRYLEFT;
|
_displaymode &= ~LCD_ENTRYLEFT;
|
||||||
command(LCD_ENTRYMODESET | _displaymode);
|
command(LCD_ENTRYMODESET | _displaymode);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This will 'right justify' text from the cursor
|
// This will 'right justify' text from the cursor
|
||||||
|
|
||||||
void Max_LCD::autoscroll(void) {
|
void Max_LCD::autoscroll(void) {
|
||||||
_displaymode |= LCD_ENTRYSHIFTINCREMENT;
|
_displaymode |= LCD_ENTRYSHIFTINCREMENT;
|
||||||
command(LCD_ENTRYMODESET | _displaymode);
|
command(LCD_ENTRYMODESET | _displaymode);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This will 'left justify' text from the cursor
|
// This will 'left justify' text from the cursor
|
||||||
|
|
||||||
void Max_LCD::noAutoscroll(void) {
|
void Max_LCD::noAutoscroll(void) {
|
||||||
_displaymode &= ~LCD_ENTRYSHIFTINCREMENT;
|
_displaymode &= ~LCD_ENTRYSHIFTINCREMENT;
|
||||||
command(LCD_ENTRYMODESET | _displaymode);
|
command(LCD_ENTRYMODESET | _displaymode);
|
||||||
|
@ -211,6 +217,7 @@ void Max_LCD::noAutoscroll(void) {
|
||||||
|
|
||||||
// Allows us to fill the first 8 CGRAM locations
|
// Allows us to fill the first 8 CGRAM locations
|
||||||
// with custom characters
|
// with custom characters
|
||||||
|
|
||||||
void Max_LCD::createChar(uint8_t location, uint8_t charmap[]) {
|
void Max_LCD::createChar(uint8_t location, uint8_t charmap[]) {
|
||||||
location &= 0x7; // we only have 8 locations 0-7
|
location &= 0x7; // we only have 8 locations 0-7
|
||||||
command(LCD_SETCGRAMADDR | (location << 3));
|
command(LCD_SETCGRAMADDR | (location << 3));
|
||||||
|
@ -230,8 +237,7 @@ inline void Max_LCD::write(uint8_t value) {
|
||||||
LCD_sendchar(value);
|
LCD_sendchar(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Max_LCD::sendbyte( uint8_t val )
|
void Max_LCD::sendbyte(uint8_t val) {
|
||||||
{
|
|
||||||
lcdPins &= 0x0f; //prepare place for the upper nibble
|
lcdPins &= 0x0f; //prepare place for the upper nibble
|
||||||
lcdPins |= (val & 0xf0); //copy upper nibble to LCD variable
|
lcdPins |= (val & 0xf0); //copy upper nibble to LCD variable
|
||||||
SET_E; //send
|
SET_E; //send
|
||||||
|
|
30
message.cpp
30
message.cpp
|
@ -15,17 +15,33 @@ Web : http://www.circuitsathome.com
|
||||||
e-mail : support@circuitsathome.com
|
e-mail : support@circuitsathome.com
|
||||||
*/
|
*/
|
||||||
#include "message.h"
|
#include "message.h"
|
||||||
|
// 0x80 is the default (i.e. trace) to turn off set this global to something lower.
|
||||||
|
// this allows for 126 other debugging levels.
|
||||||
|
// TO-DO: Allow assignment to a different serial port
|
||||||
|
int UsbDEBUGlvl = 0x80;
|
||||||
|
|
||||||
void Notify(char const * msg)
|
void Notifyc(char c, int lvl) {
|
||||||
//void Notify(const char* msg)
|
if (UsbDEBUGlvl < lvl) return;
|
||||||
{
|
|
||||||
if(!msg) return;
|
|
||||||
char c;
|
|
||||||
|
|
||||||
while((c = pgm_read_byte(msg++)))
|
|
||||||
#if defined(ARDUINO) && ARDUINO >=100
|
#if defined(ARDUINO) && ARDUINO >=100
|
||||||
Serial.print(c);
|
Serial.print(c);
|
||||||
#else
|
#else
|
||||||
Serial.print(c, BYTE);
|
Serial.print(c, BYTE);
|
||||||
#endif
|
#endif
|
||||||
|
Serial.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Notify(char const * msg, int lvl) {
|
||||||
|
if (UsbDEBUGlvl < lvl) return;
|
||||||
|
if (!msg) return;
|
||||||
|
char c;
|
||||||
|
|
||||||
|
while ((c = pgm_read_byte(msg++))) Notifyc(c, lvl);
|
||||||
|
}
|
||||||
|
|
||||||
|
void NotifyStr(char const * msg, int lvl) {
|
||||||
|
if (UsbDEBUGlvl < lvl) return;
|
||||||
|
if (!msg) return;
|
||||||
|
char c;
|
||||||
|
|
||||||
|
while (c = *msg++) Notifyc(c, lvl);
|
||||||
}
|
}
|
||||||
|
|
16
message.h
16
message.h
|
@ -19,18 +19,20 @@ e-mail : support@circuitsathome.com
|
||||||
|
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <avr/pgmspace.h>
|
#include <avr/pgmspace.h>
|
||||||
|
|
||||||
|
void Notify(char const * msg, int lvl);
|
||||||
|
void NotifyStr(char const * msg, int lvl);
|
||||||
|
|
||||||
#include "printhex.h"
|
#include "printhex.h"
|
||||||
|
|
||||||
void Notify(char const * msg);
|
|
||||||
//void Notify(const char* msg);
|
//void Notify(const char* msg);
|
||||||
|
|
||||||
template <class ERROR_TYPE>
|
template <class ERROR_TYPE>
|
||||||
void ErrorMessage(char const * msg, ERROR_TYPE rcode = 0)
|
void ErrorMessage(char const * msg, ERROR_TYPE rcode = 0) {
|
||||||
{
|
Notify(msg, 0x80);
|
||||||
Notify(msg);
|
Notify(PSTR(": "), 0x80);
|
||||||
Notify(PSTR(": "));
|
PrintHex<ERROR_TYPE > (rcode, 0x80);
|
||||||
PrintHex<ERROR_TYPE>(rcode);
|
Notify(PSTR("\r\n"), 0x80);
|
||||||
Notify(PSTR("\r\n"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -16,11 +16,9 @@ e-mail : support@circuitsathome.com
|
||||||
*/
|
*/
|
||||||
#include "parsetools.h"
|
#include "parsetools.h"
|
||||||
|
|
||||||
bool MultiByteValueParser::Parse(uint8_t **pp, uint16_t *pcntdn)
|
bool MultiByteValueParser::Parse(uint8_t **pp, uint16_t *pcntdn) {
|
||||||
{
|
if (!pBuf) {
|
||||||
if (!pBuf)
|
Notify(PSTR("Buffer pointer is NULL!\r\n"), 0x80);
|
||||||
{
|
|
||||||
Notify(PSTR("Buffer pointer is NULL!\r\n"));
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
for (; countDown && (*pcntdn); countDown--, (*pcntdn)--, (*pp)++)
|
for (; countDown && (*pcntdn); countDown--, (*pcntdn)--, (*pp)++)
|
||||||
|
@ -33,10 +31,8 @@ bool MultiByteValueParser::Parse(uint8_t **pp, uint16_t *pcntdn)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PTPListParser::Parse(uint8_t **pp, uint16_t *pcntdn, PTP_ARRAY_EL_FUNC pf, const void *me)
|
bool PTPListParser::Parse(uint8_t **pp, uint16_t *pcntdn, PTP_ARRAY_EL_FUNC pf, const void *me) {
|
||||||
{
|
switch (nStage) {
|
||||||
switch (nStage)
|
|
||||||
{
|
|
||||||
case 0:
|
case 0:
|
||||||
pBuf->valueSize = lenSize;
|
pBuf->valueSize = lenSize;
|
||||||
theParser.Initialize(pBuf);
|
theParser.Initialize(pBuf);
|
||||||
|
@ -57,8 +53,7 @@ bool PTPListParser::Parse(uint8_t **pp, uint16_t *pcntdn, PTP_ARRAY_EL_FUNC pf,
|
||||||
nStage = 3;
|
nStage = 3;
|
||||||
|
|
||||||
case 3:
|
case 3:
|
||||||
for (; arLenCntdn; arLenCntdn--)
|
for (; arLenCntdn; arLenCntdn--) {
|
||||||
{
|
|
||||||
if (!theParser.Parse(pp, pcntdn))
|
if (!theParser.Parse(pp, pcntdn))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
|
62
parsetools.h
62
parsetools.h
|
@ -29,25 +29,26 @@ e-mail : support@circuitsathome.com
|
||||||
#include <WProgram.h>
|
#include <WProgram.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct MultiValueBuffer
|
struct MultiValueBuffer {
|
||||||
{
|
|
||||||
uint8_t valueSize;
|
uint8_t valueSize;
|
||||||
void *pValue;
|
void *pValue;
|
||||||
};
|
}__attribute__((packed));
|
||||||
|
|
||||||
class MultiByteValueParser
|
class MultiByteValueParser {
|
||||||
{
|
|
||||||
uint8_t * pBuf;
|
uint8_t * pBuf;
|
||||||
uint8_t countDown;
|
uint8_t countDown;
|
||||||
uint8_t valueSize;
|
uint8_t valueSize;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
MultiByteValueParser() : pBuf(NULL), countDown(0), valueSize(0) {};
|
|
||||||
|
|
||||||
const uint8_t* GetBuffer() { return pBuf; };
|
MultiByteValueParser() : pBuf(NULL), countDown(0), valueSize(0) {
|
||||||
|
};
|
||||||
|
|
||||||
void Initialize(MultiValueBuffer * const pbuf)
|
const uint8_t* GetBuffer() {
|
||||||
{
|
return pBuf;
|
||||||
|
};
|
||||||
|
|
||||||
|
void Initialize(MultiValueBuffer * const pbuf) {
|
||||||
pBuf = (uint8_t*) pbuf->pValue;
|
pBuf = (uint8_t*) pbuf->pValue;
|
||||||
countDown = valueSize = pbuf->valueSize;
|
countDown = valueSize = pbuf->valueSize;
|
||||||
};
|
};
|
||||||
|
@ -55,25 +56,23 @@ public:
|
||||||
bool Parse(uint8_t **pp, uint16_t *pcntdn);
|
bool Parse(uint8_t **pp, uint16_t *pcntdn);
|
||||||
};
|
};
|
||||||
|
|
||||||
class ByteSkipper
|
class ByteSkipper {
|
||||||
{
|
|
||||||
uint8_t *pBuf;
|
uint8_t *pBuf;
|
||||||
uint8_t nStage;
|
uint8_t nStage;
|
||||||
uint16_t countDown;
|
uint16_t countDown;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ByteSkipper() : pBuf(NULL), nStage(0), countDown(0) {};
|
|
||||||
|
|
||||||
void Initialize(MultiValueBuffer *pbuf)
|
ByteSkipper() : pBuf(NULL), nStage(0), countDown(0) {
|
||||||
{
|
};
|
||||||
|
|
||||||
|
void Initialize(MultiValueBuffer *pbuf) {
|
||||||
pBuf = (uint8_t*) pbuf->pValue;
|
pBuf = (uint8_t*) pbuf->pValue;
|
||||||
countDown = 0;
|
countDown = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool Skip(uint8_t **pp, uint16_t *pcntdn, uint16_t bytes_to_skip)
|
bool Skip(uint8_t **pp, uint16_t *pcntdn, uint16_t bytes_to_skip) {
|
||||||
{
|
switch (nStage) {
|
||||||
switch (nStage)
|
|
||||||
{
|
|
||||||
case 0:
|
case 0:
|
||||||
countDown = bytes_to_skip;
|
countDown = bytes_to_skip;
|
||||||
nStage++;
|
nStage++;
|
||||||
|
@ -90,10 +89,12 @@ public:
|
||||||
// Pointer to a callback function triggered for each element of PTP array when used with PTPArrayParser
|
// Pointer to a callback function triggered for each element of PTP array when used with PTPArrayParser
|
||||||
typedef void (*PTP_ARRAY_EL_FUNC)(const MultiValueBuffer * const p, uint32_t count, const void *me);
|
typedef void (*PTP_ARRAY_EL_FUNC)(const MultiValueBuffer * const p, uint32_t count, const void *me);
|
||||||
|
|
||||||
class PTPListParser
|
class PTPListParser {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
enum ParseMode { modeArray, modeRange/*, modeEnum*/ };
|
|
||||||
|
enum ParseMode {
|
||||||
|
modeArray, modeRange/*, modeEnum*/
|
||||||
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint8_t nStage;
|
uint8_t nStage;
|
||||||
|
@ -113,31 +114,28 @@ private:
|
||||||
uint8_t /*ParseMode*/ prsMode;
|
uint8_t /*ParseMode*/ prsMode;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
PTPListParser() :
|
PTPListParser() :
|
||||||
pBuf(NULL),
|
|
||||||
nStage(0),
|
nStage(0),
|
||||||
enStage(0),
|
enStage(0),
|
||||||
arLenCntdn(0),
|
|
||||||
arLen(0),
|
arLen(0),
|
||||||
|
arLenCntdn(0),
|
||||||
lenSize(0),
|
lenSize(0),
|
||||||
valSize(0),
|
valSize(0),
|
||||||
prsMode(modeArray)
|
pBuf(NULL),
|
||||||
{};
|
prsMode(modeArray) {
|
||||||
|
};
|
||||||
|
|
||||||
void Initialize(const uint8_t len_size, const uint8_t val_size, MultiValueBuffer * const p, const uint8_t mode = modeArray)
|
void Initialize(const uint8_t len_size, const uint8_t val_size, MultiValueBuffer * const p, const uint8_t mode = modeArray) {
|
||||||
{
|
|
||||||
pBuf = p;
|
pBuf = p;
|
||||||
lenSize = len_size;
|
lenSize = len_size;
|
||||||
valSize = val_size;
|
valSize = val_size;
|
||||||
prsMode = mode;
|
prsMode = mode;
|
||||||
|
|
||||||
if (prsMode == modeRange)
|
if (prsMode == modeRange) {
|
||||||
{
|
|
||||||
arLenCntdn = arLen = 3;
|
arLenCntdn = arLen = 3;
|
||||||
nStage = 2;
|
nStage = 2;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
arLenCntdn = arLen = 0;
|
arLenCntdn = arLen = 0;
|
||||||
nStage = 0;
|
nStage = 0;
|
||||||
}
|
}
|
||||||
|
|
55
printhex.h
55
printhex.h
|
@ -22,29 +22,44 @@ e-mail : support@circuitsathome.com
|
||||||
#else
|
#else
|
||||||
#include <WProgram.h>
|
#include <WProgram.h>
|
||||||
#endif
|
#endif
|
||||||
|
void Notifyc(char c, int lvl);
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
void PrintHex(T val)
|
void PrintHex(T val, int lvl) {
|
||||||
{
|
int num_nibbles = sizeof (T) * 2;
|
||||||
T mask = (((T)1) << (((sizeof(T) << 1) - 1) << 2));
|
|
||||||
|
|
||||||
while (mask > 1)
|
do {
|
||||||
{
|
char v = 48 + (((val >> (num_nibbles - 1) * 4)) & 0x0f);
|
||||||
if (val < mask)
|
if (v > 57) v += 7;
|
||||||
Serial.print("0");
|
Notifyc(v, lvl);
|
||||||
|
} while (--num_nibbles);
|
||||||
mask >>= 4;
|
|
||||||
}
|
|
||||||
Serial.print((T)val, HEX);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
void PrintHex2(Print *prn, T val)
|
void PrintBin(T val, int lvl) {
|
||||||
{
|
for (T mask = (((T) 1) << ((sizeof (T) << 3) - 1)); mask; mask >>= 1)
|
||||||
|
if (val & mask)
|
||||||
|
Notifyc('1', lvl);
|
||||||
|
else
|
||||||
|
Notifyc('0', lvl);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
void SerialPrintHex(T val) {
|
||||||
|
int num_nibbles = sizeof (T) * 2;
|
||||||
|
|
||||||
|
do {
|
||||||
|
char v = 48 + (((val >> (num_nibbles - 1) * 4)) & 0x0f);
|
||||||
|
if (v > 57) v += 7;
|
||||||
|
Serial.print(v);
|
||||||
|
} while (--num_nibbles);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
void PrintHex2(Print *prn, T val) {
|
||||||
T mask = (((T) 1) << (((sizeof (T) << 1) - 1) << 2));
|
T mask = (((T) 1) << (((sizeof (T) << 1) - 1) << 2));
|
||||||
|
|
||||||
while (mask > 1)
|
while (mask > 1) {
|
||||||
{
|
|
||||||
if (val < mask)
|
if (val < mask)
|
||||||
prn->print("0");
|
prn->print("0");
|
||||||
|
|
||||||
|
@ -53,14 +68,4 @@ void PrintHex2(Print *prn, T val)
|
||||||
prn->print((T) val, HEX);
|
prn->print((T) val, HEX);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
|
||||||
void PrintBin(T val)
|
|
||||||
{
|
|
||||||
for (T mask = (((T)1) << (sizeof(T) << 3)-1); mask; mask>>=1)
|
|
||||||
if (val & mask)
|
|
||||||
Serial.print("1");
|
|
||||||
else
|
|
||||||
Serial.print("0");
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // __PRINTHEX_H__
|
#endif // __PRINTHEX_H__
|
28
usb_ch9.h
28
usb_ch9.h
|
@ -108,11 +108,10 @@ typedef struct {
|
||||||
uint8_t iProduct; // Index of String Descriptor describing the product.
|
uint8_t iProduct; // Index of String Descriptor describing the product.
|
||||||
uint8_t iSerialNumber; // Index of String Descriptor with the device's serial number.
|
uint8_t iSerialNumber; // Index of String Descriptor with the device's serial number.
|
||||||
uint8_t bNumConfigurations; // Number of possible configurations.
|
uint8_t bNumConfigurations; // Number of possible configurations.
|
||||||
} USB_DEVICE_DESCRIPTOR;
|
}__attribute__((packed)) USB_DEVICE_DESCRIPTOR;
|
||||||
|
|
||||||
/* Configuration descriptor structure */
|
/* Configuration descriptor structure */
|
||||||
typedef struct
|
typedef struct {
|
||||||
{
|
|
||||||
uint8_t bLength; // Length of this descriptor.
|
uint8_t bLength; // Length of this descriptor.
|
||||||
uint8_t bDescriptorType; // CONFIGURATION descriptor type (USB_DESCRIPTOR_CONFIGURATION).
|
uint8_t bDescriptorType; // CONFIGURATION descriptor type (USB_DESCRIPTOR_CONFIGURATION).
|
||||||
uint16_t wTotalLength; // Total length of all descriptors for this configuration.
|
uint16_t wTotalLength; // Total length of all descriptors for this configuration.
|
||||||
|
@ -121,11 +120,10 @@ typedef struct
|
||||||
uint8_t iConfiguration; // Index of String Descriptor describing the configuration.
|
uint8_t iConfiguration; // Index of String Descriptor describing the configuration.
|
||||||
uint8_t bmAttributes; // Configuration characteristics.
|
uint8_t bmAttributes; // Configuration characteristics.
|
||||||
uint8_t bMaxPower; // Maximum power consumed by this configuration.
|
uint8_t bMaxPower; // Maximum power consumed by this configuration.
|
||||||
} USB_CONFIGURATION_DESCRIPTOR;
|
}__attribute__((packed)) USB_CONFIGURATION_DESCRIPTOR;
|
||||||
|
|
||||||
/* Interface descriptor structure */
|
/* Interface descriptor structure */
|
||||||
typedef struct
|
typedef struct {
|
||||||
{
|
|
||||||
uint8_t bLength; // Length of this descriptor.
|
uint8_t bLength; // Length of this descriptor.
|
||||||
uint8_t bDescriptorType; // INTERFACE descriptor type (USB_DESCRIPTOR_INTERFACE).
|
uint8_t bDescriptorType; // INTERFACE descriptor type (USB_DESCRIPTOR_INTERFACE).
|
||||||
uint8_t bInterfaceNumber; // Number of this interface (0 based).
|
uint8_t bInterfaceNumber; // Number of this interface (0 based).
|
||||||
|
@ -135,23 +133,20 @@ typedef struct
|
||||||
uint8_t bInterfaceSubClass; // Subclass code (assigned by the USB-IF).
|
uint8_t bInterfaceSubClass; // Subclass code (assigned by the USB-IF).
|
||||||
uint8_t bInterfaceProtocol; // Protocol code (assigned by the USB-IF). 0xFF-Vendor specific.
|
uint8_t bInterfaceProtocol; // Protocol code (assigned by the USB-IF). 0xFF-Vendor specific.
|
||||||
uint8_t iInterface; // Index of String Descriptor describing the interface.
|
uint8_t iInterface; // Index of String Descriptor describing the interface.
|
||||||
} USB_INTERFACE_DESCRIPTOR;
|
}__attribute__((packed)) USB_INTERFACE_DESCRIPTOR;
|
||||||
|
|
||||||
/* Endpoint descriptor structure */
|
/* Endpoint descriptor structure */
|
||||||
typedef struct
|
typedef struct {
|
||||||
{
|
|
||||||
uint8_t bLength; // Length of this descriptor.
|
uint8_t bLength; // Length of this descriptor.
|
||||||
uint8_t bDescriptorType; // ENDPOINT descriptor type (USB_DESCRIPTOR_ENDPOINT).
|
uint8_t bDescriptorType; // ENDPOINT descriptor type (USB_DESCRIPTOR_ENDPOINT).
|
||||||
uint8_t bEndpointAddress; // Endpoint address. Bit 7 indicates direction (0=OUT, 1=IN).
|
uint8_t bEndpointAddress; // Endpoint address. Bit 7 indicates direction (0=OUT, 1=IN).
|
||||||
uint8_t bmAttributes; // Endpoint transfer type.
|
uint8_t bmAttributes; // Endpoint transfer type.
|
||||||
uint16_t wMaxPacketSize; // Maximum packet size.
|
uint16_t wMaxPacketSize; // Maximum packet size.
|
||||||
uint8_t bInterval; // Polling interval in frames.
|
uint8_t bInterval; // Polling interval in frames.
|
||||||
} USB_ENDPOINT_DESCRIPTOR;
|
}__attribute__((packed)) USB_ENDPOINT_DESCRIPTOR;
|
||||||
|
|
||||||
|
|
||||||
/* HID descriptor */
|
/* HID descriptor */
|
||||||
typedef struct
|
typedef struct {
|
||||||
{
|
|
||||||
uint8_t bLength;
|
uint8_t bLength;
|
||||||
uint8_t bDescriptorType;
|
uint8_t bDescriptorType;
|
||||||
uint16_t bcdHID; // HID class specification release
|
uint16_t bcdHID; // HID class specification release
|
||||||
|
@ -159,12 +154,11 @@ typedef struct
|
||||||
uint8_t bNumDescriptors; // Number of additional class specific descriptors
|
uint8_t bNumDescriptors; // Number of additional class specific descriptors
|
||||||
uint8_t bDescrType; // Type of class descriptor
|
uint8_t bDescrType; // Type of class descriptor
|
||||||
uint16_t wDescriptorLength; // Total size of the Report descriptor
|
uint16_t wDescriptorLength; // Total size of the Report descriptor
|
||||||
} USB_HID_DESCRIPTOR;
|
}__attribute__((packed)) USB_HID_DESCRIPTOR;
|
||||||
|
|
||||||
typedef struct
|
typedef struct {
|
||||||
{
|
|
||||||
uint8_t bDescrType; // Type of class descriptor
|
uint8_t bDescrType; // Type of class descriptor
|
||||||
uint16_t wDescriptorLength; // Total size of the Report descriptor
|
uint16_t wDescriptorLength; // Total size of the Report descriptor
|
||||||
} HID_CLASS_DESCRIPTOR_LEN_AND_TYPE;
|
}__attribute__((packed)) HID_CLASS_DESCRIPTOR_LEN_AND_TYPE;
|
||||||
|
|
||||||
#endif // _ch9_h_
|
#endif // _ch9_h_
|
||||||
|
|
82
usbhost.h
82
usbhost.h
|
@ -22,13 +22,12 @@ e-mail : support@circuitsathome.com
|
||||||
#include "max3421e.h"
|
#include "max3421e.h"
|
||||||
#include "usb_ch9.h"
|
#include "usb_ch9.h"
|
||||||
|
|
||||||
|
|
||||||
/* SPI initialization */
|
/* SPI initialization */
|
||||||
template< typename CLK, typename MOSI, typename MISO, typename SPI_SS > class SPi
|
template< typename CLK, typename MOSI, typename MISO, typename SPI_SS > class SPi {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
static void init() {
|
static void init() {
|
||||||
uint8_t tmp;
|
//uint8_t tmp;
|
||||||
CLK::SetDirWrite();
|
CLK::SetDirWrite();
|
||||||
MOSI::SetDirWrite();
|
MOSI::SetDirWrite();
|
||||||
MISO::SetDirRead();
|
MISO::SetDirRead();
|
||||||
|
@ -37,8 +36,8 @@ template< typename CLK, typename MOSI, typename MISO, typename SPI_SS > class SP
|
||||||
SPCR = 0x50;
|
SPCR = 0x50;
|
||||||
SPSR = 0x01;
|
SPSR = 0x01;
|
||||||
/**/
|
/**/
|
||||||
tmp = SPSR;
|
//tmp = SPSR;
|
||||||
tmp = SPDR;
|
//tmp = SPDR;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -53,8 +52,7 @@ typedef SPi< Pb5, Pb3, Pb4, Pb2 > spi;
|
||||||
typedef SPi< Pb7, Pb5, Pb6, Pb4 > spi;
|
typedef SPi< Pb7, Pb5, Pb6, Pb4 > spi;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
template< typename SS, typename INTR > class MAX3421e /* : public spi */
|
template< typename SS, typename INTR > class MAX3421e /* : public spi */ {
|
||||||
{
|
|
||||||
static uint8_t vbusState;
|
static uint8_t vbusState;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -67,7 +65,10 @@ template< typename SS, typename INTR > class MAX3421e /* : public spi */
|
||||||
uint8_t gpioRd();
|
uint8_t gpioRd();
|
||||||
uint16_t reset();
|
uint16_t reset();
|
||||||
int8_t Init();
|
int8_t Init();
|
||||||
uint8_t getVbusState( void ) { return vbusState; };
|
|
||||||
|
uint8_t getVbusState(void) {
|
||||||
|
return vbusState;
|
||||||
|
};
|
||||||
void busprobe();
|
void busprobe();
|
||||||
uint8_t GpxHandler();
|
uint8_t GpxHandler();
|
||||||
uint8_t IntHandler();
|
uint8_t IntHandler();
|
||||||
|
@ -79,27 +80,20 @@ uint8_t MAX3421e< SS, INTR >::vbusState = 0;
|
||||||
|
|
||||||
/* constructor */
|
/* constructor */
|
||||||
template< typename SS, typename INTR >
|
template< typename SS, typename INTR >
|
||||||
MAX3421e< SS, INTR >::MAX3421e()
|
MAX3421e< SS, INTR >::MAX3421e() {
|
||||||
{
|
|
||||||
/* pin and peripheral setup */
|
/* pin and peripheral setup */
|
||||||
SS::SetDirWrite();
|
SS::SetDirWrite();
|
||||||
SS::Set();
|
SS::Set();
|
||||||
spi::init();
|
spi::init();
|
||||||
INTR::SetDirRead();
|
INTR::SetDirRead();
|
||||||
#ifdef BOARD_MEGA_ADK
|
|
||||||
/* For Mega ADK, which has Max3421e on-board, set MAX_RESET to Output mode, and pull Reset to HIGH */
|
|
||||||
DDRJ |= _BV(PJ2);
|
|
||||||
PORTJ &= ~_BV(PJ2);
|
|
||||||
PORTJ |= _BV(PJ2);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* MAX3421E - full-duplex SPI, level interrupt */
|
/* MAX3421E - full-duplex SPI, level interrupt */
|
||||||
regWr(rPINCTL, (bmFDUPSPI + bmINTLEVEL));
|
regWr(rPINCTL, (bmFDUPSPI + bmINTLEVEL));
|
||||||
};
|
};
|
||||||
|
|
||||||
/* write single byte into MAX3421 register */
|
/* write single byte into MAX3421 register */
|
||||||
template< typename SS, typename INTR >
|
template< typename SS, typename INTR >
|
||||||
void MAX3421e< SS, INTR >::regWr( uint8_t reg, uint8_t data )
|
void MAX3421e< SS, INTR >::regWr(uint8_t reg, uint8_t data) {
|
||||||
{
|
|
||||||
SS::Clear();
|
SS::Clear();
|
||||||
SPDR = (reg | 0x02);
|
SPDR = (reg | 0x02);
|
||||||
while (!(SPSR & (1 << SPIF)));
|
while (!(SPSR & (1 << SPIF)));
|
||||||
|
@ -109,10 +103,10 @@ void MAX3421e< SS, INTR >::regWr( uint8_t reg, uint8_t data )
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
/* multiple-byte write */
|
/* multiple-byte write */
|
||||||
|
|
||||||
/* returns a pointer to memory position after last written */
|
/* returns a pointer to memory position after last written */
|
||||||
template< typename SS, typename INTR >
|
template< typename SS, typename INTR >
|
||||||
uint8_t* MAX3421e< SS, INTR >::bytesWr( uint8_t reg, uint8_t nbytes, uint8_t* data_p )
|
uint8_t* MAX3421e< SS, INTR >::bytesWr(uint8_t reg, uint8_t nbytes, uint8_t* data_p) {
|
||||||
{
|
|
||||||
SS::Clear();
|
SS::Clear();
|
||||||
SPDR = (reg | 0x02); //set WR bit and send register number
|
SPDR = (reg | 0x02); //set WR bit and send register number
|
||||||
while (nbytes--) {
|
while (nbytes--) {
|
||||||
|
@ -126,19 +120,19 @@ uint8_t* MAX3421e< SS, INTR >::bytesWr( uint8_t reg, uint8_t nbytes, uint8_t* da
|
||||||
}
|
}
|
||||||
/* GPIO write */
|
/* GPIO write */
|
||||||
/*GPIO byte is split between 2 registers, so two writes are needed to write one byte */
|
/*GPIO byte is split between 2 registers, so two writes are needed to write one byte */
|
||||||
|
|
||||||
/* GPOUT bits are in the low nibble. 0-3 in IOPINS1, 4-7 in IOPINS2 */
|
/* GPOUT bits are in the low nibble. 0-3 in IOPINS1, 4-7 in IOPINS2 */
|
||||||
template< typename SS, typename INTR >
|
template< typename SS, typename INTR >
|
||||||
void MAX3421e< SS, INTR >::gpioWr( uint8_t data )
|
void MAX3421e< SS, INTR >::gpioWr(uint8_t data) {
|
||||||
{
|
|
||||||
regWr(rIOPINS1, data);
|
regWr(rIOPINS1, data);
|
||||||
data >>= 4;
|
data >>= 4;
|
||||||
regWr(rIOPINS2, data);
|
regWr(rIOPINS2, data);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* single host register read */
|
/* single host register read */
|
||||||
template< typename SS, typename INTR >
|
template< typename SS, typename INTR >
|
||||||
uint8_t MAX3421e< SS, INTR >::regRd( uint8_t reg )
|
uint8_t MAX3421e< SS, INTR >::regRd(uint8_t reg) {
|
||||||
{
|
|
||||||
SS::Clear();
|
SS::Clear();
|
||||||
SPDR = reg;
|
SPDR = reg;
|
||||||
while (!(SPSR & (1 << SPIF)));
|
while (!(SPSR & (1 << SPIF)));
|
||||||
|
@ -148,10 +142,10 @@ uint8_t MAX3421e< SS, INTR >::regRd( uint8_t reg )
|
||||||
return ( SPDR);
|
return ( SPDR);
|
||||||
}
|
}
|
||||||
/* multiple-byte register read */
|
/* multiple-byte register read */
|
||||||
|
|
||||||
/* returns a pointer to a memory position after last read */
|
/* returns a pointer to a memory position after last read */
|
||||||
template< typename SS, typename INTR >
|
template< typename SS, typename INTR >
|
||||||
uint8_t* MAX3421e< SS, INTR >::bytesRd( uint8_t reg, uint8_t nbytes, uint8_t* data_p )
|
uint8_t* MAX3421e< SS, INTR >::bytesRd(uint8_t reg, uint8_t nbytes, uint8_t* data_p) {
|
||||||
{
|
|
||||||
SS::Clear();
|
SS::Clear();
|
||||||
SPDR = reg;
|
SPDR = reg;
|
||||||
while (!(SPSR & (1 << SPIF))); //wait
|
while (!(SPSR & (1 << SPIF))); //wait
|
||||||
|
@ -166,21 +160,21 @@ uint8_t* MAX3421e< SS, INTR >::bytesRd( uint8_t reg, uint8_t nbytes, uint8_t* da
|
||||||
return ( data_p);
|
return ( data_p);
|
||||||
}
|
}
|
||||||
/* GPIO read. See gpioWr for explanation */
|
/* GPIO read. See gpioWr for explanation */
|
||||||
|
|
||||||
/* GPIN pins are in high nibbles of IOPINS1, IOPINS2 */
|
/* GPIN pins are in high nibbles of IOPINS1, IOPINS2 */
|
||||||
template< typename SS, typename INTR >
|
template< typename SS, typename INTR >
|
||||||
uint8_t MAX3421e< SS, INTR >::gpioRd()
|
uint8_t MAX3421e< SS, INTR >::gpioRd() {
|
||||||
{
|
|
||||||
uint8_t gpin = 0;
|
uint8_t gpin = 0;
|
||||||
gpin = regRd(rIOPINS2); //pins 4-7
|
gpin = regRd(rIOPINS2); //pins 4-7
|
||||||
gpin &= 0xf0; //clean lower nibble
|
gpin &= 0xf0; //clean lower nibble
|
||||||
gpin |= (regRd(rIOPINS1) >> 4); //shift low bits and OR with upper from previous operation.
|
gpin |= (regRd(rIOPINS1) >> 4); //shift low bits and OR with upper from previous operation.
|
||||||
return ( gpin);
|
return ( gpin);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* reset MAX3421E. Returns number of cycles it took for PLL to stabilize after reset
|
/* reset MAX3421E. Returns number of cycles it took for PLL to stabilize after reset
|
||||||
or zero if PLL haven't stabilized in 65535 cycles */
|
or zero if PLL haven't stabilized in 65535 cycles */
|
||||||
template< typename SS, typename INTR >
|
template< typename SS, typename INTR >
|
||||||
uint16_t MAX3421e< SS, INTR >::reset()
|
uint16_t MAX3421e< SS, INTR >::reset() {
|
||||||
{
|
|
||||||
uint16_t i = 0;
|
uint16_t i = 0;
|
||||||
regWr(rUSBCTL, bmCHIPRES);
|
regWr(rUSBCTL, bmCHIPRES);
|
||||||
regWr(rUSBCTL, 0x00);
|
regWr(rUSBCTL, 0x00);
|
||||||
|
@ -202,12 +196,11 @@ uint16_t MAX3421e< SS, INTR >::reset()
|
||||||
//
|
//
|
||||||
// return( 0 );
|
// return( 0 );
|
||||||
//}
|
//}
|
||||||
|
|
||||||
/* initialize MAX3421E. Set Host mode, pullups, and stuff. Returns 0 if success, -1 if not */
|
/* initialize MAX3421E. Set Host mode, pullups, and stuff. Returns 0 if success, -1 if not */
|
||||||
template< typename SS, typename INTR >
|
template< typename SS, typename INTR >
|
||||||
int8_t MAX3421e< SS, INTR >::Init()
|
int8_t MAX3421e< SS, INTR >::Init() {
|
||||||
{
|
if (reset() == 0) { //OSCOKIRQ hasn't asserted in time
|
||||||
if( reset() == 0 )
|
|
||||||
{ //OSCOKIRQ hasn't asserted in time
|
|
||||||
return ( -1);
|
return ( -1);
|
||||||
}
|
}
|
||||||
regWr(rMODE, bmDPPULLDN | bmDMPULLDN | bmHOST); // set pull-downs, Host
|
regWr(rMODE, bmDPPULLDN | bmDMPULLDN | bmHOST); // set pull-downs, Host
|
||||||
|
@ -225,10 +218,9 @@ int8_t MAX3421e< SS, INTR >::Init()
|
||||||
return ( 0);
|
return ( 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* probe bus to determine device presense and speed and switch host to this speed */
|
/* probe bus to determine device presence and speed and switch host to this speed */
|
||||||
template< typename SS, typename INTR >
|
template< typename SS, typename INTR >
|
||||||
void MAX3421e< SS, INTR >::busprobe()
|
void MAX3421e< SS, INTR >::busprobe() {
|
||||||
{
|
|
||||||
uint8_t bus_sample;
|
uint8_t bus_sample;
|
||||||
bus_sample = regRd(rHRSL); //Get J,K status
|
bus_sample = regRd(rHRSL); //Get J,K status
|
||||||
bus_sample &= (bmJSTATUS | bmKSTATUS); //zero the rest of the byte
|
bus_sample &= (bmJSTATUS | bmKSTATUS); //zero the rest of the byte
|
||||||
|
@ -237,8 +229,7 @@ void MAX3421e< SS, INTR >::busprobe()
|
||||||
if ((regRd(rMODE) & bmLOWSPEED) == 0) {
|
if ((regRd(rMODE) & bmLOWSPEED) == 0) {
|
||||||
regWr(rMODE, MODE_FS_HOST); //start full-speed host
|
regWr(rMODE, MODE_FS_HOST); //start full-speed host
|
||||||
vbusState = FSHOST;
|
vbusState = FSHOST;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
regWr(rMODE, MODE_LS_HOST); //start low-speed host
|
regWr(rMODE, MODE_LS_HOST); //start low-speed host
|
||||||
vbusState = LSHOST;
|
vbusState = LSHOST;
|
||||||
}
|
}
|
||||||
|
@ -247,8 +238,7 @@ void MAX3421e< SS, INTR >::busprobe()
|
||||||
if ((regRd(rMODE) & bmLOWSPEED) == 0) {
|
if ((regRd(rMODE) & bmLOWSPEED) == 0) {
|
||||||
regWr(rMODE, MODE_LS_HOST); //start low-speed host
|
regWr(rMODE, MODE_LS_HOST); //start low-speed host
|
||||||
vbusState = LSHOST;
|
vbusState = LSHOST;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
regWr(rMODE, MODE_FS_HOST); //start full-speed host
|
regWr(rMODE, MODE_FS_HOST); //start full-speed host
|
||||||
vbusState = FSHOST;
|
vbusState = FSHOST;
|
||||||
}
|
}
|
||||||
|
@ -262,10 +252,10 @@ void MAX3421e< SS, INTR >::busprobe()
|
||||||
break;
|
break;
|
||||||
}//end switch( bus_sample )
|
}//end switch( bus_sample )
|
||||||
}
|
}
|
||||||
|
|
||||||
/* MAX3421 state change task and interrupt handler */
|
/* MAX3421 state change task and interrupt handler */
|
||||||
template< typename SS, typename INTR >
|
template< typename SS, typename INTR >
|
||||||
uint8_t MAX3421e< SS, INTR >::Task( void )
|
uint8_t MAX3421e< SS, INTR >::Task(void) {
|
||||||
{
|
|
||||||
uint8_t rcode = 0;
|
uint8_t rcode = 0;
|
||||||
uint8_t pinvalue;
|
uint8_t pinvalue;
|
||||||
//Serial.print("Vbus state: ");
|
//Serial.print("Vbus state: ");
|
||||||
|
@ -282,9 +272,9 @@ uint8_t MAX3421e< SS, INTR >::Task( void )
|
||||||
// usbSM(); //USB state machine
|
// usbSM(); //USB state machine
|
||||||
return ( rcode);
|
return ( rcode);
|
||||||
}
|
}
|
||||||
|
|
||||||
template< typename SS, typename INTR >
|
template< typename SS, typename INTR >
|
||||||
uint8_t MAX3421e< SS, INTR >::IntHandler()
|
uint8_t MAX3421e< SS, INTR >::IntHandler() {
|
||||||
{
|
|
||||||
uint8_t HIRQ;
|
uint8_t HIRQ;
|
||||||
uint8_t HIRQ_sendback = 0x00;
|
uint8_t HIRQ_sendback = 0x00;
|
||||||
HIRQ = regRd(rHIRQ); //determine interrupt source
|
HIRQ = regRd(rHIRQ); //determine interrupt source
|
||||||
|
|
56
usbhub.cpp
56
usbhub.cpp
|
@ -24,8 +24,7 @@ USBHub::USBHub(USB *p) :
|
||||||
bNbrPorts(0),
|
bNbrPorts(0),
|
||||||
bInitState(0),
|
bInitState(0),
|
||||||
qNextPollTime(0),
|
qNextPollTime(0),
|
||||||
bPollEnable(false)
|
bPollEnable(false) {
|
||||||
{
|
|
||||||
epInfo[0].epAddr = 0;
|
epInfo[0].epAddr = 0;
|
||||||
epInfo[0].maxPktSize = 8;
|
epInfo[0].maxPktSize = 8;
|
||||||
epInfo[0].epAttribs = 0;
|
epInfo[0].epAttribs = 0;
|
||||||
|
@ -40,8 +39,7 @@ USBHub::USBHub(USB *p) :
|
||||||
pUsb->RegisterDeviceClass(this);
|
pUsb->RegisterDeviceClass(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t USBHub::Init(uint8_t parent, uint8_t port, bool lowspeed)
|
uint8_t USBHub::Init(uint8_t parent, uint8_t port, bool lowspeed) {
|
||||||
{
|
|
||||||
uint8_t buf[32];
|
uint8_t buf[32];
|
||||||
uint8_t rcode;
|
uint8_t rcode;
|
||||||
UsbDevice *p = NULL;
|
UsbDevice *p = NULL;
|
||||||
|
@ -53,8 +51,7 @@ uint8_t USBHub::Init(uint8_t parent, uint8_t port, bool lowspeed)
|
||||||
|
|
||||||
AddressPool &addrPool = pUsb->GetAddressPool();
|
AddressPool &addrPool = pUsb->GetAddressPool();
|
||||||
|
|
||||||
switch (bInitState)
|
switch (bInitState) {
|
||||||
{
|
|
||||||
case 0:
|
case 0:
|
||||||
if (bAddress)
|
if (bAddress)
|
||||||
return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE;
|
return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE;
|
||||||
|
@ -84,8 +81,7 @@ uint8_t USBHub::Init(uint8_t parent, uint8_t port, bool lowspeed)
|
||||||
if (!rcode)
|
if (!rcode)
|
||||||
len = (buf[0] > 32) ? 32 : buf[0];
|
len = (buf[0] > 32) ? 32 : buf[0];
|
||||||
|
|
||||||
if( rcode )
|
if (rcode) {
|
||||||
{
|
|
||||||
// Restore p->epinfo
|
// Restore p->epinfo
|
||||||
p->epinfo = oldep_ptr;
|
p->epinfo = oldep_ptr;
|
||||||
return rcode;
|
return rcode;
|
||||||
|
@ -108,8 +104,7 @@ uint8_t USBHub::Init(uint8_t parent, uint8_t port, bool lowspeed)
|
||||||
// Assign new address to the device
|
// Assign new address to the device
|
||||||
rcode = pUsb->setAddr(0, 0, bAddress);
|
rcode = pUsb->setAddr(0, 0, bAddress);
|
||||||
|
|
||||||
if (rcode)
|
if (rcode) {
|
||||||
{
|
|
||||||
// Restore p->epinfo
|
// Restore p->epinfo
|
||||||
p->epinfo = oldep_ptr;
|
p->epinfo = oldep_ptr;
|
||||||
addrPool.FreeAddress(bAddress);
|
addrPool.FreeAddress(bAddress);
|
||||||
|
@ -152,8 +147,7 @@ uint8_t USBHub::Init(uint8_t parent, uint8_t port, bool lowspeed)
|
||||||
// Read configuration Descriptor in Order To Obtain Proper Configuration Value
|
// Read configuration Descriptor in Order To Obtain Proper Configuration Value
|
||||||
rcode = pUsb->getConfDescr(bAddress, 0, 8, 0, buf);
|
rcode = pUsb->getConfDescr(bAddress, 0, 8, 0, buf);
|
||||||
|
|
||||||
if (!rcode)
|
if (!rcode) {
|
||||||
{
|
|
||||||
cd_len = ((USB_CONFIGURATION_DESCRIPTOR*) buf)->wTotalLength;
|
cd_len = ((USB_CONFIGURATION_DESCRIPTOR*) buf)->wTotalLength;
|
||||||
rcode = pUsb->getConfDescr(bAddress, 0, cd_len, 0, buf);
|
rcode = pUsb->getConfDescr(bAddress, 0, cd_len, 0, buf);
|
||||||
}
|
}
|
||||||
|
@ -206,15 +200,11 @@ FailGetConfDescr:
|
||||||
FailSetConfDescr:
|
FailSetConfDescr:
|
||||||
goto Fail;
|
goto Fail;
|
||||||
|
|
||||||
FailGetPortStatus:
|
|
||||||
goto Fail;
|
|
||||||
|
|
||||||
Fail:
|
Fail:
|
||||||
return rcode;
|
return rcode;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t USBHub::Release()
|
uint8_t USBHub::Release() {
|
||||||
{
|
|
||||||
pUsb->GetAddressPool().FreeAddress(bAddress);
|
pUsb->GetAddressPool().FreeAddress(bAddress);
|
||||||
|
|
||||||
if (bAddress == 0x41)
|
if (bAddress == 0x41)
|
||||||
|
@ -227,23 +217,20 @@ uint8_t USBHub::Release()
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t USBHub::Poll()
|
uint8_t USBHub::Poll() {
|
||||||
{
|
|
||||||
uint8_t rcode = 0;
|
uint8_t rcode = 0;
|
||||||
|
|
||||||
if (!bPollEnable)
|
if (!bPollEnable)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (qNextPollTime <= millis())
|
if (qNextPollTime <= millis()) {
|
||||||
{
|
|
||||||
rcode = CheckHubStatus();
|
rcode = CheckHubStatus();
|
||||||
qNextPollTime = millis() + 100;
|
qNextPollTime = millis() + 100;
|
||||||
}
|
}
|
||||||
return rcode;
|
return rcode;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t USBHub::CheckHubStatus()
|
uint8_t USBHub::CheckHubStatus() {
|
||||||
{
|
|
||||||
uint8_t rcode;
|
uint8_t rcode;
|
||||||
uint8_t buf[8];
|
uint8_t buf[8];
|
||||||
uint16_t read = 1;
|
uint16_t read = 1;
|
||||||
|
@ -264,10 +251,8 @@ uint8_t USBHub::CheckHubStatus()
|
||||||
// return rcode;
|
// return rcode;
|
||||||
//}
|
//}
|
||||||
}
|
}
|
||||||
for (uint8_t port=1,mask=0x02; port<8; mask<<=1, port++)
|
for (uint8_t port = 1, mask = 0x02; port < 8; mask <<= 1, port++) {
|
||||||
{
|
if (buf[0] & mask) {
|
||||||
if (buf[0] & mask)
|
|
||||||
{
|
|
||||||
HubEvent evt;
|
HubEvent evt;
|
||||||
evt.bmEvent = 0;
|
evt.bmEvent = 0;
|
||||||
|
|
||||||
|
@ -286,8 +271,7 @@ uint8_t USBHub::CheckHubStatus()
|
||||||
}
|
}
|
||||||
} // for
|
} // for
|
||||||
|
|
||||||
for (uint8_t port=1; port<=bNbrPorts; port++)
|
for (uint8_t port = 1; port <= bNbrPorts; port++) {
|
||||||
{
|
|
||||||
HubEvent evt;
|
HubEvent evt;
|
||||||
evt.bmEvent = 0;
|
evt.bmEvent = 0;
|
||||||
|
|
||||||
|
@ -313,10 +297,8 @@ uint8_t USBHub::CheckHubStatus()
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t USBHub::PortStatusChange(uint8_t port, HubEvent &evt)
|
uint8_t USBHub::PortStatusChange(uint8_t port, HubEvent &evt) {
|
||||||
{
|
switch (evt.bmEvent) {
|
||||||
switch (evt.bmEvent)
|
|
||||||
{
|
|
||||||
// Device connected event
|
// Device connected event
|
||||||
case bmHUB_PORT_EVENT_CONNECT:
|
case bmHUB_PORT_EVENT_CONNECT:
|
||||||
case bmHUB_PORT_EVENT_LS_CONNECT:
|
case bmHUB_PORT_EVENT_LS_CONNECT:
|
||||||
|
@ -360,15 +342,13 @@ uint8_t USBHub::PortStatusChange(uint8_t port, HubEvent &evt)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrintHubPortStatus(USBHub *hubptr, uint8_t addr, uint8_t port, bool print_changes)
|
void PrintHubPortStatus(USBHub *hubptr, uint8_t addr, uint8_t port, bool print_changes) {
|
||||||
{
|
|
||||||
uint8_t rcode = 0;
|
uint8_t rcode = 0;
|
||||||
HubEvent evt;
|
HubEvent evt;
|
||||||
|
|
||||||
rcode = hubptr->GetPortStatus(port, 4, evt.evtBuff);
|
rcode = hubptr->GetPortStatus(port, 4, evt.evtBuff);
|
||||||
|
|
||||||
if (rcode)
|
if (rcode) {
|
||||||
{
|
|
||||||
Serial.println("ERROR!");
|
Serial.println("ERROR!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -400,7 +380,7 @@ void PrintHubPortStatus(USBHub *hubptr, uint8_t addr, uint8_t port, bool print_c
|
||||||
if (!print_changes)
|
if (!print_changes)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Serial.println("\nChange");
|
Serial.println("\r\nChange");
|
||||||
Serial.print("CONNECTION:\t");
|
Serial.print("CONNECTION:\t");
|
||||||
Serial.println((evt.bmChange & bmHUB_PORT_STATUS_C_PORT_CONNECTION) > 0, DEC);
|
Serial.println((evt.bmChange & bmHUB_PORT_STATUS_C_PORT_CONNECTION) > 0, DEC);
|
||||||
Serial.print("ENABLE:\t\t");
|
Serial.print("ENABLE:\t\t");
|
||||||
|
|
66
usbhub.h
66
usbhub.h
|
@ -25,6 +25,7 @@ e-mail : support@circuitsathome.com
|
||||||
#include "usb_ch9.h"
|
#include "usb_ch9.h"
|
||||||
#include "Usb.h"
|
#include "Usb.h"
|
||||||
|
|
||||||
|
|
||||||
#if defined(ARDUINO) && ARDUINO >=100
|
#if defined(ARDUINO) && ARDUINO >=100
|
||||||
#include "Arduino.h"
|
#include "Arduino.h"
|
||||||
#else
|
#else
|
||||||
|
@ -142,42 +143,38 @@ e-mail : support@circuitsathome.com
|
||||||
#define bmHUB_PORT_EVENT_LS_RESET_COMPLETE (((0UL | bmHUB_PORT_STATUS_C_PORT_RESET) << 16) | bmHUB_PORT_STATUS_PORT_POWER | bmHUB_PORT_STATUS_PORT_ENABLE | bmHUB_PORT_STATUS_PORT_CONNECTION | bmHUB_PORT_STATUS_PORT_LOW_SPEED)
|
#define bmHUB_PORT_EVENT_LS_RESET_COMPLETE (((0UL | bmHUB_PORT_STATUS_C_PORT_RESET) << 16) | bmHUB_PORT_STATUS_PORT_POWER | bmHUB_PORT_STATUS_PORT_ENABLE | bmHUB_PORT_STATUS_PORT_CONNECTION | bmHUB_PORT_STATUS_PORT_LOW_SPEED)
|
||||||
#define bmHUB_PORT_EVENT_LS_PORT_ENABLED (((0UL | bmHUB_PORT_STATUS_C_PORT_CONNECTION | bmHUB_PORT_STATUS_C_PORT_ENABLE) << 16) | bmHUB_PORT_STATUS_PORT_POWER | bmHUB_PORT_STATUS_PORT_ENABLE | bmHUB_PORT_STATUS_PORT_CONNECTION | bmHUB_PORT_STATUS_PORT_LOW_SPEED)
|
#define bmHUB_PORT_EVENT_LS_PORT_ENABLED (((0UL | bmHUB_PORT_STATUS_C_PORT_CONNECTION | bmHUB_PORT_STATUS_C_PORT_ENABLE) << 16) | bmHUB_PORT_STATUS_PORT_POWER | bmHUB_PORT_STATUS_PORT_ENABLE | bmHUB_PORT_STATUS_PORT_CONNECTION | bmHUB_PORT_STATUS_PORT_LOW_SPEED)
|
||||||
|
|
||||||
struct HubDescriptor
|
struct HubDescriptor {
|
||||||
{
|
|
||||||
uint8_t bDescLength; // descriptor length
|
uint8_t bDescLength; // descriptor length
|
||||||
uint8_t bDescriptorType; // descriptor type
|
uint8_t bDescriptorType; // descriptor type
|
||||||
uint8_t bNbrPorts; // number of ports a hub equiped with
|
uint8_t bNbrPorts; // number of ports a hub equiped with
|
||||||
|
|
||||||
struct
|
struct {
|
||||||
{
|
|
||||||
uint16_t LogPwrSwitchMode : 2;
|
uint16_t LogPwrSwitchMode : 2;
|
||||||
uint16_t CompoundDevice : 1;
|
uint16_t CompoundDevice : 1;
|
||||||
uint16_t OverCurrentProtectMode : 2;
|
uint16_t OverCurrentProtectMode : 2;
|
||||||
uint16_t TTThinkTime : 2;
|
uint16_t TTThinkTime : 2;
|
||||||
uint16_t PortIndicatorsSupported : 1;
|
uint16_t PortIndicatorsSupported : 1;
|
||||||
uint16_t Reserved : 8;
|
uint16_t Reserved : 8;
|
||||||
};
|
}__attribute__((packed));
|
||||||
|
|
||||||
uint8_t bPwrOn2PwrGood;
|
uint8_t bPwrOn2PwrGood;
|
||||||
uint8_t bHubContrCurrent;
|
uint8_t bHubContrCurrent;
|
||||||
};
|
}__attribute__((packed));
|
||||||
|
|
||||||
struct HubEvent
|
struct HubEvent {
|
||||||
{
|
|
||||||
union
|
union {
|
||||||
{
|
|
||||||
struct
|
struct {
|
||||||
{
|
|
||||||
uint16_t bmStatus; // port status bits
|
uint16_t bmStatus; // port status bits
|
||||||
uint16_t bmChange; // port status change bits
|
uint16_t bmChange; // port status change bits
|
||||||
};
|
}__attribute__((packed));
|
||||||
uint32_t bmEvent;
|
uint32_t bmEvent;
|
||||||
uint8_t evtBuff[4];
|
uint8_t evtBuff[4];
|
||||||
};
|
};
|
||||||
};
|
}__attribute__((packed));
|
||||||
|
|
||||||
class USBHub : USBDeviceConfig
|
class USBHub : USBDeviceConfig {
|
||||||
{
|
|
||||||
static bool bResetInitiated; // True when reset is triggered
|
static bool bResetInitiated; // True when reset is triggered
|
||||||
|
|
||||||
USB *pUsb; // USB class instance pointer
|
USB *pUsb; // USB class instance pointer
|
||||||
|
@ -210,47 +207,50 @@ public:
|
||||||
virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed);
|
virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed);
|
||||||
virtual uint8_t Release();
|
virtual uint8_t Release();
|
||||||
virtual uint8_t Poll();
|
virtual uint8_t Poll();
|
||||||
virtual uint8_t GetAddress() { return bAddress; };
|
|
||||||
|
virtual uint8_t GetAddress() {
|
||||||
|
return bAddress;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
// Clear Hub Feature
|
// Clear Hub Feature
|
||||||
inline uint8_t USBHub::ClearHubFeature( uint8_t fid )
|
|
||||||
{
|
inline uint8_t USBHub::ClearHubFeature(uint8_t fid) {
|
||||||
return ( pUsb->ctrlReq(bAddress, 0, bmREQ_CLEAR_HUB_FEATURE, USB_REQUEST_CLEAR_FEATURE, fid, 0, 0, 0, 0, NULL, NULL));
|
return ( pUsb->ctrlReq(bAddress, 0, bmREQ_CLEAR_HUB_FEATURE, USB_REQUEST_CLEAR_FEATURE, fid, 0, 0, 0, 0, NULL, NULL));
|
||||||
}
|
}
|
||||||
// Clear Port Feature
|
// Clear Port Feature
|
||||||
inline uint8_t USBHub::ClearPortFeature( uint8_t fid, uint8_t port, uint8_t sel )
|
|
||||||
{
|
inline uint8_t USBHub::ClearPortFeature(uint8_t fid, uint8_t port, uint8_t sel) {
|
||||||
return ( pUsb->ctrlReq(bAddress, 0, bmREQ_CLEAR_PORT_FEATURE, USB_REQUEST_CLEAR_FEATURE, fid, 0, ((0x0000 | port) | (sel << 8)), 0, 0, NULL, NULL));
|
return ( pUsb->ctrlReq(bAddress, 0, bmREQ_CLEAR_PORT_FEATURE, USB_REQUEST_CLEAR_FEATURE, fid, 0, ((0x0000 | port) | (sel << 8)), 0, 0, NULL, NULL));
|
||||||
}
|
}
|
||||||
// Get Hub Descriptor
|
// Get Hub Descriptor
|
||||||
inline uint8_t USBHub::GetHubDescriptor( uint8_t index, uint16_t nbytes, uint8_t *dataptr )
|
|
||||||
{
|
inline uint8_t USBHub::GetHubDescriptor(uint8_t index, uint16_t nbytes, uint8_t *dataptr) {
|
||||||
return ( pUsb->ctrlReq(bAddress, 0, bmREQ_GET_HUB_DESCRIPTOR, USB_REQUEST_GET_DESCRIPTOR, index, 0x29, 0, nbytes, nbytes, dataptr, NULL));
|
return ( pUsb->ctrlReq(bAddress, 0, bmREQ_GET_HUB_DESCRIPTOR, USB_REQUEST_GET_DESCRIPTOR, index, 0x29, 0, nbytes, nbytes, dataptr, NULL));
|
||||||
}
|
}
|
||||||
// Get Hub Status
|
// Get Hub Status
|
||||||
inline uint8_t USBHub::GetHubStatus( uint16_t nbytes, uint8_t* dataptr )
|
|
||||||
{
|
inline uint8_t USBHub::GetHubStatus(uint16_t nbytes, uint8_t* dataptr) {
|
||||||
return ( pUsb->ctrlReq(bAddress, 0, bmREQ_GET_HUB_STATUS, USB_REQUEST_GET_STATUS, 0, 0, 0x0000, nbytes, nbytes, dataptr, NULL));
|
return ( pUsb->ctrlReq(bAddress, 0, bmREQ_GET_HUB_STATUS, USB_REQUEST_GET_STATUS, 0, 0, 0x0000, nbytes, nbytes, dataptr, NULL));
|
||||||
}
|
}
|
||||||
// Get Port Status
|
// Get Port Status
|
||||||
inline uint8_t USBHub::GetPortStatus( uint8_t port, uint16_t nbytes, uint8_t* dataptr )
|
|
||||||
{
|
inline uint8_t USBHub::GetPortStatus(uint8_t port, uint16_t nbytes, uint8_t* dataptr) {
|
||||||
return ( pUsb->ctrlReq(bAddress, 0, bmREQ_GET_PORT_STATUS, USB_REQUEST_GET_STATUS, 0, 0, port, nbytes, nbytes, dataptr, NULL));
|
return ( pUsb->ctrlReq(bAddress, 0, bmREQ_GET_PORT_STATUS, USB_REQUEST_GET_STATUS, 0, 0, port, nbytes, nbytes, dataptr, NULL));
|
||||||
}
|
}
|
||||||
// Set Hub Descriptor
|
// Set Hub Descriptor
|
||||||
inline uint8_t USBHub::SetHubDescriptor( uint8_t port, uint16_t nbytes, uint8_t* dataptr )
|
|
||||||
{
|
inline uint8_t USBHub::SetHubDescriptor(uint8_t port, uint16_t nbytes, uint8_t* dataptr) {
|
||||||
return ( pUsb->ctrlReq(bAddress, 0, bmREQ_SET_HUB_DESCRIPTOR, USB_REQUEST_SET_DESCRIPTOR, 0, 0, port, nbytes, nbytes, dataptr, NULL));
|
return ( pUsb->ctrlReq(bAddress, 0, bmREQ_SET_HUB_DESCRIPTOR, USB_REQUEST_SET_DESCRIPTOR, 0, 0, port, nbytes, nbytes, dataptr, NULL));
|
||||||
}
|
}
|
||||||
// Set Hub Feature
|
// Set Hub Feature
|
||||||
inline uint8_t USBHub::SetHubFeature( uint8_t fid )
|
|
||||||
{
|
inline uint8_t USBHub::SetHubFeature(uint8_t fid) {
|
||||||
return ( pUsb->ctrlReq(bAddress, 0, bmREQ_SET_HUB_FEATURE, USB_REQUEST_SET_FEATURE, fid, 0, 0, 0, 0, NULL, NULL));
|
return ( pUsb->ctrlReq(bAddress, 0, bmREQ_SET_HUB_FEATURE, USB_REQUEST_SET_FEATURE, fid, 0, 0, 0, 0, NULL, NULL));
|
||||||
}
|
}
|
||||||
// Set Port Feature
|
// Set Port Feature
|
||||||
inline uint8_t USBHub::SetPortFeature( uint8_t fid, uint8_t port, uint8_t sel )
|
|
||||||
{
|
inline uint8_t USBHub::SetPortFeature(uint8_t fid, uint8_t port, uint8_t sel) {
|
||||||
return ( pUsb->ctrlReq(bAddress, 0, bmREQ_SET_PORT_FEATURE, USB_REQUEST_SET_FEATURE, fid, 0, (((0x0000 | sel) << 8) | port), 0, 0, NULL, NULL));
|
return ( pUsb->ctrlReq(bAddress, 0, bmREQ_SET_PORT_FEATURE, USB_REQUEST_SET_FEATURE, fid, 0, (((0x0000 | sel) << 8) | port), 0, 0, NULL, NULL));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue