From 629594f957f8adfd101a4f069c6ad6ee52b4efd1 Mon Sep 17 00:00:00 2001 From: "Andrew J. Kroll" Date: Thu, 28 Mar 2013 03:26:02 -0400 Subject: [PATCH 1/7] Merge my debug changes. Merge my format sanity changes. Track everything. --- Usb.cpp | 932 ++++++----- Usb.h | 279 ++-- address.h | 400 +++-- adk.cpp | 715 ++++----- adk.h | 292 ++-- avrpins.h | 476 +++--- cdcacm.cpp | 696 ++++---- cdcacm.h | 394 +++-- cdcftdi.cpp | 680 ++++---- cdcftdi.h | 299 ++-- cdcprolific.cpp | 444 +++--- cdcprolific.h | 330 ++-- confdescparser.h | 432 +++-- gpl2.txt | 680 ++++---- hexdump.h | 115 +- hid.cpp | 166 +- hid.h | 400 ++--- hidboot.cpp | 293 ++-- hidboot.h | 987 ++++++------ hidescriptorparser.cpp | 3337 +++++++++++++++++++-------------------- hidescriptorparser.h | 384 +++-- hiduniversal.cpp | 796 +++++----- hiduniversal.h | 152 +- hidusagestr.h | 1952 +++++++++++------------ hidusagetitlearrays.cpp | 2092 ++++++++++++------------ masstorage.cpp | 1507 ++++++++++-------- masstorage.h | 528 ++++--- max3421e.h | 10 +- max_LCD.cpp | 506 +++--- max_LCD.h | 202 +-- message.cpp | 78 +- message.h | 76 +- parsetools.cpp | 139 +- parsetools.h | 300 ++-- printhex.h | 137 +- usb_ch9.h | 122 +- usbhost.h | 402 +++-- usbhub.cpp | 578 ++++--- usbhub.h | 172 +- 39 files changed, 11136 insertions(+), 11344 deletions(-) diff --git a/Usb.cpp b/Usb.cpp index 08e017c6..3a6ea5db 100644 --- a/Usb.cpp +++ b/Usb.cpp @@ -13,7 +13,7 @@ Contact information Circuits At Home, LTD Web : http://www.circuitsathome.com e-mail : support@circuitsathome.com -*/ + */ /* USB functions */ #include "avrpins.h" @@ -31,611 +31,587 @@ static uint8_t usb_error = 0; static uint8_t usb_task_state; /* constructor */ -USB::USB () : bmHubPre(0) -{ - usb_task_state = USB_DETACHED_SUBSTATE_INITIALIZE; //set up state machine - init(); +USB::USB() : bmHubPre(0) { + usb_task_state = USB_DETACHED_SUBSTATE_INITIALIZE; //set up state machine + init(); } /* Initialize data structures */ -void USB::init() -{ - devConfigIndex = 0; - bmHubPre = 0; +void USB::init() { + devConfigIndex = 0; + bmHubPre = 0; } -uint8_t USB::getUsbTaskState( void ) -{ - return( usb_task_state ); +uint8_t USB::getUsbTaskState(void) { + return ( usb_task_state); } -void USB::setUsbTaskState( uint8_t state ) -{ - usb_task_state = state; -} +void USB::setUsbTaskState(uint8_t state) { + usb_task_state = state; +} -EpInfo* USB::getEpInfoEntry( uint8_t addr, uint8_t ep ) -{ - UsbDevice *p = addrPool.GetUsbDevicePtr(addr); +EpInfo* USB::getEpInfoEntry(uint8_t addr, uint8_t ep) { + UsbDevice *p = addrPool.GetUsbDevicePtr(addr); - if (!p || !p->epinfo) - return NULL; + if (!p || !p->epinfo) + return NULL; - EpInfo *pep = p->epinfo; + EpInfo *pep = p->epinfo; - for (uint8_t i=0; iepcount; i++) - { - if ((pep)->epAddr == ep) - return pep; + for (uint8_t i = 0; i < p->epcount; i++) { + if ((pep)->epAddr == ep) + return pep; - pep ++; - } - return NULL; + pep++; + } + return NULL; } /* 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 */ -uint8_t USB::setEpInfoEntry( uint8_t addr, uint8_t epcount, EpInfo* eprecord_ptr ) -{ - if (!eprecord_ptr) - return USB_ERROR_INVALID_ARGUMENT; +uint8_t USB::setEpInfoEntry(uint8_t addr, uint8_t epcount, EpInfo* eprecord_ptr) { + if (!eprecord_ptr) + return USB_ERROR_INVALID_ARGUMENT; - UsbDevice *p = addrPool.GetUsbDevicePtr(addr); + UsbDevice *p = addrPool.GetUsbDevicePtr(addr); - if (!p) - return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; - - p->address = addr; - p->epinfo = eprecord_ptr; - p->epcount = epcount; + if (!p) + return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; - return 0; + p->address = addr; + p->epinfo = eprecord_ptr; + p->epcount = epcount; + + return 0; } -uint8_t USB::SetAddress(uint8_t addr, uint8_t ep, EpInfo **ppep, uint16_t &nak_limit) -{ - UsbDevice *p = addrPool.GetUsbDevicePtr(addr); +uint8_t USB::SetAddress(uint8_t addr, uint8_t ep, EpInfo **ppep, uint16_t &nak_limit) { + UsbDevice *p = addrPool.GetUsbDevicePtr(addr); - if (!p) - return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; + if (!p) + return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; - if (!p->epinfo) - return USB_ERROR_EPINFO_IS_NULL; + if (!p->epinfo) + return USB_ERROR_EPINFO_IS_NULL; - *ppep = getEpInfoEntry(addr, ep); + *ppep = getEpInfoEntry(addr, ep); - if (!*ppep) - return USB_ERROR_EP_NOT_FOUND_IN_TBL; + if (!*ppep) + return USB_ERROR_EP_NOT_FOUND_IN_TBL; - nak_limit = (0x0001UL << ( ( (*ppep)->bmNakPower > USB_NAK_MAX_POWER ) ? USB_NAK_MAX_POWER : (*ppep)->bmNakPower) ); - nak_limit--; - -/* - USBTRACE2("\r\nAddress: ", addr); - USBTRACE2(" EP: ", ep); - USBTRACE2(" NAK Power: ",(*ppep)->bmNakPower); - USBTRACE2(" NAK Limit: ", nak_limit); - USBTRACE("\r\n"); -*/ - regWr( rPERADDR, addr ); //set peripheral address + nak_limit = (0x0001UL << (((*ppep)->bmNakPower > USB_NAK_MAX_POWER) ? USB_NAK_MAX_POWER : (*ppep)->bmNakPower)); + nak_limit--; + /* + USBTRACE2("\r\nAddress: ", addr); + USBTRACE2(" EP: ", ep); + USBTRACE2(" NAK Power: ",(*ppep)->bmNakPower); + USBTRACE2(" NAK Limit: ", nak_limit); + USBTRACE("\r\n"); + */ + regWr(rPERADDR, addr); //set peripheral address - uint8_t mode = regRd( rMODE ); + uint8_t mode = regRd(rMODE); - // Set bmLOWSPEED and bmHUBPRE in case of low-speed device, reset them otherwise - regWr( rMODE, (p->lowspeed) ? mode | bmLOWSPEED | bmHubPre : mode & ~(bmHUBPRE | bmLOWSPEED)); + // Set bmLOWSPEED and bmHUBPRE in case of low-speed device, reset them otherwise + regWr(rMODE, (p->lowspeed) ? mode | bmLOWSPEED | bmHubPre : mode & ~(bmHUBPRE | bmLOWSPEED)); - return 0; + return 0; } /* Control transfer. Sets address, endpoint, fills control packet with necessary data, dispatches control packet, and initiates bulk IN transfer, */ /* depending on request. Actual requests are defined as inlines */ /* return codes: */ /* 00 = success */ + /* 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, - uint16_t wInd, uint16_t total, uint16_t nbytes, uint8_t* dataptr, USBReadParser *p) -{ - boolean direction = false; //request direction, IN or OUT - uint8_t rcode; - SETUP_PKT setup_pkt; +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) { + bool direction = false; //request direction, IN or OUT + uint8_t rcode; + SETUP_PKT setup_pkt; - EpInfo *pep = NULL; - uint16_t nak_limit; + EpInfo *pep = NULL; + uint16_t nak_limit; - rcode = SetAddress(addr, ep, &pep, nak_limit); + rcode = SetAddress(addr, ep, &pep, nak_limit); - if (rcode) - return rcode; + if (rcode) + return rcode; - direction = (( bmReqType & 0x80 ) > 0); + direction = ((bmReqType & 0x80) > 0); - /* fill in setup packet */ - setup_pkt.ReqType_u.bmRequestType = bmReqType; - setup_pkt.bRequest = bRequest; - setup_pkt.wVal_u.wValueLo = wValLo; - setup_pkt.wVal_u.wValueHi = wValHi; - setup_pkt.wIndex = wInd; - setup_pkt.wLength = total; - - bytesWr( rSUDFIFO, 8, (uint8_t*)&setup_pkt ); //transfer to setup packet FIFO + /* fill in setup packet */ + setup_pkt.ReqType_u.bmRequestType = bmReqType; + setup_pkt.bRequest = bRequest; + setup_pkt.wVal_u.wValueLo = wValLo; + setup_pkt.wVal_u.wValueHi = wValHi; + setup_pkt.wIndex = wInd; + setup_pkt.wLength = total; - rcode = dispatchPkt( tokSETUP, ep, nak_limit ); //dispatch packet + bytesWr(rSUDFIFO, 8, (uint8_t*) & setup_pkt); //transfer to setup packet FIFO - if( rcode ) //return HRSLT if not zero - return( rcode ); + rcode = dispatchPkt(tokSETUP, ep, nak_limit); //dispatch packet - if( dataptr != NULL ) //data stage, if present - { - if( direction ) //IN transfer - { - uint16_t left = total; + if (rcode) //return HRSLT if not zero + return ( rcode); - pep->bmRcvToggle = 1; //bmRCVTOG1; + if (dataptr != NULL) //data stage, if present + { + if (direction) //IN transfer + { + uint16_t left = total; - while (left) - { - // Bytes read into buffer - uint16_t read = nbytes; - //uint16_t read = (leftbmRcvToggle = 1; //bmRCVTOG1; - rcode = InTransfer( pep, nak_limit, &read, dataptr ); + while (left) { + // Bytes read into buffer + uint16_t read = nbytes; + //uint16_t read = (leftParse( read, dataptr, total - left ); + if (rcode) + return rcode; - left -= read; + // Invoke callback function if inTransfer completed successfuly and callback function pointer is specified + if (!rcode && p) + ((USBReadParser*) p)->Parse(read, dataptr, total - left); - if (read < nbytes) - break; - } - } - else //OUT transfer - { - pep->bmSndToggle = 1; //bmSNDTOG1; - rcode = OutTransfer( pep, nak_limit, nbytes, dataptr ); - } - if( rcode ) //return error - return( rcode ); - } - // Status stage - return dispatchPkt( (direction) ? tokOUTHS : tokINHS, ep, nak_limit ); //GET if direction + left -= read; + + if (read < nbytes) + break; + } + } else //OUT transfer + { + pep->bmSndToggle = 1; //bmSNDTOG1; + rcode = OutTransfer(pep, nak_limit, nbytes, dataptr); + } + if (rcode) //return error + return ( rcode); + } + // Status stage + return dispatchPkt((direction) ? tokOUTHS : tokINHS, ep, nak_limit); //GET if direction } /* 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' */ + /* rcode 0 if no errors. rcode 01-0f is relayed from dispatchPkt(). Rcode f0 means RCVDAVIRQ error, fe USB xfer timeout */ -uint8_t USB::inTransfer( uint8_t addr, uint8_t ep, uint16_t *nbytesptr, uint8_t* data) -{ - EpInfo *pep = NULL; - uint16_t nak_limit = 0; +uint8_t USB::inTransfer(uint8_t addr, uint8_t ep, uint16_t *nbytesptr, uint8_t* data) { + EpInfo *pep = NULL; + 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) - return rcode; - - return InTransfer(pep, nak_limit, nbytesptr, data); + if (rcode) { + //printf("SetAddress Failed"); + return rcode; + } + 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 rcode = 0; - uint8_t pktsize; +uint8_t USB::InTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t *nbytesptr, uint8_t* data) { + uint8_t rcode = 0; + uint8_t pktsize; - uint16_t nbytes = *nbytesptr; - uint8_t maxpktsize = pep->maxPktSize; + uint16_t nbytes = *nbytesptr; + //printf("Requesting %i bytes ", nbytes); + uint8_t maxpktsize = pep->maxPktSize; - *nbytesptr = 0; - regWr( rHCTL, (pep->bmRcvToggle) ? bmRCVTOG1 : bmRCVTOG0 ); //set toggle value + *nbytesptr = 0; + regWr(rHCTL, (pep->bmRcvToggle) ? bmRCVTOG1 : bmRCVTOG0); //set toggle value - while( 1 ) // use a 'return' to exit this loop - { - rcode = dispatchPkt( tokIN, pep->epAddr, nak_limit ); //IN packet to EP-'endpoint'. Function takes care of NAKS. - - if( rcode ) - return( rcode ); //should be 0, indicating ACK. Else return error code. - - /* 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 */ - if(( regRd( rHIRQ ) & bmRCVDAVIRQ ) == 0 ) - return ( 0xf0 ); //receive error - - pktsize = regRd( rRCVBC ); //number of received bytes - - assert(pktsize <= nbytes); - - int16_t mem_left = (int16_t)nbytes - *((int16_t*)nbytesptr); + while (1) // use a 'return' to exit this loop + { + rcode = dispatchPkt(tokIN, pep->epAddr, nak_limit); //IN packet to EP-'endpoint'. Function takes care of NAKS. - if (mem_left < 0) - mem_left = 0; + if (rcode) { + //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 */ + /* 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) { + //printf("Problem! NO RCVDAVIRQ!\r\n"); + rcode = 0xf0; //receive error + break; + } + pktsize = regRd(rRCVBC); //number of received bytes + //printf("Got %i bytes ", pktsize); + assert(pktsize <= nbytes); - data = bytesRd( rRCVFIFO, ((pktsize > mem_left) ? mem_left : pktsize), data ); + int16_t mem_left = (int16_t) nbytes - *((int16_t*) nbytesptr); - regWr( rHIRQ, bmRCVDAVIRQ ); // Clear the IRQ & free the buffer - *nbytesptr += pktsize; // add this packet's byte count to total transfer length + if (mem_left < 0) + mem_left = 0; - /* The transfer is complete under two conditions: */ - /* 1. The device sent a short packet (L.T. maxPacketSize) */ - /* 2. 'nbytes' have been transferred. */ - if (( pktsize < maxpktsize ) || (*nbytesptr >= nbytes )) // have we transferred 'nbytes' bytes? - { - // Save toggle value - pep->bmRcvToggle = (( regRd( rHRSL ) & bmRCVTOGRD )) ? 1 : 0; + data = bytesRd(rRCVFIFO, ((pktsize > mem_left) ? mem_left : pktsize), data); - return( 0 ); - } // if - } //while( 1 ) + regWr(rHIRQ, bmRCVDAVIRQ); // Clear the IRQ & free the buffer + *nbytesptr += pktsize; // add this packet's byte count to total transfer length + + /* The transfer is complete under two conditions: */ + /* 1. The device sent a short packet (L.T. maxPacketSize) */ + /* 2. 'nbytes' have been transferred. */ + if ((pktsize < maxpktsize) || (*nbytesptr >= nbytes)) // have we transferred 'nbytes' bytes? + { + // Save toggle value + pep->bmRcvToggle = ((regRd(rHRSL) & bmRCVTOGRD)) ? 1 : 0; + //printf("\r\n"); + rcode = 0; + break; + } // if + } //while( 1 ) + return ( rcode); } /* 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 */ + /* 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 ) -{ - EpInfo *pep = NULL; - uint16_t nak_limit; +uint8_t USB::outTransfer(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* data) { + EpInfo *pep = NULL; + uint16_t nak_limit; - uint8_t rcode = SetAddress(addr, ep, &pep, nak_limit); + uint8_t rcode = SetAddress(addr, ep, &pep, nak_limit); - if (rcode) - return rcode; + if (rcode) + return rcode; - 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 rcode, retry_count; - uint8_t *data_p = data; //local copy of the data pointer - uint16_t bytes_tosend, nak_count; - uint16_t bytes_left = nbytes; +uint8_t USB::OutTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t nbytes, uint8_t *data) { + uint8_t rcode = hrSUCCESS, retry_count; + uint8_t *data_p = data; //local copy of the data pointer + uint16_t bytes_tosend, nak_count; + uint16_t bytes_left = nbytes; - uint8_t maxpktsize = pep->maxPktSize; - - if (maxpktsize < 1 || maxpktsize > 64) - return USB_ERROR_INVALID_MAX_PKT_SIZE; - - unsigned long timeout = millis() + USB_XFER_TIMEOUT; - - regWr( rHCTL, (pep->bmSndToggle) ? bmSNDTOG1 : bmSNDTOG0 ); //set toggle value - - while( bytes_left ) - { - retry_count = 0; - nak_count = 0; - bytes_tosend = ( bytes_left >= maxpktsize ) ? maxpktsize : bytes_left; - bytesWr( rSNDFIFO, bytes_tosend, data_p ); //filling output FIFO - regWr( rSNDBC, bytes_tosend ); //set number of bytes - regWr( rHXFR, ( tokOUT | pep->epAddr )); //dispatch packet - while(!(regRd( rHIRQ ) & bmHXFRDNIRQ )); //wait for the completion IRQ - regWr( rHIRQ, bmHXFRDNIRQ ); //clear IRQ - rcode = ( regRd( rHRSL ) & 0x0f ); + uint8_t maxpktsize = pep->maxPktSize; - while( rcode && ( timeout > millis())) - { - switch( rcode ) - { - case hrNAK: - nak_count ++; - if( nak_limit && ( nak_count == nak_limit )) - return( rcode ); - break; - case hrTIMEOUT: - retry_count ++; - if( retry_count == USB_RETRY_LIMIT ) - return( rcode ); - break; - default: - return( rcode ); - }//switch( rcode + if (maxpktsize < 1 || maxpktsize > 64) + return USB_ERROR_INVALID_MAX_PKT_SIZE; - /* process NAK according to Host out NAK bug */ - regWr( rSNDBC, 0 ); - regWr( rSNDFIFO, *data_p ); - regWr( rSNDBC, bytes_tosend ); - regWr( rHXFR, ( tokOUT | pep->epAddr )); //dispatch packet - while(!(regRd( rHIRQ ) & bmHXFRDNIRQ )); //wait for the completion IRQ - regWr( rHIRQ, bmHXFRDNIRQ ); //clear IRQ - rcode = ( regRd( rHRSL ) & 0x0f ); - }//while( rcode && .... - bytes_left -= bytes_tosend; - data_p += bytes_tosend; - }//while( bytes_left... - pep->bmSndToggle = ( regRd( rHRSL ) & bmSNDTOGRD ) ? 1 : 0; //bmSNDTOG1 : bmSNDTOG0; //update toggle - return( rcode ); //should be 0 in all cases + unsigned long timeout = millis() + USB_XFER_TIMEOUT; + + regWr(rHCTL, (pep->bmSndToggle) ? bmSNDTOG1 : bmSNDTOG0); //set toggle value + + while (bytes_left) { + retry_count = 0; + nak_count = 0; + bytes_tosend = (bytes_left >= maxpktsize) ? maxpktsize : bytes_left; + bytesWr(rSNDFIFO, bytes_tosend, data_p); //filling output FIFO + regWr(rSNDBC, bytes_tosend); //set number of bytes + regWr(rHXFR, (tokOUT | pep->epAddr)); //dispatch packet + while (!(regRd(rHIRQ) & bmHXFRDNIRQ)); //wait for the completion IRQ + regWr(rHIRQ, bmHXFRDNIRQ); //clear IRQ + rcode = (regRd(rHRSL) & 0x0f); + + while (rcode && (timeout > millis())) { + switch (rcode) { + case hrNAK: + nak_count++; + if (nak_limit && (nak_count == nak_limit)) + return ( rcode); + break; + case hrTIMEOUT: + retry_count++; + if (retry_count == USB_RETRY_LIMIT) + return ( rcode); + break; + default: + return ( rcode); + }//switch( rcode + + /* process NAK according to Host out NAK bug */ + regWr(rSNDBC, 0); + regWr(rSNDFIFO, *data_p); + regWr(rSNDBC, bytes_tosend); + regWr(rHXFR, (tokOUT | pep->epAddr)); //dispatch packet + while (!(regRd(rHIRQ) & bmHXFRDNIRQ)); //wait for the completion IRQ + regWr(rHIRQ, bmHXFRDNIRQ); //clear IRQ + rcode = (regRd(rHRSL) & 0x0f); + }//while( rcode && .... + bytes_left -= bytes_tosend; + data_p += bytes_tosend; + }//while( bytes_left... + pep->bmSndToggle = (regRd(rHRSL) & bmSNDTOGRD) ? 1 : 0; //bmSNDTOG1 : bmSNDTOG0; //update toggle + return ( rcode); //should be 0 in all cases } /* dispatch usb packet. Assumes peripheral address is set and relevant buffer is loaded/empty */ /* If NAK, tries to re-send up to nak_limit times */ /* If nak_limit == 0, do not count NAKs, exit after timeout */ /* If bus timeout, re-sends up to USB_RETRY_LIMIT times */ + /* 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 ) -{ - unsigned long timeout = millis() + USB_XFER_TIMEOUT; - uint8_t tmpdata; - uint8_t rcode; - uint8_t retry_count = 0; - uint16_t nak_count = 0; +uint8_t USB::dispatchPkt(uint8_t token, uint8_t ep, uint16_t nak_limit) { + unsigned long timeout = millis() + USB_XFER_TIMEOUT; + uint8_t tmpdata; + uint8_t rcode = hrSUCCESS; + uint8_t retry_count = 0; + uint16_t nak_count = 0; - while( timeout > millis() ) - { - regWr( rHXFR, ( token|ep )); //launch the transfer - rcode = USB_ERROR_TRANSFER_TIMEOUT; + while (timeout > millis()) { + regWr(rHXFR, (token | ep)); //launch the transfer + rcode = USB_ERROR_TRANSFER_TIMEOUT; - while( millis() < timeout ) //wait for transfer completion - { - tmpdata = regRd( rHIRQ ); + while (millis() < timeout) //wait for transfer completion + { + tmpdata = regRd(rHIRQ); - if( tmpdata & bmHXFRDNIRQ ) - { - regWr( rHIRQ, bmHXFRDNIRQ ); //clear the interrupt - rcode = 0x00; - break; - }//if( tmpdata & bmHXFRDNIRQ + if (tmpdata & bmHXFRDNIRQ) { + regWr(rHIRQ, bmHXFRDNIRQ); //clear the interrupt + rcode = 0x00; + break; + }//if( tmpdata & bmHXFRDNIRQ - }//while ( millis() < timeout + }//while ( millis() < timeout - if( rcode != 0x00 ) //exit if timeout - return( rcode ); + if (rcode != 0x00) //exit if timeout + return ( rcode); - rcode = ( regRd( rHRSL ) & 0x0f ); //analyze transfer result + rcode = (regRd(rHRSL) & 0x0f); //analyze transfer result - switch( rcode ) - { - case hrNAK: - nak_count ++; - if( nak_limit && ( nak_count == nak_limit )) - return( rcode ); - //delay(1); - break; - case hrTIMEOUT: - retry_count ++; - if( retry_count == USB_RETRY_LIMIT ) - return( rcode ); - break; - default: - return( rcode ); - }//switch( rcode + switch (rcode) { + case hrNAK: + nak_count++; + if (nak_limit && (nak_count == nak_limit)) + return ( rcode); + break; + case hrTIMEOUT: + retry_count++; + if (retry_count == USB_RETRY_LIMIT) + return ( rcode); + break; + default: + return ( rcode); + }//switch( rcode - }//while( timeout > millis() - return( rcode ); + }//while( timeout > millis() + return ( rcode); } /* USB main task. Performs enumeration/cleanup */ -void USB::Task( void ) //USB state machine +void USB::Task(void) //USB state machine { - uint8_t rcode; - uint8_t tmpdata; - static unsigned long delay = 0; - USB_DEVICE_DESCRIPTOR buf; - bool lowspeed = false; + uint8_t rcode; + uint8_t tmpdata; + static unsigned long delay = 0; + //USB_DEVICE_DESCRIPTOR buf; + bool lowspeed = false; - MAX3421E::Task(); + MAX3421E::Task(); - tmpdata = getVbusState(); + tmpdata = getVbusState(); - /* modify USB task state if Vbus changed */ - switch( tmpdata ) - { - case SE1: //illegal state - usb_task_state = USB_DETACHED_SUBSTATE_ILLEGAL; - lowspeed = false; - break; - case SE0: //disconnected - if(( usb_task_state & USB_STATE_MASK ) != USB_STATE_DETACHED ) - usb_task_state = USB_DETACHED_SUBSTATE_INITIALIZE; - lowspeed = false; - break; - case LSHOST: - lowspeed = true; - case FSHOST: //attached - if(( usb_task_state & USB_STATE_MASK ) == USB_STATE_DETACHED ) - { - delay = millis() + USB_SETTLE_DELAY; - usb_task_state = USB_ATTACHED_SUBSTATE_SETTLE; - } - break; - }// switch( tmpdata + /* modify USB task state if Vbus changed */ + switch (tmpdata) { + case SE1: //illegal state + usb_task_state = USB_DETACHED_SUBSTATE_ILLEGAL; + lowspeed = false; + break; + case SE0: //disconnected + if ((usb_task_state & USB_STATE_MASK) != USB_STATE_DETACHED) + usb_task_state = USB_DETACHED_SUBSTATE_INITIALIZE; + lowspeed = false; + break; + case LSHOST: + lowspeed = true; + case FSHOST: //attached + if ((usb_task_state & USB_STATE_MASK) == USB_STATE_DETACHED) { + delay = millis() + USB_SETTLE_DELAY; + usb_task_state = USB_ATTACHED_SUBSTATE_SETTLE; + } + break; + }// switch( tmpdata - for (uint8_t i=0; iPoll(); + for (uint8_t i = 0; i < USB_NUMDEVICES; i++) + if (devConfig[i]) + rcode = devConfig[i]->Poll(); - switch( usb_task_state ) { - case USB_DETACHED_SUBSTATE_INITIALIZE: - init(); + switch (usb_task_state) { + case USB_DETACHED_SUBSTATE_INITIALIZE: + init(); - for (uint8_t i=0; iRelease(); + for (uint8_t i = 0; i < USB_NUMDEVICES; i++) + if (devConfig[i]) + rcode = devConfig[i]->Release(); - usb_task_state = USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE; - break; - case USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE: //just sit here - break; - case USB_DETACHED_SUBSTATE_ILLEGAL: //just sit here - break; - case USB_ATTACHED_SUBSTATE_SETTLE: //setlle time for just attached device - if( delay < millis() ) - usb_task_state = USB_ATTACHED_SUBSTATE_RESET_DEVICE; - break; - case USB_ATTACHED_SUBSTATE_RESET_DEVICE: - regWr( rHCTL, bmBUSRST ); //issue bus reset - usb_task_state = USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE; - break; - case USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE: - if(( regRd( rHCTL ) & bmBUSRST ) == 0 ) - { - tmpdata = regRd( rMODE ) | bmSOFKAENAB; //start SOF generation - regWr( rMODE, tmpdata ); - usb_task_state = USB_ATTACHED_SUBSTATE_WAIT_SOF; - delay = millis() + 20; //20ms wait after reset per USB spec - } - break; - case USB_ATTACHED_SUBSTATE_WAIT_SOF: //todo: change check order - if( regRd( rHIRQ ) & bmFRAMEIRQ ) //when first SOF received we can continue - { - if( delay < millis() ) //20ms passed - usb_task_state = USB_STATE_CONFIGURING; - } - break; - case USB_STATE_CONFIGURING: - rcode = Configuring(0, 0, lowspeed); + usb_task_state = USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE; + break; + case USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE: //just sit here + break; + case USB_DETACHED_SUBSTATE_ILLEGAL: //just sit here + break; + case USB_ATTACHED_SUBSTATE_SETTLE: //settle time for just attached device + if (delay < millis()) + usb_task_state = USB_ATTACHED_SUBSTATE_RESET_DEVICE; + break; + case USB_ATTACHED_SUBSTATE_RESET_DEVICE: + regWr(rHCTL, bmBUSRST); //issue bus reset + usb_task_state = USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE; + break; + case USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE: + if ((regRd(rHCTL) & bmBUSRST) == 0) { + tmpdata = regRd(rMODE) | bmSOFKAENAB; //start SOF generation + regWr(rMODE, tmpdata); + usb_task_state = USB_ATTACHED_SUBSTATE_WAIT_SOF; + delay = millis() + 20; //20ms wait after reset per USB spec + } + break; + case USB_ATTACHED_SUBSTATE_WAIT_SOF: //todo: change check order + if (regRd(rHIRQ) & bmFRAMEIRQ) //when first SOF received we can continue + { + if (delay < millis()) //20ms passed + usb_task_state = USB_STATE_CONFIGURING; + } + break; + case USB_STATE_CONFIGURING: + rcode = Configuring(0, 0, lowspeed); - if (rcode) - { - if (rcode != USB_DEV_CONFIG_ERROR_DEVICE_INIT_INCOMPLETE) - { - usb_error = rcode; - usb_task_state = USB_STATE_ERROR; - } - } - else - usb_task_state = USB_STATE_RUNNING; - break; - case USB_STATE_RUNNING: - break; - case USB_STATE_ERROR: - break; - } // switch( usb_task_state ) -} - -uint8_t USB::DefaultAddressing(uint8_t parent, uint8_t port, bool lowspeed) -{ - uint8_t buf[12]; - uint8_t rcode; - UsbDevice *p0 = NULL, *p = NULL; - - // Get pointer to pseudo device with address 0 assigned - p0 = addrPool.GetUsbDevicePtr(0); - - if (!p0) - return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; - - if (!p0->epinfo) - return USB_ERROR_EPINFO_IS_NULL; - - p0->lowspeed = (lowspeed) ? true : false; - - // Allocate new address according to device class - uint8_t bAddress = addrPool.AllocAddress(parent, false, port); - - if (!bAddress) - return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; - - p = addrPool.GetUsbDevicePtr(bAddress); - - if (!p) - return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; - - p->lowspeed = lowspeed; - - // Assign new address to the device - rcode = setAddr( 0, 0, bAddress ); - - if (rcode) - { - addrPool.FreeAddress(bAddress); - bAddress = 0; - return rcode; - } - return 0; -}; - -uint8_t USB::Configuring(uint8_t parent, uint8_t port, bool lowspeed) -{ - static uint8_t dev_index = 0; - uint8_t rcode = 0; - - for (; devConfigIndexInit(parent, port, lowspeed); - - if (!rcode) - { - devConfigIndex = 0; - return 0; - } - 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 order to start from the very beginning the - // next time the program gets here - if (rcode != USB_DEV_CONFIG_ERROR_DEVICE_INIT_INCOMPLETE) - devConfigIndex = 0; - - return rcode; - } - } - // if we get here that means that the device class is not supported by any of registered classes - devConfigIndex = 0; - - rcode = DefaultAddressing(parent, port, lowspeed); - - return rcode; + if (rcode) { + if (rcode != USB_DEV_CONFIG_ERROR_DEVICE_INIT_INCOMPLETE) { + usb_error = rcode; + usb_task_state = USB_STATE_ERROR; + } + } else + usb_task_state = USB_STATE_RUNNING; + break; + case USB_STATE_RUNNING: + break; + case USB_STATE_ERROR: + break; + } // switch( usb_task_state ) } -uint8_t USB::ReleaseDevice(uint8_t addr) -{ - if (!addr) - return 0; +uint8_t USB::DefaultAddressing(uint8_t parent, uint8_t port, bool lowspeed) { + //uint8_t buf[12]; + uint8_t rcode; + UsbDevice *p0 = NULL, *p = NULL; - for (uint8_t i=0; iGetAddress() == addr) - return devConfig[i]->Release(); + // Get pointer to pseudo device with address 0 assigned + p0 = addrPool.GetUsbDevicePtr(0); + + if (!p0) + return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; + + if (!p0->epinfo) + return USB_ERROR_EPINFO_IS_NULL; + + p0->lowspeed = (lowspeed) ? true : false; + + // Allocate new address according to device class + uint8_t bAddress = addrPool.AllocAddress(parent, false, port); + + if (!bAddress) + return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; + + p = addrPool.GetUsbDevicePtr(bAddress); + + if (!p) + return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; + + p->lowspeed = lowspeed; + + // Assign new address to the device + rcode = setAddr(0, 0, bAddress); + + if (rcode) { + addrPool.FreeAddress(bAddress); + bAddress = 0; + return rcode; + } + return 0; +}; + +uint8_t USB::Configuring(uint8_t parent, uint8_t port, bool lowspeed) { + //static uint8_t dev_index = 0; + uint8_t rcode = 0; + + for (; devConfigIndex < USB_NUMDEVICES; devConfigIndex++) { + if (!devConfig[devConfigIndex]) + continue; + + rcode = devConfig[devConfigIndex]->Init(parent, port, lowspeed); + + if (!rcode) { + devConfigIndex = 0; + return 0; + } + 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 order to start from the very beginning the + // next time the program gets here + if (rcode != USB_DEV_CONFIG_ERROR_DEVICE_INIT_INCOMPLETE) + devConfigIndex = 0; + + return rcode; + } + } + // if we get here that means that the device class is not supported by any of registered classes + devConfigIndex = 0; + + rcode = DefaultAddressing(parent, port, lowspeed); + + return rcode; +} + +uint8_t USB::ReleaseDevice(uint8_t addr) { + if (!addr) + return 0; + + for (uint8_t i = 0; i < USB_NUMDEVICES; i++) + if (devConfig[i]->GetAddress() == addr) + return devConfig[i]->Release(); + + return 0; } #if 1 //!defined(USB_METHODS_INLINE) //get device descriptor -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 )); + +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)); } -//get configuration descriptor -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 )); +//get configuration descriptor + +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)); } -uint8_t USB::getConfDescr( uint8_t addr, uint8_t ep, uint8_t conf, USBReadParser *p ) -{ - const uint8_t bufSize = 64; - uint8_t buf[bufSize]; +uint8_t USB::getConfDescr(uint8_t addr, uint8_t ep, uint8_t conf, USBReadParser *p) { + const uint8_t bufSize = 64; + uint8_t buf[bufSize]; - uint8_t ret = getConfDescr( addr, ep, 8, conf, buf ); + uint8_t ret = getConfDescr(addr, ep, 8, conf, buf); - if (ret) - return ret; + if (ret) + return ret; - uint16_t total = ((USB_CONFIGURATION_DESCRIPTOR*)buf)->wTotalLength; - delay(100); - //USBTRACE2("\r\ntotal conf.size:", total); + uint16_t total = ((USB_CONFIGURATION_DESCRIPTOR*) buf)->wTotalLength; - return( ctrlReq( addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, conf, USB_DESCRIPTOR_CONFIGURATION, 0x0000, total, bufSize, buf, p )); + //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)); } //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 ) -{ - return( ctrlReq( addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, index, USB_DESCRIPTOR_STRING, langid, ns, ns, dataptr, NULL )); + +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)); } -//set address -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 )); +//set address + +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)); } //set configuration -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 )); + +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)); } #endif // defined(USB_METHODS_INLINE) diff --git a/Usb.h b/Usb.h index 7acdb2d5..15bc20f2 100644 --- a/Usb.h +++ b/Usb.h @@ -13,7 +13,7 @@ Contact information Circuits At Home, LTD Web : http://www.circuitsathome.com e-mail : support@circuitsathome.com -*/ + */ /* USB functions */ #ifndef _usb_h_ #define _usb_h_ @@ -44,28 +44,18 @@ e-mail : support@circuitsathome.com #include "hexdump.h" #include "message.h" - +extern int UsbDEBUGlvl; /* 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 -typedef MAX3421e MAX3421E; // Black Widow -#elif defined(BOARD_TEENSY_PLUS_PLUS) -typedef MAX3421e MAX3421E; // Teensy++ 2.0 & 1.0 -#elif defined(BOARD_MEGA_ADK) -typedef MAX3421e MAX3421E; // Arduino Mega ADK -#elif defined(BOARD_BALANDUINO) -typedef MAX3421e MAX3421E; // Balanduino +typedef MAX3421e MAX3421E; // Black Widow #else -typedef MAX3421e MAX3421E; // Official Arduinos (UNO, Duemilanove, Mega, 2560, Leonardo etc.) +typedef MAX3421e MAX3421E; // Official Arduinos (UNO, Duemilanove, Mega, 2560 #endif //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 USBTRACE2(s,r) (Serial.print((s)), Serial.println((r),HEX)) +#define USBTRACE(s) (Notify(PSTR(s), 0x80)) +#define USBTRACE2(s,r) (Notify(PSTR(s), 0x80), PrintHex((r), 0x80), Notify(PSTR("\r\n"), 0x80)) @@ -80,22 +70,22 @@ typedef MAX3421e MAX3421E; // Official Arduinos (UNO, Duemilanove, Me // USB Device Classes #define USB_CLASS_USE_CLASS_INFO 0x00 // Use Class Info in the Interface Descriptors -#define USB_CLASS_AUDIO 0x01 // Audio +#define USB_CLASS_AUDIO 0x01 // Audio #define USB_CLASS_COM_AND_CDC_CTRL 0x02 // Communications and CDC Control -#define USB_CLASS_HID 0x03 // HID -#define USB_CLASS_PHYSICAL 0x05 // Physical -#define USB_CLASS_IMAGE 0x06 // Image -#define USB_CLASS_PRINTER 0x07 // Printer +#define USB_CLASS_HID 0x03 // HID +#define USB_CLASS_PHYSICAL 0x05 // Physical +#define USB_CLASS_IMAGE 0x06 // Image +#define USB_CLASS_PRINTER 0x07 // Printer #define USB_CLASS_MASS_STORAGE 0x08 // Mass Storage -#define USB_CLASS_HUB 0x09 // Hub -#define USB_CLASS_CDC_DATA 0x0a // CDC-Data +#define USB_CLASS_HUB 0x09 // Hub +#define USB_CLASS_CDC_DATA 0x0a // CDC-Data #define USB_CLASS_SMART_CARD 0x0b // Smart-Card #define USB_CLASS_CONTENT_SECURITY 0x0d // Content Security -#define USB_CLASS_VIDEO 0x0e // Video +#define USB_CLASS_VIDEO 0x0e // Video #define USB_CLASS_PERSONAL_HEALTH 0x0f // Personal Healthcare #define USB_CLASS_DIAGNOSTIC_DEVICE 0xdc // Diagnostic Device #define USB_CLASS_WIRELESS_CTRL 0xe0 // Wireless Controller -#define USB_CLASS_MISC 0xef // Miscellaneous +#define USB_CLASS_MISC 0xef // Miscellaneous #define USB_CLASS_APP_SPECIFIC 0xfe // Application Specific #define USB_CLASS_VENDOR_SPECIFIC 0xff // Vendor Specific @@ -104,42 +94,41 @@ typedef MAX3421e MAX3421E; // Official Arduinos (UNO, Duemilanove, Me #define USB_DEV_CONFIG_ERROR_DEVICE_INIT_INCOMPLETE 0xD2 #define USB_ERROR_UNABLE_TO_REGISTER_DEVICE_CLASS 0xD3 #define USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL 0xD4 -#define USB_ERROR_HUB_ADDRESS_OVERFLOW 0xD5 -#define USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL 0xD6 -#define USB_ERROR_EPINFO_IS_NULL 0xD7 -#define USB_ERROR_INVALID_ARGUMENT 0xD8 +#define USB_ERROR_HUB_ADDRESS_OVERFLOW 0xD5 +#define USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL 0xD6 +#define USB_ERROR_EPINFO_IS_NULL 0xD7 +#define USB_ERROR_INVALID_ARGUMENT 0xD8 #define USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE 0xD9 -#define USB_ERROR_INVALID_MAX_PKT_SIZE 0xDA -#define USB_ERROR_EP_NOT_FOUND_IN_TBL 0xDB -#define USB_ERROR_TRANSFER_TIMEOUT 0xFF +#define USB_ERROR_INVALID_MAX_PKT_SIZE 0xDA +#define USB_ERROR_EP_NOT_FOUND_IN_TBL 0xDB +#define USB_ERROR_TRANSFER_TIMEOUT 0xFF -class USBDeviceConfig -{ +class USBDeviceConfig { public: - virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed) = 0; - virtual uint8_t Release() = 0; - virtual uint8_t Poll() = 0; - virtual uint8_t GetAddress() = 0; + virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed) = 0; + virtual uint8_t Release() = 0; + virtual uint8_t Poll() = 0; + virtual uint8_t GetAddress() = 0; }; -#define USB_XFER_TIMEOUT 5000 //USB transfer timeout in milliseconds, per section 9.2.6.1 of USB 2.0 spec -//#define USB_NAK_LIMIT 32000 //NAK limit for a transfer. 0 means NAKs are not counted -#define USB_RETRY_LIMIT 3 //retry limit for a transfer -#define USB_SETTLE_DELAY 200 //settle delay in milliseconds +#define USB_XFER_TIMEOUT 5000 //USB transfer timeout in milliseconds, per section 9.2.6.1 of USB 2.0 spec +//#define USB_NAK_LIMIT 32000 //NAK limit for a transfer. 0 means NAKs are not counted +#define USB_RETRY_LIMIT 3 //retry limit for a transfer +#define USB_SETTLE_DELAY 200 //settle delay in milliseconds -#define USB_NUMDEVICES 16 //number of USB devices -//#define HUB_MAX_HUBS 7 // maximum number of hubs that can be attached to the host controller -#define HUB_PORT_RESET_DELAY 20 // hub port reset delay 10 ms recomended, can be up to 20 ms +#define USB_NUMDEVICES 16 //number of USB devices +//#define HUB_MAX_HUBS 7 // maximum number of hubs that can be attached to the host controller +#define HUB_PORT_RESET_DELAY 20 // hub port reset delay 10 ms recomended, can be up to 20 ms /* USB state machine states */ #define USB_STATE_MASK 0xf0 #define USB_STATE_DETACHED 0x10 -#define USB_DETACHED_SUBSTATE_INITIALIZE 0x11 +#define USB_DETACHED_SUBSTATE_INITIALIZE 0x11 #define USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE 0x12 #define USB_DETACHED_SUBSTATE_ILLEGAL 0x13 #define USB_ATTACHED_SUBSTATE_SETTLE 0x20 -#define USB_ATTACHED_SUBSTATE_RESET_DEVICE 0x30 +#define USB_ATTACHED_SUBSTATE_RESET_DEVICE 0x30 #define USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE 0x40 #define USB_ATTACHED_SUBSTATE_WAIT_SOF 0x50 #define USB_ATTACHED_SUBSTATE_GET_DEVICE_DESCRIPTOR_SIZE 0x60 @@ -150,134 +139,138 @@ public: /* USB Setup Packet Structure */ typedef struct { - union { // offset description - uint8_t bmRequestType; // 0 Bit-map of request type - struct { - uint8_t recipient: 5; // Recipient of the request - uint8_t type: 2; // Type of request - uint8_t direction: 1; // Direction of data X-fer - }; - }ReqType_u; - uint8_t bRequest; // 1 Request - union { - uint16_t wValue; // 2 Depends on bRequest - struct { - uint8_t wValueLo; - uint8_t wValueHi; - }; - }wVal_u; - uint16_t wIndex; // 4 Depends on bRequest - uint16_t wLength; // 6 Depends on bRequest -} SETUP_PKT, *PSETUP_PKT; + + union { // offset description + uint8_t bmRequestType; // 0 Bit-map of request type + + struct { + uint8_t recipient : 5; // Recipient of the request + uint8_t type : 2; // Type of request + uint8_t direction : 1; // Direction of data X-fer + }__attribute__((packed)); + } ReqType_u; + uint8_t bRequest; // 1 Request + + union { + uint16_t wValue; // 2 Depends on bRequest + + struct { + uint8_t wValueLo; + uint8_t wValueHi; + }__attribute__((packed)); + } wVal_u; + uint16_t wIndex; // 4 Depends on bRequest + uint16_t wLength; // 6 Depends on bRequest +} SETUP_PKT, *PSETUP_PKT __attribute__((packed)); // Base class for incomming data parser -class USBReadParser -{ + +class USBReadParser { 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 { + AddressPoolImpl addrPool; + USBDeviceConfig* devConfig[USB_NUMDEVICES]; + uint8_t devConfigIndex; + uint8_t bmHubPre; -class USB : public MAX3421E -{ - AddressPoolImpl addrPool; - USBDeviceConfig* devConfig[USB_NUMDEVICES]; - uint8_t devConfigIndex; - uint8_t bmHubPre; +public: + USB(void); - public: - USB( void ); + void SetHubPreMask() { + bmHubPre |= bmHUBPRE; + }; - void SetHubPreMask() { bmHubPre |= bmHUBPRE; }; - void ResetHubPreMask() { bmHubPre &= (~bmHUBPRE); }; + void ResetHubPreMask() { + bmHubPre &= (~bmHUBPRE); + }; - AddressPool& GetAddressPool() - { - return (AddressPool&)addrPool; - }; - uint8_t RegisterDeviceClass(USBDeviceConfig *pdev) - { - for (uint8_t i=0; i -class AddressPoolImpl : public AddressPool -{ - EpInfo dev0ep; //Endpoint data structure used during enumeration for uninitialized device +class AddressPoolImpl : public AddressPool { + EpInfo dev0ep; //Endpoint data structure used during enumeration for uninitialized device - uint8_t hubCounter; // hub counter is kept - // in order to avoid hub address duplication + uint8_t hubCounter; // hub counter is kept + // in order to avoid hub address duplication - UsbDevice thePool[MAX_DEVICES_ALLOWED]; + UsbDevice thePool[MAX_DEVICES_ALLOWED]; - // Initializes address pool entry - void InitEntry(uint8_t index) - { - thePool[index].address = 0; - thePool[index].epcount = 1; - thePool[index].lowspeed = 0; - thePool[index].epinfo = &dev0ep; - }; - // Returns thePool index for a given address - uint8_t FindAddressIndex(uint8_t address = 0) - { - for (uint8_t i=1; i=MAX_DEVICES_ALLOWED) ? 1 : start; ibmParent == addr.bmAddress) - return i; - } - return 0; - }; - // Frees address entry specified by index parameter - void FreeAddressByIndex(uint8_t index) - { - // Zerro field is reserved and should not be affected - if (index == 0) - return; + // Initializes address pool entry - // If a hub was switched off all port addresses should be freed - if (((UsbDeviceAddress*)&thePool[index].address)->bmHub == 1) - { - for (uint8_t i=1; i = FindChildIndex(*((UsbDeviceAddress*)&thePool[index].address), i); ) - FreeAddressByIndex(i); + void InitEntry(uint8_t index) { + thePool[index].address = 0; + thePool[index].epcount = 1; + thePool[index].lowspeed = 0; + thePool[index].epinfo = &dev0ep; + }; + // Returns thePool index for a given address - // If the hub had the last allocated address, hubCounter should be decremented - if (hubCounter == ((UsbDeviceAddress*)&thePool[index].address)->bmAddress) - hubCounter --; - } - InitEntry(index); - } - // Initializes the whole address pool at once - void InitAllAddresses() - { - for (uint8_t i=1; i= MAX_DEVICES_ALLOWED) ? 1 : start; i < MAX_DEVICES_ALLOWED; i++) { + if (((UsbDeviceAddress*) & thePool[i].address)->bmParent == addr.bmAddress) + return i; + } + return 0; + }; + // Frees address entry specified by index parameter + + void FreeAddressByIndex(uint8_t index) { + // Zerro field is reserved and should not be affected + if (index == 0) + return; + + // If a hub was switched off all port addresses should be freed + if (((UsbDeviceAddress*) & thePool[index].address)->bmHub == 1) { + for (uint8_t i = 1; (i = FindChildIndex(*((UsbDeviceAddress*) & thePool[index].address), i));) + FreeAddressByIndex(i); + + // If the hub had the last allocated address, hubCounter should be decremented + if (hubCounter == ((UsbDeviceAddress*) & thePool[index].address)->bmAddress) + hubCounter--; + } + InitEntry(index); + } + // Initializes the whole address pool at once + + void InitAllAddresses() { + for (uint8_t i = 1; i < MAX_DEVICES_ALLOWED; i++) + InitEntry(i); + + hubCounter = 0; + }; - hubCounter = 0; - }; - public: - AddressPoolImpl() : hubCounter(0) - { - // Zero address is reserved - InitEntry(0); - thePool[0].address = 0; - thePool[0].epinfo = &dev0ep; - dev0ep.epAddr = 0; - dev0ep.maxPktSize = 8; - dev0ep.epAttribs = 0; //set DATA0/1 toggles to 0 - dev0ep.bmNakPower = USB_NAK_MAX_POWER; + AddressPoolImpl() : hubCounter(0) { + // Zero address is reserved + InitEntry(0); - InitAllAddresses(); - }; - // Returns a pointer to a specified address entry - virtual UsbDevice* GetUsbDevicePtr(uint8_t addr) - { - if (!addr) - return thePool; + thePool[0].address = 0; + thePool[0].epinfo = &dev0ep; + dev0ep.epAddr = 0; + dev0ep.maxPktSize = 8; + dev0ep.epAttribs = 0; //set DATA0/1 toggles to 0 + dev0ep.bmNakPower = USB_NAK_MAX_POWER; - uint8_t index = FindAddressIndex(addr); + InitAllAddresses(); + }; + // Returns a pointer to a specified address entry - return (!index) ? NULL : thePool + index; - }; - - // Performs an operation specified by pfunc for each addressed device - void ForEachUsbDevice(UsbDeviceHandleFunc pfunc) - { - if (!pfunc) - return; + virtual UsbDevice* GetUsbDevicePtr(uint8_t addr) { + if (!addr) + return thePool; - for (uint8_t i=1; i 127 || port > 7) - return 0; + return (!index) ? NULL : thePool + index; + }; - if (is_hub && hubCounter == 7) - return 0; + // Performs an operation specified by pfunc for each addressed device - // finds first empty address entry starting from one - uint8_t index = FindAddressIndex(0); + void ForEachUsbDevice(UsbDeviceHandleFunc pfunc) { + if (!pfunc) + return; - if (!index) // if empty entry is not found - return 0; + for (uint8_t i = 1; i < MAX_DEVICES_ALLOWED; i++) + if (thePool[i].address) + pfunc(thePool + i); + }; + // Allocates new address - if (parent == 0) - { - if (is_hub) - { - thePool[index].address = 0x41; - hubCounter ++; - } - else - thePool[index].address = 1; + virtual uint8_t AllocAddress(uint8_t parent, bool is_hub = false, uint8_t port = 0) { + /* if (parent != 0 && port == 0) + Serial.println("PRT:0"); */ - return thePool[index].address; - } + if (parent > 127 || port > 7) + return 0; - UsbDeviceAddress addr; + if (is_hub && hubCounter == 7) + return 0; - addr.bmParent = ((UsbDeviceAddress*)&parent)->bmAddress; + // finds first empty address entry starting from one + uint8_t index = FindAddressIndex(0); - if (is_hub) - { - addr.bmHub = 1; - addr.bmAddress = ++hubCounter; - } - else - { - addr.bmHub = 0; - addr.bmAddress = port; - } - thePool[index].address = *((uint8_t*)&addr); -/* - Serial.print("Addr:"); - Serial.print(addr.bmHub, HEX); - Serial.print("."); - Serial.print(addr.bmParent, HEX); - Serial.print("."); - Serial.println(addr.bmAddress, HEX); -*/ - return thePool[index].address; - }; - // Empties pool entry - virtual void FreeAddress(uint8_t addr) - { - // if the root hub is disconnected all the addresses should be initialized - if (addr == 0x41) - { - InitAllAddresses(); - return; - } - uint8_t index = FindAddressIndex(addr); - FreeAddressByIndex(index); - }; - // Returns number of hubs attached - // It can be rather helpfull to find out if there are hubs attached than getting the exact number of hubs. - //uint8_t GetNumHubs() - //{ - // return hubCounter; - //}; - //uint8_t GetNumDevices() - //{ - // uint8_t counter = 0; + if (!index) // if empty entry is not found + return 0; - // for (uint8_t i=1; ibmAddress; + + if (is_hub) { + addr.bmHub = 1; + addr.bmAddress = ++hubCounter; + } else { + addr.bmHub = 0; + addr.bmAddress = port; + } + thePool[index].address = *((uint8_t*) & addr); + /* + Serial.print("Addr:"); + Serial.print(addr.bmHub, HEX); + Serial.print("."); + Serial.print(addr.bmParent, HEX); + Serial.print("."); + Serial.println(addr.bmAddress, HEX); + */ + return thePool[index].address; + }; + // Empties pool entry + + virtual void FreeAddress(uint8_t addr) { + // if the root hub is disconnected all the addresses should be initialized + if (addr == 0x41) { + InitAllAddresses(); + return; + } + uint8_t index = FindAddressIndex(addr); + FreeAddressByIndex(index); + }; + // Returns number of hubs attached + // It can be rather helpfull to find out if there are hubs attached than getting the exact number of hubs. + //uint8_t GetNumHubs() + //{ + // return hubCounter; + //}; + //uint8_t GetNumDevices() + //{ + // uint8_t counter = 0; + + // for (uint8_t i=1; iRegisterDeviceClass(this); //set devConfig[] entry - } -} - -/* Connection initialization of an Android phone */ -uint8_t ADK::Init(uint8_t parent, uint8_t port, bool lowspeed) -{ - - uint8_t buf[sizeof(USB_DEVICE_DESCRIPTOR)]; - uint8_t rcode; - UsbDevice *p = NULL; - EpInfo *oldep_ptr = NULL; - uint8_t num_of_conf; // number of configurations - - // get memory address of USB device address pool - AddressPool &addrPool = pUsb->GetAddressPool(); -#ifdef DEBUG - USBTRACE("\r\nADK Init"); -#endif - // check if address has already been assigned to an instance - if (bAddress) { -#ifdef DEBUG - USBTRACE("\r\nAddress in use"); -#endif - return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE; - } - - // Get pointer to pseudo device with address 0 assigned - p = addrPool.GetUsbDevicePtr(0); - - if (!p) { -#ifdef DEBUG - USBTRACE("\r\nAddress not found"); -#endif - return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; - } - - if (!p->epinfo) { -#ifdef DEBUG - USBTRACE("epinfo is null\r\n"); -#endif - return USB_ERROR_EPINFO_IS_NULL; - } - - // Save old pointer to EP_RECORD of address 0 - oldep_ptr = p->epinfo; - - // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence - p->epinfo = epInfo; - - p->lowspeed = lowspeed; - - // Get device descriptor - rcode = pUsb->getDevDescr( 0, 0, sizeof(USB_DEVICE_DESCRIPTOR), (uint8_t*)buf ); - - // Restore p->epinfo - p->epinfo = oldep_ptr; - - if( rcode ){ - goto FailGetDevDescr; - } - - // Allocate new address according to device class - bAddress = addrPool.AllocAddress(parent, false, port); - - // Extract Max Packet Size from device descriptor - epInfo[0].maxPktSize = (uint8_t)((USB_DEVICE_DESCRIPTOR*)buf)->bMaxPacketSize0; - - // Assign new address to the device - rcode = pUsb->setAddr( 0, 0, bAddress ); - if (rcode) { - p->lowspeed = false; - addrPool.FreeAddress(bAddress); - bAddress = 0; - //USBTRACE2("setAddr:",rcode); - return rcode; - }//if (rcode... - - //USBTRACE2("\r\nAddr:", bAddress); - - p->lowspeed = false; - - //get pointer to assigned address record - p = addrPool.GetUsbDevicePtr(bAddress); - if (!p) { - return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; - } - - p->lowspeed = lowspeed; - - // Assign epInfo to epinfo pointer - only EP0 is known - rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); - if (rcode) { - goto FailSetDevTblEntry; - } - - //check if ADK device is already in accessory mode; if yes, configure and exit - if(((USB_DEVICE_DESCRIPTOR*)buf)->idVendor == ADK_VID && - (((USB_DEVICE_DESCRIPTOR*)buf)->idProduct == ADK_PID || ((USB_DEVICE_DESCRIPTOR*)buf)->idProduct == ADB_PID)) { -#ifdef DEBUG - USBTRACE("\r\nAcc.mode device detected"); -#endif - /* go through configurations, find first bulk-IN, bulk-OUT EP, fill epInfo and quit */ - num_of_conf = ((USB_DEVICE_DESCRIPTOR*)buf)->bNumConfigurations; - - //USBTRACE2("\r\nNC:",num_of_conf); - - for (uint8_t i=0; i confDescrParser(this); - delay(1); - 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 ) { - goto FailGetConfDescr; - } - if( bNumEP > 2 ) { - break; - } - } // for (uint8_t i=0; isetEpInfoEntry(bAddress, 3, epInfo); - if (rcode) { - goto FailSetDevTblEntry; - } - } - - - - // Set Configuration Value - rcode = pUsb->setConf(bAddress, 0, bConfNum); - if( rcode ){ - goto FailSetConf; - } - /* print endpoint structure */ -// USBTRACE("\r\nEndpoint Structure:"); -// USBTRACE("\r\nEP0:"); -// USBTRACE2("\r\nAddr: ", epInfo[0].epAddr ); -// USBTRACE2("\r\nMax.pkt.size: ", epInfo[0].maxPktSize ); -// USBTRACE2("\r\nAttr: ", epInfo[0].epAttribs ); -// USBTRACE("\r\nEpout:"); -// USBTRACE2("\r\nAddr: ", epInfo[epDataOutIndex].epAddr ); -// USBTRACE2("\r\nMax.pkt.size: ", epInfo[epDataOutIndex].maxPktSize ); -// USBTRACE2("\r\nAttr: ", epInfo[epDataOutIndex].epAttribs ); -// USBTRACE("\r\nEpin:"); -// USBTRACE2("\r\nAddr: ", epInfo[epDataInIndex].epAddr ); -// USBTRACE2("\r\nMax.pkt.size: ", epInfo[epDataInIndex].maxPktSize ); -// USBTRACE2("\r\nAttr: ", epInfo[epDataInIndex].epAttribs ); -#ifdef DEBUG - USBTRACE("\r\nConfiguration successful"); -#endif - ready = true; - return 0; //successful configuration - }//if( buf->idVendor == ADK_VID... - - //probe device - get accessory protocol revision - { - uint16_t adkproto = -1; - delay(1); - 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 ){ - goto FailGetProto; //init fails - } -#ifdef DEBUG - USBTRACE2("\r\nADK protocol rev. ", adkproto ); -#endif - } - - //sending ID strings - sendStr( ACCESSORY_STRING_MANUFACTURER, manufacturer); - sendStr( ACCESSORY_STRING_MODEL, model); - sendStr( ACCESSORY_STRING_DESCRIPTION, description); - sendStr( ACCESSORY_STRING_VERSION, version); - sendStr( ACCESSORY_STRING_URI, uri); - sendStr( ACCESSORY_STRING_SERIAL, serial); - - //switch to accessory mode - //the Android phone will reset - rcode = switchAcc(); - if( rcode ) { - goto FailSwAcc; //init fails - } - rcode = -1; - goto SwAttempt; //switch to accessory mode attempted - - /* diagnostic messages */ -FailGetDevDescr: -#ifdef DEBUG - USBTRACE("\r\ngetDevDescr:"); -#endif - goto Fail; - -FailSetDevTblEntry: -#ifdef DEBUG - USBTRACE("\r\nsetDevTblEn:"); -#endif - goto Fail; - -FailGetProto: -#ifdef DEBUG - USBTRACE("\r\ngetProto:"); -#endif - goto Fail; - -FailSwAcc: -#ifdef DEBUG - USBTRACE("\r\nswAcc:"); -#endif - goto Fail; - -SwAttempt: -#ifdef DEBUG - USBTRACE("\r\nAccessory mode switch attempt"); -#endif - goto Fail; - -FailGetConfDescr: -// USBTRACE("getConf:"); - goto Fail; -// -FailSetConf: -// USBTRACE("setConf:"); - goto Fail; -// -//FailOnInit: -// USBTRACE("OnInit:"); -// goto Fail; -// -Fail: - //USBTRACE2("\r\nADK Init Failed, error code: ", rcode); - Release(); - return rcode; -} - -/* 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) -{ - //ErrorMessage(PSTR("Conf.Val"), conf); - //ErrorMessage(PSTR("Iface Num"),iface); - //ErrorMessage(PSTR("Alt.Set"), alt); - - //added by Yuuichi Akagawa - if( bNumEP == 3 ) { - return; - } - - bConfNum = conf; - - uint8_t index; - - if ((pep->bmAttributes & 0x02) == 2) { - index = ((pep->bEndpointAddress & 0x80) == 0x80) ? epDataInIndex : epDataOutIndex; - } - - // Fill in the endpoint info structure - epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F); - epInfo[index].maxPktSize = (uint8_t)pep->wMaxPacketSize; - - bNumEP ++; - - //PrintEndpointDescriptor(pep); -} - -/* Performs a cleanup after failed Init() attempt */ -uint8_t ADK::Release() -{ - pUsb->GetAddressPool().FreeAddress(bAddress); - - bNumEP = 1; //must have to be reset to 1 - - bAddress = 0; - ready = false; - return 0; -} - -uint8_t ADK::RcvData(uint16_t *bytes_rcvd, uint8_t *dataptr) -{ - //USBTRACE2("\r\nAddr: ", bAddress ); - //USBTRACE2("\r\nEP: ",epInfo[epDataInIndex].epAddr); - return pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, bytes_rcvd, dataptr); -} - -uint8_t ADK::SndData(uint16_t nbytes, uint8_t *dataptr) -{ - return pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, nbytes, dataptr); -} - -void ADK::PrintEndpointDescriptor( const USB_ENDPOINT_DESCRIPTOR* ep_ptr ) -{ -#ifdef DEBUG - Notify(PSTR("Endpoint descriptor:")); - Notify(PSTR("\r\nLength:\t\t")); - PrintHex(ep_ptr->bLength); - Notify(PSTR("\r\nType:\t\t")); - PrintHex(ep_ptr->bDescriptorType); - Notify(PSTR("\r\nAddress:\t")); - PrintHex(ep_ptr->bEndpointAddress); - Notify(PSTR("\r\nAttributes:\t")); - PrintHex(ep_ptr->bmAttributes); - Notify(PSTR("\r\nMaxPktSize:\t")); - PrintHex(ep_ptr->wMaxPacketSize); - Notify(PSTR("\r\nPoll Intrv:\t")); - PrintHex(ep_ptr->bInterval); - Notify(PSTR("\r\n")); -#endif -} +/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. + +This software may be distributed and modified under the terms of the GNU +General Public License version 2 (GPL2) as published by the Free Software +Foundation and appearing in the file GPL2.TXT included in the packaging of +this file. Please note that GPL2 Section 2[b] requires that all works based +on this software must also be made publicly available under the terms of +the GPL2 ("Copyleft"). + +Contact information +------------------- + +Circuits At Home, LTD +Web : http://www.circuitsathome.com +e-mail : support@circuitsathome.com + */ + +/* Google ADK interface */ + +#include "adk.h" + +const uint8_t ADK::epDataInIndex = 1; +const uint8_t ADK::epDataOutIndex = 2; + +ADK::ADK(USB *p, const char* manufacturer, + const char* model, + const char* description, + const char* version, + const char* uri, + const char* serial) : + +/* ADK ID Strings */ + +manufacturer(manufacturer), +model(model), +description(description), +version(version), +uri(uri), +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 + for (uint8_t i = 0; i < ADK_MAX_ENDPOINTS; i++) { + epInfo[i].epAddr = 0; + epInfo[i].maxPktSize = (i) ? 0 : 8; + epInfo[i].epAttribs = (0xfc & (USB_NAK_MAX_POWER << 2)); + }//for(uint8_t i=0; iRegisterDeviceClass(this); //set devConfig[] entry + } +} + +/* Connection initialization of an Android phone */ +uint8_t ADK::Init(uint8_t parent, uint8_t port, bool lowspeed) { + + uint8_t buf[sizeof (USB_DEVICE_DESCRIPTOR)]; + uint8_t rcode; + UsbDevice *p = NULL; + EpInfo *oldep_ptr = NULL; + uint8_t num_of_conf; // number of configurations + + // get memory address of USB device address pool + AddressPool &addrPool = pUsb->GetAddressPool(); + + USBTRACE("\r\nADK Init"); + + // check if address has already been assigned to an instance + if (bAddress) { + USBTRACE("\r\nAddress in use"); + return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE; + } + + // Get pointer to pseudo device with address 0 assigned + p = addrPool.GetUsbDevicePtr(0); + + if (!p) { + USBTRACE("\r\nAddress not found"); + return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; + } + + if (!p->epinfo) { + USBTRACE("epinfo is null\r\n"); + return USB_ERROR_EPINFO_IS_NULL; + } + + // Save old pointer to EP_RECORD of address 0 + oldep_ptr = p->epinfo; + + // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence + p->epinfo = epInfo; + + p->lowspeed = lowspeed; + + // Get device descriptor + rcode = pUsb->getDevDescr(0, 0, sizeof (USB_DEVICE_DESCRIPTOR), (uint8_t*) buf); + + // Restore p->epinfo + p->epinfo = oldep_ptr; + + if (rcode) { + goto FailGetDevDescr; + } + + // Allocate new address according to device class + bAddress = addrPool.AllocAddress(parent, false, port); + + // Extract Max Packet Size from device descriptor + epInfo[0].maxPktSize = (uint8_t) ((USB_DEVICE_DESCRIPTOR*) buf)->bMaxPacketSize0; + + // Assign new address to the device + rcode = pUsb->setAddr(0, 0, bAddress); + if (rcode) { + p->lowspeed = false; + addrPool.FreeAddress(bAddress); + bAddress = 0; + //USBTRACE2("setAddr:",rcode); + return rcode; + }//if (rcode... + + //USBTRACE2("\r\nAddr:", bAddress); + + p->lowspeed = false; + + //get pointer to assigned address record + p = addrPool.GetUsbDevicePtr(bAddress); + if (!p) { + return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; + } + + p->lowspeed = lowspeed; + + // Assign epInfo to epinfo pointer - only EP0 is known + rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); + if (rcode) { + goto FailSetDevTblEntry; + } + + //check if ADK device is already in accessory mode; if yes, configure and exit + if (((USB_DEVICE_DESCRIPTOR*) buf)->idVendor == ADK_VID && + (((USB_DEVICE_DESCRIPTOR*) buf)->idProduct == ADK_PID || ((USB_DEVICE_DESCRIPTOR*) buf)->idProduct == ADB_PID)) { + USBTRACE("\r\nAcc.mode device detected"); + /* go through configurations, find first bulk-IN, bulk-OUT EP, fill epInfo and quit */ + num_of_conf = ((USB_DEVICE_DESCRIPTOR*) buf)->bNumConfigurations; + + //USBTRACE2("\r\nNC:",num_of_conf); + + for (uint8_t i = 0; i < num_of_conf; i++) { + ConfigDescParser < 0, 0, 0, 0 > confDescrParser(this); + rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser); + if (rcode) { + goto FailGetConfDescr; + } + if (bNumEP > 2) { + break; + } + } // for (uint8_t i=0; isetEpInfoEntry(bAddress, 3, epInfo); + if (rcode) { + goto FailSetDevTblEntry; + } + } + + + + // Set Configuration Value + rcode = pUsb->setConf(bAddress, 0, bConfNum); + if (rcode) { + goto FailSetConf; + } + /* print endpoint structure */ + // USBTRACE("\r\nEndpoint Structure:"); + // USBTRACE("\r\nEP0:"); + // USBTRACE2("\r\nAddr: ", epInfo[0].epAddr ); + // USBTRACE2("\r\nMax.pkt.size: ", epInfo[0].maxPktSize ); + // USBTRACE2("\r\nAttr: ", epInfo[0].epAttribs ); + // USBTRACE("\r\nEpout:"); + // USBTRACE2("\r\nAddr: ", epInfo[epDataOutIndex].epAddr ); + // USBTRACE2("\r\nMax.pkt.size: ", epInfo[epDataOutIndex].maxPktSize ); + // USBTRACE2("\r\nAttr: ", epInfo[epDataOutIndex].epAttribs ); + // USBTRACE("\r\nEpin:"); + // USBTRACE2("\r\nAddr: ", epInfo[epDataInIndex].epAddr ); + // USBTRACE2("\r\nMax.pkt.size: ", epInfo[epDataInIndex].maxPktSize ); + // USBTRACE2("\r\nAttr: ", epInfo[epDataInIndex].epAttribs ); + + USBTRACE("\r\nConfiguration successful"); + ready = true; + return 0; //successful configuration + }//if( buf->idVendor == ADK_VID... + + //probe device - get accessory protocol revision + { + uint16_t adkproto = -1; + rcode = getProto((uint8_t*) & adkproto); + if (rcode) { + goto FailGetProto; //init fails + } + USBTRACE2("\r\nADK protocol rev. ", adkproto); + } + + //sending ID strings + sendStr(ACCESSORY_STRING_MANUFACTURER, manufacturer); + sendStr(ACCESSORY_STRING_MODEL, model); + sendStr(ACCESSORY_STRING_DESCRIPTION, description); + sendStr(ACCESSORY_STRING_VERSION, version); + sendStr(ACCESSORY_STRING_URI, uri); + sendStr(ACCESSORY_STRING_SERIAL, serial); + + //switch to accessory mode + //the Android phone will reset + rcode = switchAcc(); + if (rcode) { + goto FailSwAcc; //init fails + } + rcode = -1; + goto SwAttempt; //switch to accessory mode attempted + + /* diagnostic messages */ +FailGetDevDescr: + USBTRACE("\r\ngetDevDescr:"); + goto Fail; + +FailSetDevTblEntry: + USBTRACE("\r\nsetDevTblEn:"); + goto Fail; + +FailGetProto: + USBTRACE("\r\ngetProto:"); + goto Fail; + +FailSwAcc: + USBTRACE("\r\nswAcc:"); + goto Fail; + +SwAttempt: + USBTRACE("\r\nAccessory mode switch attempt"); + goto Fail; + +FailGetConfDescr: + // USBTRACE("getConf:"); + goto Fail; + // +FailSetConf: + // USBTRACE("setConf:"); + goto Fail; + // + //FailOnInit: + // USBTRACE("OnInit:"); + // goto Fail; + // +Fail: + //USBTRACE2("\r\nADK Init Failed, error code: ", rcode); + Release(); + return rcode; +} + +/* 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) { + //ErrorMessage(PSTR("Conf.Val"), conf); + //ErrorMessage(PSTR("Iface Num"),iface); + //ErrorMessage(PSTR("Alt.Set"), alt); + + //added by Yuuichi Akagawa + if (bNumEP == 3) { + return; + } + + bConfNum = conf; + + uint8_t index; + + // if ((pep->bmAttributes & 0x02) == 2) { + index = ((pep->bEndpointAddress & 0x80) == 0x80) ? epDataInIndex : epDataOutIndex; + // } + + // Fill in the endpoint info structure + epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F); + epInfo[index].maxPktSize = (uint8_t) pep->wMaxPacketSize; + + bNumEP++; + + //PrintEndpointDescriptor(pep); +} + +/* Performs a cleanup after failed Init() attempt */ +uint8_t ADK::Release() { + pUsb->GetAddressPool().FreeAddress(bAddress); + + bNumEP = 1; //must have to be reset to 1 + + bAddress = 0; + ready = false; + return 0; +} + +uint8_t ADK::RcvData(uint16_t *bytes_rcvd, uint8_t *dataptr) { + //USBTRACE2("\r\nAddr: ", bAddress ); + //USBTRACE2("\r\nEP: ",epInfo[epDataInIndex].epAddr); + return pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, bytes_rcvd, dataptr); +} + +uint8_t ADK::SndData(uint16_t nbytes, uint8_t *dataptr) { + return pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, nbytes, dataptr); +} + +void ADK::PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr) { + Notify(PSTR("Endpoint descriptor:"), 0x80); + Notify(PSTR("\r\nLength:\t\t"), 0x80); + PrintHex (ep_ptr->bLength, 0x80); + Notify(PSTR("\r\nType:\t\t"), 0x80); + PrintHex (ep_ptr->bDescriptorType, 0x80); + Notify(PSTR("\r\nAddress:\t"), 0x80); + PrintHex (ep_ptr->bEndpointAddress, 0x80); + Notify(PSTR("\r\nAttributes:\t"), 0x80); + PrintHex (ep_ptr->bmAttributes, 0x80); + Notify(PSTR("\r\nMaxPktSize:\t"), 0x80); + PrintHex (ep_ptr->wMaxPacketSize, 0x80); + Notify(PSTR("\r\nPoll Intrv:\t"), 0x80); + PrintHex (ep_ptr->bInterval, 0x80); + Notify(PSTR("\r\n"), 0x80); +} diff --git a/adk.h b/adk.h index 8084decb..7f8bf606 100644 --- a/adk.h +++ b/adk.h @@ -1,145 +1,149 @@ -/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. - -This software may be distributed and modified under the terms of the GNU -General Public License version 2 (GPL2) as published by the Free Software -Foundation and appearing in the file GPL2.TXT included in the packaging of -this file. Please note that GPL2 Section 2[b] requires that all works based -on this software must also be made publicly available under the terms of -the GPL2 ("Copyleft"). - -Contact information -------------------- - -Circuits At Home, LTD -Web : http://www.circuitsathome.com -e-mail : support@circuitsathome.com -*/ - -/* Google ADK interface support header */ - -#if !defined(_ADK_H_) -#define _ADK_H_ - -#include -#include -#include "avrpins.h" -#include "max3421e.h" -#include "usbhost.h" -#include "usb_ch9.h" -#include "Usb.h" - -#if defined(ARDUINO) && ARDUINO >=100 -#include "Arduino.h" -#else -#include -#endif - -#include "printhex.h" -#include "hexdump.h" -#include "message.h" - -#include "confdescparser.h" - -#define ADK_VID 0x18D1 -#define ADK_PID 0x2D00 -#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 */ - -#define ADK_GETPROTO 51 //check USB accessory protocol version -#define ADK_SENDSTR 52 //send identifying string -#define ADK_ACCSTART 53 //start device in accessory mode - -#define bmREQ_ADK_GET USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_VENDOR|USB_SETUP_RECIPIENT_DEVICE -#define bmREQ_ADK_SEND USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_VENDOR|USB_SETUP_RECIPIENT_DEVICE - -#define ACCESSORY_STRING_MANUFACTURER 0 -#define ACCESSORY_STRING_MODEL 1 -#define ACCESSORY_STRING_DESCRIPTION 2 -#define ACCESSORY_STRING_VERSION 3 -#define ACCESSORY_STRING_URI 4 -#define ACCESSORY_STRING_SERIAL 5 - -#define ADK_MAX_ENDPOINTS 3 //endpoint 0, bulk_IN, bulk_OUT - -class ADK; - -class ADK : public USBDeviceConfig, public UsbConfigXtracter -{ -private: - /* ID strings */ - const char* manufacturer; - const char* model; - const char* description; - const char* version; - const char* uri; - const char* serial; - - /* ADK proprietary requests */ - uint8_t getProto( uint8_t* adkproto ); - uint8_t sendStr( uint8_t index, const char* str ); - uint8_t switchAcc( void ); - -protected: - static const uint8_t epDataInIndex; // DataIn endpoint index - static const uint8_t epDataOutIndex; // DataOUT endpoint index - - /* mandatory members */ - USB *pUsb; - uint8_t bAddress; - uint8_t bConfNum; // configuration number - - uint8_t bNumEP; // total number of EP in the configuration - bool ready; - - /* Endpoint data structure */ - EpInfo epInfo[ADK_MAX_ENDPOINTS]; - - void PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr); - -public: - ADK(USB *pUsb, const char* manufacturer, - const char* model, - const char* description, - const char* version, - const char* uri, - const char* serial); - - // Methods for receiving and sending data - uint8_t RcvData(uint16_t *nbytesptr, uint8_t *dataptr); - uint8_t SndData(uint16_t nbytes, uint8_t *dataptr); - - - // USBDeviceConfig implementation - virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed); - virtual uint8_t Release(); - virtual uint8_t Poll(){}; //not implemented - virtual uint8_t GetAddress() { return bAddress; }; - virtual bool isReady() { return ready; }; - - //UsbConfigXtracter implementation - virtual void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep); -}; //class ADK : public USBDeviceConfig ... - -/* get ADK protocol version */ -/* returns 2 bytes in *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 )); -} -/* send ADK string */ -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)); -} -/* switch to accessory mode */ -inline uint8_t ADK::switchAcc( void ) -{ - return( pUsb->ctrlReq(bAddress, 0, bmREQ_ADK_SEND, ADK_ACCSTART, 0, 0, 0, 0, 0, NULL, NULL)); -} - +/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. + +This software may be distributed and modified under the terms of the GNU +General Public License version 2 (GPL2) as published by the Free Software +Foundation and appearing in the file GPL2.TXT included in the packaging of +this file. Please note that GPL2 Section 2[b] requires that all works based +on this software must also be made publicly available under the terms of +the GPL2 ("Copyleft"). + +Contact information +------------------- + +Circuits At Home, LTD +Web : http://www.circuitsathome.com +e-mail : support@circuitsathome.com + */ + +/* Google ADK interface support header */ + +#if !defined(_ADK_H_) +#define _ADK_H_ + +#include +#include +#include "avrpins.h" +#include "max3421e.h" +#include "usbhost.h" +#include "usb_ch9.h" +#include "Usb.h" + +#if defined(ARDUINO) && ARDUINO >=100 +#include "Arduino.h" +#else +#include +#endif + +#include "printhex.h" +#include "hexdump.h" +#include "message.h" + +#include "confdescparser.h" + +#define ADK_VID 0x18D1 +#define ADK_PID 0x2D00 +#define ADB_PID 0x2D01 + +/* requests */ + +#define ADK_GETPROTO 51 //check USB accessory protocol version +#define ADK_SENDSTR 52 //send identifying string +#define ADK_ACCSTART 53 //start device in accessory mode + +#define bmREQ_ADK_GET USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_VENDOR|USB_SETUP_RECIPIENT_DEVICE +#define bmREQ_ADK_SEND USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_VENDOR|USB_SETUP_RECIPIENT_DEVICE + +#define ACCESSORY_STRING_MANUFACTURER 0 +#define ACCESSORY_STRING_MODEL 1 +#define ACCESSORY_STRING_DESCRIPTION 2 +#define ACCESSORY_STRING_VERSION 3 +#define ACCESSORY_STRING_URI 4 +#define ACCESSORY_STRING_SERIAL 5 + +#define ADK_MAX_ENDPOINTS 3 //endpoint 0, bulk_IN, bulk_OUT + +class ADK; + +class ADK : public USBDeviceConfig, public UsbConfigXtracter { +private: + /* ID strings */ + const char* manufacturer; + const char* model; + const char* description; + const char* version; + const char* uri; + const char* serial; + + /* ADK proprietary requests */ + uint8_t getProto(uint8_t* adkproto); + uint8_t sendStr(uint8_t index, const char* str); + uint8_t switchAcc(void); + +protected: + static const uint8_t epDataInIndex; // DataIn endpoint index + static const uint8_t epDataOutIndex; // DataOUT endpoint index + + /* mandatory members */ + USB *pUsb; + uint8_t bAddress; + uint8_t bConfNum; // configuration number + + uint8_t bNumEP; // total number of EP in the configuration + bool ready; + + /* Endpoint data structure */ + EpInfo epInfo[ADK_MAX_ENDPOINTS]; + + void PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr); + +public: + ADK(USB *pUsb, const char* manufacturer, + const char* model, + const char* description, + const char* version, + const char* uri, + const char* serial); + + // Methods for receiving and sending data + uint8_t RcvData(uint16_t *nbytesptr, uint8_t *dataptr); + uint8_t SndData(uint16_t nbytes, uint8_t *dataptr); + + + // USBDeviceConfig implementation + virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed); + virtual uint8_t Release(); + + virtual uint8_t Poll() { + return 0; + }; + + virtual uint8_t GetAddress() { + return bAddress; + }; + + virtual bool isReady() { + return ready; + }; + + //UsbConfigXtracter implementation + virtual void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep); +}; //class ADK : public USBDeviceConfig ... + +/* get ADK protocol version */ + +/* returns 2 bytes in *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)); +} + +/* send ADK string */ +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)); +} + +/* switch to accessory mode */ +inline uint8_t ADK::switchAcc(void) { + return ( pUsb->ctrlReq(bAddress, 0, bmREQ_ADK_SEND, ADK_ACCSTART, 0, 0, 0, 0, 0, NULL, NULL)); +} + #endif // _ADK_H_ \ No newline at end of file diff --git a/avrpins.h b/avrpins.h index f3b5ddb9..765a5530 100644 --- a/avrpins.h +++ b/avrpins.h @@ -13,24 +13,13 @@ Contact information Circuits At Home, LTD Web : http://www.circuitsathome.com e-mail : support@circuitsathome.com -*/ + */ /* derived from Konstantin Chizhov's AVR port templates */ #ifndef _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 #ifdef PORTA @@ -122,6 +111,7 @@ e-mail : support@circuitsathome.com }; #ifdef USE_PORTA + MAKE_PORT(PORTA, DDRA, PINA, Porta, 'A') #endif #ifdef USE_PORTB @@ -171,238 +161,271 @@ MAKE_TCCR(TCCR1A, Tccr1a) MAKE_TCCR(TCCR2A, Tccr2a) #endif - // this class represents one pin in a IO port. - // It is fully static. - template - class TPin - { -// BOOST_STATIC_ASSERT(PIN < PORT::Width); - public: - typedef PORT Port; - enum{Number = PIN}; +// this class represents one pin in a IO port. +// It is fully static. +template +class TPin { + // BOOST_STATIC_ASSERT(PIN < PORT::Width); +public: + typedef PORT Port; - static void Set() { PORT::Set(1 << PIN); } + enum { + Number = PIN + }; - static void Set(uint8_t val){ - if(val) - Set(); - else Clear();} + static void Set() { + PORT::Set(1 << PIN); + } - static void SetDir(uint8_t val){ - if(val) - SetDirWrite(); - else SetDirRead();} + static void Set(uint8_t val) { + if (val) + Set(); + else Clear(); + } - static void Clear(){PORT::Clear(1 << PIN);} + static void SetDir(uint8_t val) { + if (val) + SetDirWrite(); + else SetDirRead(); + } - static void Toggle(){PORT::Toggle(1 << PIN);} + static void Clear() { + PORT::Clear(1 << PIN); + } - static void SetDirRead(){PORT::DirClear(1 << PIN);} + static void Toggle() { + PORT::Toggle(1 << PIN); + } - static void SetDirWrite(){PORT::DirSet(1 << PIN);} + static void SetDirRead() { + PORT::DirClear(1 << PIN); + } - static uint8_t IsSet(){return PORT::PinRead() & (uint8_t)(1 << PIN);} - - static void WaiteForSet(){ while(IsSet()==0){} } + static void SetDirWrite() { + PORT::DirSet(1 << PIN); + } - static void WaiteForClear(){ while(IsSet()){} } - }; //class TPin... + static uint8_t IsSet() { + return PORT::PinRead() & (uint8_t) (1 << PIN); + } - // this class represents one bit in TCCR port. - // used to set/clear TCCRx bits - // It is fully static. - template - class TCom - { -// BOOST_STATIC_ASSERT(PIN < PORT::Width); - public: - typedef TCCR Tccr; - enum{Com = COM}; + static void WaiteForSet() { + while (IsSet() == 0) { + } + } - static void Set() { TCCR::Set(1 << COM); } + static void WaiteForClear() { + while (IsSet()) { + } + } +}; //class TPin... - static void Clear() { TCCR::Clear(1 << COM); } +// this class represents one bit in TCCR port. +// used to set/clear TCCRx bits +// It is fully static. - static void Toggle() { TCCR::Toggle(1 << COM); } - }; //class TCom... +template +class TCom { + // BOOST_STATIC_ASSERT(PIN < PORT::Width); +public: + typedef TCCR Tccr; -//Short pin definitions + enum { + Com = COM + }; + + static void Set() { + TCCR::Set(1 << COM); + } + + static void Clear() { + TCCR::Clear(1 << COM); + } + + static void Toggle() { + TCCR::Toggle(1 << COM); + } +}; //class TCom... + +//Short pin definitions #ifdef USE_PORTA -typedef TPin Pa0; -typedef TPin Pa1; -typedef TPin Pa2; -typedef TPin Pa3; -typedef TPin Pa4; -typedef TPin Pa5; -typedef TPin Pa6; -typedef TPin Pa7; +typedef TPin Pa0; +typedef TPin Pa1; +typedef TPin Pa2; +typedef TPin Pa3; +typedef TPin Pa4; +typedef TPin Pa5; +typedef TPin Pa6; +typedef TPin Pa7; #endif #ifdef USE_PORTB -typedef TPin Pb0; -typedef TPin Pb1; -typedef TPin Pb2; -typedef TPin Pb3; -typedef TPin Pb4; -typedef TPin Pb5; -typedef TPin Pb6; -typedef TPin Pb7; +typedef TPin Pb0; +typedef TPin Pb1; +typedef TPin Pb2; +typedef TPin Pb3; +typedef TPin Pb4; +typedef TPin Pb5; +typedef TPin Pb6; +typedef TPin Pb7; #endif #ifdef USE_PORTC -typedef TPin Pc0; -typedef TPin Pc1; -typedef TPin Pc2; -typedef TPin Pc3; -typedef TPin Pc4; -typedef TPin Pc5; -typedef TPin Pc6; -typedef TPin Pc7; +typedef TPin Pc0; +typedef TPin Pc1; +typedef TPin Pc2; +typedef TPin Pc3; +typedef TPin Pc4; +typedef TPin Pc5; +typedef TPin Pc6; +typedef TPin Pc7; #endif #ifdef USE_PORTD -typedef TPin Pd0; -typedef TPin Pd1; -typedef TPin Pd2; -typedef TPin Pd3; -typedef TPin Pd4; -typedef TPin Pd5; -typedef TPin Pd6; -typedef TPin Pd7; +typedef TPin Pd0; +typedef TPin Pd1; +typedef TPin Pd2; +typedef TPin Pd3; +typedef TPin Pd4; +typedef TPin Pd5; +typedef TPin Pd6; +typedef TPin Pd7; #endif #ifdef USE_PORTE -typedef TPin Pe0; -typedef TPin Pe1; -typedef TPin Pe2; -typedef TPin Pe3; -typedef TPin Pe4; -typedef TPin Pe5; -typedef TPin Pe6; -typedef TPin Pe7; +typedef TPin Pe0; +typedef TPin Pe1; +typedef TPin Pe2; +typedef TPin Pe3; +typedef TPin Pe4; +typedef TPin Pe5; +typedef TPin Pe6; +typedef TPin Pe7; #endif #ifdef USE_PORTF -typedef TPin Pf0; -typedef TPin Pf1; -typedef TPin Pf2; -typedef TPin Pf3; -typedef TPin Pf4; -typedef TPin Pf5; -typedef TPin Pf6; -typedef TPin Pf7; +typedef TPin Pf0; +typedef TPin Pf1; +typedef TPin Pf2; +typedef TPin Pf3; +typedef TPin Pf4; +typedef TPin Pf5; +typedef TPin Pf6; +typedef TPin Pf7; #endif #ifdef USE_PORTG -typedef TPin Pg0; -typedef TPin Pg1; -typedef TPin Pg2; -typedef TPin Pg3; -typedef TPin Pg4; -typedef TPin Pg5; -typedef TPin Pg6; -typedef TPin Pg7; +typedef TPin Pg0; +typedef TPin Pg1; +typedef TPin Pg2; +typedef TPin Pg3; +typedef TPin Pg4; +typedef TPin Pg5; +typedef TPin Pg6; +typedef TPin Pg7; #endif #ifdef USE_PORTH -typedef TPin Ph0; -typedef TPin Ph1; -typedef TPin Ph2; -typedef TPin Ph3; -typedef TPin Ph4; -typedef TPin Ph5; -typedef TPin Ph6; -typedef TPin Ph7; +typedef TPin Ph0; +typedef TPin Ph1; +typedef TPin Ph2; +typedef TPin Ph3; +typedef TPin Ph4; +typedef TPin Ph5; +typedef TPin Ph6; +typedef TPin Ph7; #endif #ifdef USE_PORTJ -typedef TPin Pj0; -typedef TPin Pj1; -typedef TPin Pj2; -typedef TPin Pj3; -typedef TPin Pj4; -typedef TPin Pj5; -typedef TPin Pj6; -typedef TPin Pj7; +typedef TPin Pj0; +typedef TPin Pj1; +typedef TPin Pj2; +typedef TPin Pj3; +typedef TPin Pj4; +typedef TPin Pj5; +typedef TPin Pj6; +typedef TPin Pj7; #endif #ifdef USE_PORTK -typedef TPin Pk0; -typedef TPin Pk1; -typedef TPin Pk2; -typedef TPin Pk3; -typedef TPin Pk4; -typedef TPin Pk5; -typedef TPin Pk6; -typedef TPin Pk7; +typedef TPin Pk0; +typedef TPin Pk1; +typedef TPin Pk2; +typedef TPin Pk3; +typedef TPin Pk4; +typedef TPin Pk5; +typedef TPin Pk6; +typedef TPin Pk7; #endif #ifdef USE_PORTL -typedef TPin Pl0; -typedef TPin Pl1; -typedef TPin Pl2; -typedef TPin Pl3; -typedef TPin Pl4; -typedef TPin Pl5; -typedef TPin Pl6; -typedef TPin Pl7; +typedef TPin Pl0; +typedef TPin Pl1; +typedef TPin Pl2; +typedef TPin Pl3; +typedef TPin Pl4; +typedef TPin Pl5; +typedef TPin Pl6; +typedef TPin Pl7; #endif #ifdef USE_PORTQ -typedef TPin Pq0; -typedef TPin Pq1; -typedef TPin Pq2; -typedef TPin Pq3; -typedef TPin Pq4; -typedef TPin Pq5; -typedef TPin Pq6; -typedef TPin Pq7; +typedef TPin Pq0; +typedef TPin Pq1; +typedef TPin Pq2; +typedef TPin Pq3; +typedef TPin Pq4; +typedef TPin Pq5; +typedef TPin Pq6; +typedef TPin Pq7; #endif #ifdef USE_PORTR -typedef TPin Pr0; -typedef TPin Pr1; -typedef TPin Pr2; -typedef TPin Pr3; -typedef TPin Pr4; -typedef TPin Pr5; -typedef TPin Pr6; -typedef TPin Pr7; +typedef TPin Pr0; +typedef TPin Pr1; +typedef TPin Pr2; +typedef TPin Pr3; +typedef TPin Pr4; +typedef TPin Pr5; +typedef TPin Pr6; +typedef TPin Pr7; #endif #ifdef USE_TCCR0A -typedef TCom Tc0a; //P6 -typedef TCom Tc0b; //P5 +typedef TCom Tc0a; //P6 +typedef TCom Tc0b; //P5 #endif #ifdef USE_TCCR1A -typedef TCom Tc1a; //P9 -typedef TCom Tc1b; //P10 +typedef TCom Tc1a; //P9 +typedef TCom Tc1b; //P10 #endif #ifdef USE_TCCR2A -typedef TCom Tc2a; //P11 -typedef TCom Tc2b; //P3 +typedef TCom Tc2a; //P11 +typedef TCom Tc2b; //P3 #endif template - class Tp_Tc - { - public: - static void SetDir(uint8_t val){ - if(val) - SetDirWrite(); - else SetDirRead(); - } - static void SetDirRead(){ - Tp_pin::SetDirRead(); //set pin direction - Tc_bit::Clear(); //disconnect pin from PWM - } - static void SetDirWrite(){ - Tp_pin::SetDirWrite(); - Tc_bit::Clear(); - } - }; +class Tp_Tc { +public: + + static void SetDir(uint8_t val) { + if (val) + SetDirWrite(); + else SetDirRead(); + } + + static void SetDirRead() { + Tp_pin::SetDirRead(); //set pin direction + Tc_bit::Clear(); //disconnect pin from PWM + } + + static void SetDirWrite() { + Tp_pin::SetDirWrite(); + Tc_bit::Clear(); + } +}; /* pin definitions for cases where it's necessary to clear compare output mode bits */ @@ -416,7 +439,7 @@ template /* Arduino pin definitions */ #if defined(__AVR_ATmega1280__) || (__AVR_ATmega2560__) -// "Mega" Arduino pin numbers +// "Mega" Arduino pin numbers #define P0 Pe0 #define P1 Pe1 @@ -424,7 +447,7 @@ template #define P3 Pe5 #define P4 Pg5 #define P5 Pe5 -#define P6 Ph3 +#define P6 Ph3 #define P7 Ph4 #define P8 Ph5 @@ -441,7 +464,7 @@ template #define P18 Pd3 #define P19 Pd2 #define P20 Pd1 -#define P21 Pd0 +#define P21 Pd0 #define P22 Pa0 #define P23 Pa1 @@ -476,7 +499,6 @@ template #define P51 Pb2 #define P52 Pb1 #define P53 Pb0 -#define P54 Pe6 // INT on Arduino ADK #endif //"Mega" pin numbers @@ -489,7 +511,7 @@ template #define P3 Pd3 #define P4 Pd4 #define P5 Pd5 -#define P6 Pd6 +#define P6 Pd6 #define P7 Pd7 #define P8 Pb0 @@ -508,47 +530,7 @@ template #endif // "Classic" Arduino pin numbers -#if !defined(BOARD_TEENSY) && 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__) +#if defined(__AVR_ATmega32U4__) // Teensy 2.0 pin numbers // http://www.pjrc.com/teensy/pinout.html #define P0 Pb0 @@ -629,45 +611,7 @@ template #define P45 Pf7 #endif // Teensy++ 2.0 -#if !defined(BOARD_SANGUINO) && (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__)) +#if defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) // Sanguino pin numbers // http://sanguino.cc/hardware #define P0 Pb0 diff --git a/cdcacm.cpp b/cdcacm.cpp index e93e61eb..9c535a6e 100644 --- a/cdcacm.cpp +++ b/cdcacm.cpp @@ -1,359 +1,337 @@ -/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. - -This software may be distributed and modified under the terms of the GNU -General Public License version 2 (GPL2) as published by the Free Software -Foundation and appearing in the file GPL2.TXT included in the packaging of -this file. Please note that GPL2 Section 2[b] requires that all works based -on this software must also be made publicly available under the terms of -the GPL2 ("Copyleft"). - -Contact information -------------------- - -Circuits At Home, LTD -Web : http://www.circuitsathome.com -e-mail : support@circuitsathome.com -*/ -#include "cdcacm.h" - -const uint8_t ACM::epDataInIndex = 1; -const uint8_t ACM::epDataOutIndex = 2; -const uint8_t ACM::epInterruptInIndex = 3; - -ACM::ACM(USB *p, CDCAsyncOper *pasync) : - pUsb(p), - pAsync(pasync), - bAddress(0), - qNextPollTime(0), - bPollEnable(false), - bControlIface(0), - bDataIface(0), - bNumEP(1), - ready(false) -{ - for(uint8_t i=0; iRegisterDeviceClass(this); -} - -uint8_t ACM::Init(uint8_t parent, uint8_t port, bool lowspeed) -{ - const uint8_t constBufSize = sizeof(USB_DEVICE_DESCRIPTOR); - - uint8_t buf[constBufSize]; - uint8_t rcode; - UsbDevice *p = NULL; - EpInfo *oldep_ptr = NULL; - uint8_t num_of_conf; // number of configurations - - AddressPool &addrPool = pUsb->GetAddressPool(); - - USBTRACE("ACM Init\r\n"); - - if (bAddress) - return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE; - - // Get pointer to pseudo device with address 0 assigned - p = addrPool.GetUsbDevicePtr(0); - - if (!p) - return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; - - if (!p->epinfo) - { - USBTRACE("epinfo\r\n"); - return USB_ERROR_EPINFO_IS_NULL; - } - - // Save old pointer to EP_RECORD of address 0 - oldep_ptr = p->epinfo; - - // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence - p->epinfo = epInfo; - - p->lowspeed = lowspeed; - - // Get device descriptor - rcode = pUsb->getDevDescr( 0, 0, constBufSize, (uint8_t*)buf ); - - // Restore p->epinfo - p->epinfo = oldep_ptr; - - if( rcode ) - goto FailGetDevDescr; - - // Allocate new address according to device class - bAddress = addrPool.AllocAddress(parent, false, port); - - if (!bAddress) - return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; - - // Extract Max Packet Size from the device descriptor - epInfo[0].maxPktSize = (uint8_t)((USB_DEVICE_DESCRIPTOR*)buf)->bMaxPacketSize0; - - // Assign new address to the device - rcode = pUsb->setAddr( 0, 0, bAddress ); - - if (rcode) - { - p->lowspeed = false; - addrPool.FreeAddress(bAddress); - bAddress = 0; - USBTRACE2("setAddr:",rcode); - return rcode; - } - - USBTRACE2("Addr:", bAddress); - - p->lowspeed = false; - - p = addrPool.GetUsbDevicePtr(bAddress); - - if (!p) - return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; - - p->lowspeed = lowspeed; - - num_of_conf = ((USB_DEVICE_DESCRIPTOR*)buf)->bNumConfigurations; - - // Assign epInfo to epinfo pointer - rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); - - if (rcode) - goto FailSetDevTblEntry; - - USBTRACE2("NC:", num_of_conf); - - for (uint8_t i=0; i CdcControlParser(this); - - ConfigDescParser CdcDataParser(this); - - rcode = pUsb->getConfDescr(bAddress, 0, i, &CdcControlParser); - rcode = pUsb->getConfDescr(bAddress, 0, i, &CdcDataParser); - - if (bNumEP > 1) - break; - } // for - - if (bNumEP < 4) - return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; - - // Assign epInfo to epinfo pointer - rcode = pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo); - - USBTRACE2("Conf:", bConfNum); - - // Set Configuration Value - rcode = pUsb->setConf(bAddress, 0, bConfNum); - - if (rcode) - goto FailSetConf; - - rcode = pAsync->OnInit(this); - - if (rcode) - goto FailOnInit; - - USBTRACE("ACM configured\r\n"); - ready = true; - - //bPollEnable = true; - - //USBTRACE("Poll enabled\r\n"); - return 0; - -FailGetDevDescr: - USBTRACE("getDevDescr:"); - goto Fail; - -FailSetDevTblEntry: - USBTRACE("setDevTblEn:"); - goto Fail; - -FailGetConfDescr: - USBTRACE("getConf:"); - goto Fail; - -FailSetConf: - USBTRACE("setConf:"); - goto Fail; - -FailOnInit: - USBTRACE("OnInit:"); - goto Fail; - -Fail: - Serial.println(rcode, HEX); - Release(); - return rcode; -} - - -void ACM::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *pep) -{ - //ErrorMessage(PSTR("Conf.Val"), conf); - //ErrorMessage(PSTR("Iface Num"),iface); - //ErrorMessage(PSTR("Alt.Set"), alt); - - bConfNum = conf; - - uint8_t index; - - if ((pep->bmAttributes & 0x03) == 3 && (pep->bEndpointAddress & 0x80) == 0x80) - index = epInterruptInIndex; - else - if ((pep->bmAttributes & 0x02) == 2) - index = ((pep->bEndpointAddress & 0x80) == 0x80) ? epDataInIndex : epDataOutIndex; - else - return; - - // Fill in the endpoint info structure - epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F); - epInfo[index].maxPktSize = (uint8_t)pep->wMaxPacketSize; - //epInfo[index].epAttribs = 0; - - bNumEP ++; - - //PrintEndpointDescriptor(pep); -} - -uint8_t ACM::Release() -{ - pUsb->GetAddressPool().FreeAddress(bAddress); - - bControlIface = 0; - bDataIface = 0; - bNumEP = 1; - - bAddress = 0; - qNextPollTime = 0; - bPollEnable = false; - ready = false; - return 0; -} - -uint8_t ACM::Poll() -{ - uint8_t rcode = 0; - - if (!bPollEnable) - return 0; - - //uint32_t time_now = millis(); - - //if (qNextPollTime <= time_now) - //{ - // qNextPollTime = time_now + 100; - - // uint8_t rcode; - // const uint8_t constBufSize = 16; - // uint8_t buf[constBufSize]; - - // for (uint8_t i=0; i epInfo[epInterruptInIndex].maxPktSize) - // ? epInfo[epInterruptInIndex].maxPktSize : constBufSize; - // rcode = pUsb->inTransfer(bAddress, epInfo[epInterruptInIndex].epAddr, &read, buf); - - // if (rcode) - // return rcode; - - // for (uint8_t i=0; i(buf[i]); - // Serial.print(" "); - // } - // USBTRACE("\r\n"); - //} - return rcode; -} - -uint8_t ACM::RcvData(uint16_t *bytes_rcvd, uint8_t *dataptr) -{ - return pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, bytes_rcvd, dataptr); -} - -uint8_t ACM::SndData(uint16_t nbytes, uint8_t *dataptr) -{ - return pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, nbytes, dataptr); -} - -/* untested */ -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 )); -} - -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 )); -} - -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 )); -} - -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 )); -} - -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 )); -} - -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 )); -} - -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 )); -} - - -void ACM::PrintEndpointDescriptor( const USB_ENDPOINT_DESCRIPTOR* ep_ptr ) -{ - Notify(PSTR("Endpoint descriptor:")); - Notify(PSTR("\r\nLength:\t\t")); - PrintHex(ep_ptr->bLength); - Notify(PSTR("\r\nType:\t\t")); - PrintHex(ep_ptr->bDescriptorType); - Notify(PSTR("\r\nAddress:\t")); - PrintHex(ep_ptr->bEndpointAddress); - Notify(PSTR("\r\nAttributes:\t")); - PrintHex(ep_ptr->bmAttributes); - Notify(PSTR("\r\nMaxPktSize:\t")); - PrintHex(ep_ptr->wMaxPacketSize); - Notify(PSTR("\r\nPoll Intrv:\t")); - PrintHex(ep_ptr->bInterval); - Notify(PSTR("\r\n")); -} +/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. + +This software may be distributed and modified under the terms of the GNU +General Public License version 2 (GPL2) as published by the Free Software +Foundation and appearing in the file GPL2.TXT included in the packaging of +this file. Please note that GPL2 Section 2[b] requires that all works based +on this software must also be made publicly available under the terms of +the GPL2 ("Copyleft"). + +Contact information +------------------- + +Circuits At Home, LTD +Web : http://www.circuitsathome.com +e-mail : support@circuitsathome.com + */ +#include "cdcacm.h" + +const uint8_t ACM::epDataInIndex = 1; +const uint8_t ACM::epDataOutIndex = 2; +const uint8_t ACM::epInterruptInIndex = 3; + +ACM::ACM(USB *p, CDCAsyncOper *pasync) : +pUsb(p), +pAsync(pasync), +bAddress(0), +bControlIface(0), +bDataIface(0), +bNumEP(1), +qNextPollTime(0), +bPollEnable(false) { + for (uint8_t i = 0; i < ACM_MAX_ENDPOINTS; i++) { + epInfo[i].epAddr = 0; + epInfo[i].maxPktSize = (i) ? 0 : 8; + epInfo[i].epAttribs = 0; + //epInfo[i].bmNakPower = USB_NAK_NOWAIT; + epInfo[i].bmNakPower = USB_NAK_MAX_POWER; + + //if (!i) + epInfo[i].bmNakPower = USB_NAK_MAX_POWER; + } + if (pUsb) + pUsb->RegisterDeviceClass(this); +} + +uint8_t ACM::Init(uint8_t parent, uint8_t port, bool lowspeed) { + const uint8_t constBufSize = sizeof (USB_DEVICE_DESCRIPTOR); + + uint8_t buf[constBufSize]; + uint8_t rcode; + UsbDevice *p = NULL; + EpInfo *oldep_ptr = NULL; + uint8_t num_of_conf; // number of configurations + + AddressPool &addrPool = pUsb->GetAddressPool(); + + USBTRACE("ACM Init\r\n"); + + if (bAddress) + return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE; + + // Get pointer to pseudo device with address 0 assigned + p = addrPool.GetUsbDevicePtr(0); + + if (!p) + return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; + + if (!p->epinfo) { + USBTRACE("epinfo\r\n"); + return USB_ERROR_EPINFO_IS_NULL; + } + + // Save old pointer to EP_RECORD of address 0 + oldep_ptr = p->epinfo; + + // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence + p->epinfo = epInfo; + + p->lowspeed = lowspeed; + + // Get device descriptor + rcode = pUsb->getDevDescr(0, 0, constBufSize, (uint8_t*) buf); + + // Restore p->epinfo + p->epinfo = oldep_ptr; + + if (rcode) + goto FailGetDevDescr; + + // Allocate new address according to device class + bAddress = addrPool.AllocAddress(parent, false, port); + + if (!bAddress) + return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; + + // Extract Max Packet Size from the device descriptor + epInfo[0].maxPktSize = (uint8_t) ((USB_DEVICE_DESCRIPTOR*) buf)->bMaxPacketSize0; + + // Assign new address to the device + rcode = pUsb->setAddr(0, 0, bAddress); + + if (rcode) { + p->lowspeed = false; + addrPool.FreeAddress(bAddress); + bAddress = 0; + USBTRACE2("setAddr:", rcode); + return rcode; + } + + USBTRACE2("Addr:", bAddress); + + p->lowspeed = false; + + p = addrPool.GetUsbDevicePtr(bAddress); + + if (!p) + return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; + + p->lowspeed = lowspeed; + + num_of_conf = ((USB_DEVICE_DESCRIPTOR*) buf)->bNumConfigurations; + + // Assign epInfo to epinfo pointer + rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); + + if (rcode) + goto FailSetDevTblEntry; + + USBTRACE2("NC:", num_of_conf); + + for (uint8_t i = 0; i < num_of_conf; i++) { + ConfigDescParser< USB_CLASS_COM_AND_CDC_CTRL, + CDC_SUBCLASS_ACM, + CDC_PROTOCOL_ITU_T_V_250, + CP_MASK_COMPARE_CLASS | + CP_MASK_COMPARE_SUBCLASS | + CP_MASK_COMPARE_PROTOCOL > CdcControlParser(this); + + ConfigDescParser CdcDataParser(this); + + rcode = pUsb->getConfDescr(bAddress, 0, i, &CdcControlParser); + + if (rcode) + goto FailGetConfDescr; + + rcode = pUsb->getConfDescr(bAddress, 0, i, &CdcDataParser); + + if (rcode) + goto FailGetConfDescr; + + if (bNumEP > 1) + break; + } // for + + if (bNumEP < 4) + return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; + + // Assign epInfo to epinfo pointer + rcode = pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo); + + USBTRACE2("Conf:", bConfNum); + + // Set Configuration Value + rcode = pUsb->setConf(bAddress, 0, bConfNum); + + if (rcode) + goto FailSetConf; + + rcode = pAsync->OnInit(this); + + if (rcode) + goto FailOnInit; + + USBTRACE("ACM configured\r\n"); + + //bPollEnable = true; + + //USBTRACE("Poll enabled\r\n"); + return 0; + +FailGetDevDescr: + USBTRACE("getDevDescr:"); + goto Fail; + +FailSetDevTblEntry: + USBTRACE("setDevTblEn:"); + goto Fail; + +FailGetConfDescr: + USBTRACE("getConf:"); + goto Fail; + +FailSetConf: + USBTRACE("setConf:"); + goto Fail; + +FailOnInit: + USBTRACE("OnInit:"); + goto Fail; + +Fail: + PrintHex (rcode, 0x80); + Notify(PSTR("\r\n"), 0x80); + // Serial.println(rcode, HEX); + Release(); + return rcode; +} + +void ACM::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *pep) { + ErrorMessage (PSTR("Conf.Val"), conf); + ErrorMessage (PSTR("Iface Num"), iface); + ErrorMessage (PSTR("Alt.Set"), alt); + + bConfNum = conf; + + uint8_t index; + + if ((pep->bmAttributes & 0x03) == 3 && (pep->bEndpointAddress & 0x80) == 0x80) + index = epInterruptInIndex; + else + if ((pep->bmAttributes & 0x02) == 2) + index = ((pep->bEndpointAddress & 0x80) == 0x80) ? epDataInIndex : epDataOutIndex; + else + return; + + // Fill in the endpoint info structure + epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F); + epInfo[index].maxPktSize = (uint8_t) pep->wMaxPacketSize; + epInfo[index].epAttribs = 0; + + bNumEP++; + + PrintEndpointDescriptor(pep); +} + +uint8_t ACM::Release() { + pUsb->GetAddressPool().FreeAddress(bAddress); + + bControlIface = 0; + bDataIface = 0; + bNumEP = 1; + + bAddress = 0; + qNextPollTime = 0; + bPollEnable = false; + return 0; +} + +uint8_t ACM::Poll() { + uint8_t rcode = 0; + + if (!bPollEnable) + return 0; + + //uint32_t time_now = millis(); + + //if (qNextPollTime <= time_now) + //{ + // qNextPollTime = time_now + 100; + + // uint8_t rcode; + // const uint8_t constBufSize = 16; + // uint8_t buf[constBufSize]; + + // for (uint8_t i=0; i epInfo[epInterruptInIndex].maxPktSize) + // ? epInfo[epInterruptInIndex].maxPktSize : constBufSize; + // rcode = pUsb->inTransfer(bAddress, epInfo[epInterruptInIndex].epAddr, &read, buf); + + // if (rcode) + // return rcode; + + // for (uint8_t i=0; i(buf[i]); + // Serial.print(" "); + // } + // USBTRACE("\r\n"); + //} + return rcode; +} + +uint8_t ACM::RcvData(uint16_t *bytes_rcvd, uint8_t *dataptr) { + return pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, bytes_rcvd, dataptr); +} + +uint8_t ACM::SndData(uint16_t nbytes, uint8_t *dataptr) { + return pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, nbytes, 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)); +} + +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)); +} + +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)); +} + +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)); +} + +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)); +} + +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)); +} + +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)); +} + +void ACM::PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr) { + Notify(PSTR("Endpoint descriptor:"), 0x80); + Notify(PSTR("\r\nLength:\t\t"), 0x80); + PrintHex (ep_ptr->bLength, 0x80); + Notify(PSTR("\r\nType:\t\t"), 0x80); + PrintHex (ep_ptr->bDescriptorType, 0x80); + Notify(PSTR("\r\nAddress:\t"), 0x80); + PrintHex (ep_ptr->bEndpointAddress, 0x80); + Notify(PSTR("\r\nAttributes:\t"), 0x80); + PrintHex (ep_ptr->bmAttributes, 0x80); + Notify(PSTR("\r\nMaxPktSize:\t"), 0x80); + PrintHex (ep_ptr->wMaxPacketSize, 0x80); + Notify(PSTR("\r\nPoll Intrv:\t"), 0x80); + PrintHex (ep_ptr->bInterval, 0x80); + Notify(PSTR("\r\n"), 0x80); +} diff --git a/cdcacm.h b/cdcacm.h index d8b8db55..34c92b93 100644 --- a/cdcacm.h +++ b/cdcacm.h @@ -1,211 +1,185 @@ -/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. - -This software may be distributed and modified under the terms of the GNU -General Public License version 2 (GPL2) as published by the Free Software -Foundation and appearing in the file GPL2.TXT included in the packaging of -this file. Please note that GPL2 Section 2[b] requires that all works based -on this software must also be made publicly available under the terms of -the GPL2 ("Copyleft"). - -Contact information -------------------- - -Circuits At Home, LTD -Web : http://www.circuitsathome.com -e-mail : support@circuitsathome.com -*/ -#if !defined(__CDCACM_H__) -#define __CDCACM_H__ - -#include -#include -#include "avrpins.h" -#include "max3421e.h" -#include "usbhost.h" -#include "usb_ch9.h" -#include "Usb.h" - -#if defined(ARDUINO) && ARDUINO >=100 -#include "Arduino.h" -#else -#include -#endif - -#include "printhex.h" -#include "hexdump.h" -#include "message.h" - -#include "confdescparser.h" - -#define bmREQ_CDCOUT USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE -#define bmREQ_CDCIN USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE - -// CDC Subclass Constants -#define CDC_SUBCLASS_DLCM 0x01 // Direct Line Control Model -#define CDC_SUBCLASS_ACM 0x02 // Abstract Control Model -#define CDC_SUBCLASS_TCM 0x03 // Telephone Control Model -#define CDC_SUBCLASS_MCCM 0x04 // Multi Channel Control Model -#define CDC_SUBCLASS_CAPI 0x05 // CAPI Control Model -#define CDC_SUBCLASS_ETHERNET 0x06 // Ethernet Network Control Model -#define CDC_SUBCLASS_ATM 0x07 // ATM Network Control Model -#define CDC_SUBCLASS_WIRELESS_HANDSET 0x08 // Wireless Handset Control Model -#define CDC_SUBCLASS_DEVICE_MANAGEMENT 0x09 // Device Management -#define CDC_SUBCLASS_MOBILE_DIRECT_LINE 0x0A // Mobile Direct Line Model -#define CDC_SUBCLASS_OBEX 0x0B // OBEX -#define CDC_SUBCLASS_ETHERNET_EMU 0x0C // Ethernet Emulation Model - -// Communication Interface Class Control Protocol Codes -#define CDC_PROTOCOL_ITU_T_V_250 0x01 // AT Commands defined by ITU-T V.250 -#define CDC_PROTOCOL_PCCA_101 0x02 // AT Commands defined by PCCA-101 -#define CDC_PROTOCOL_PCCA_101_O 0x03 // AT Commands defined by PCCA-101 & Annex O -#define CDC_PROTOCOL_GSM_7_07 0x04 // AT Commands defined by GSM 7.07 -#define CDC_PROTOCOL_3GPP_27_07 0x05 // AT Commands defined by 3GPP 27.007 -#define CDC_PROTOCOL_C_S0017_0 0x06 // AT Commands defined by TIA for CDMA -#define CDC_PROTOCOL_USB_EEM 0x07 // Ethernet Emulation Model - -// CDC Commands defined by CDC 1.2 -#define CDC_SEND_ENCAPSULATED_COMMAND 0x00 -#define CDC_GET_ENCAPSULATED_RESPONSE 0x01 - -// CDC Commands defined by PSTN 1.2 -#define CDC_SET_COMM_FEATURE 0x02 -#define CDC_GET_COMM_FEATURE 0x03 -#define CDC_CLEAR_COMM_FEATURE 0x04 -#define CDC_SET_AUX_LINE_STATE 0x10 -#define CDC_SET_HOOK_STATE 0x11 -#define CDC_PULSE_SETUP 0x12 -#define CDC_SEND_PULSE 0x13 -#define CDC_SET_PULSE_TIME 0x14 -#define CDC_RING_AUX_JACK 0x15 -#define CDC_SET_LINE_CODING 0x20 -#define CDC_GET_LINE_CODING 0x21 -#define CDC_SET_CONTROL_LINE_STATE 0x22 -#define CDC_SEND_BREAK 0x23 -#define CDC_SET_RINGER_PARMS 0x30 -#define CDC_GET_RINGER_PARMS 0x31 -#define CDC_SET_OPERATION_PARMS 0x32 -#define CDC_GET_OPERATION_PARMS 0x33 -#define CDC_SET_LINE_PARMS 0x34 -#define CDC_GET_LINE_PARMS 0x35 -#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 -typedef struct -{ - uint8_t bFunctionLength; - uint8_t bDescriptorType; - uint8_t bDescriptorSubtype; - uint8_t bmCapabilities; - uint8_t bDataInterface; -} CALL_MGMNT_FUNC_DESCR; - -typedef struct -{ - uint8_t bFunctionLength; - uint8_t bDescriptorType; - uint8_t bDescriptorSubtype; - uint8_t bmCapabilities; -} ACM_FUNC_DESCR, DLM_FUNC_DESCR, TEL_OPER_MODES_FUNC_DESCR, - TEL_CALL_STATE_REP_CPBL_FUNC_DESCR; - -typedef struct -{ - uint8_t bFunctionLength; - uint8_t bDescriptorType; - uint8_t bDescriptorSubtype; - uint8_t bRingerVolSteps; - uint8_t bNumRingerPatterns; -} TEL_RINGER_FUNC_DESCR; - -typedef struct -{ - 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 bParityType; // 0 - None, 1 - Odd, 2 - Even, 3 - Mark, 4 - Space - uint8_t bDataBits; // Data bits (5, 6, 7, 8 or 16) -} 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 CDCAsyncOper -{ -public: - virtual uint8_t OnInit(ACM *pacm) = 0; - //virtual void OnDataRcvd(ACM *pacm, uint8_t nbytes, uint8_t *dataptr) = 0; - //virtual void OnDisconnected(ACM *pacm) = 0; -}; - - -#define ACM_MAX_ENDPOINTS 4 - -class ACM : public USBDeviceConfig, public UsbConfigXtracter -{ -protected: - static const uint8_t epDataInIndex; // DataIn endpoint index - static const uint8_t epDataOutIndex; // DataOUT endpoint index - static const uint8_t epInterruptInIndex; // InterruptIN endpoint index - - USB *pUsb; - CDCAsyncOper *pAsync; - uint8_t bAddress; - uint8_t bConfNum; // configuration number - uint8_t bControlIface; // Control interface value - uint8_t bDataIface; // Data interface value - uint8_t bNumEP; // total number of EP in the configuration - uint32_t qNextPollTime; // next poll time - bool bPollEnable; // poll enable flag - bool ready; //device ready indicator - - EpInfo epInfo[ACM_MAX_ENDPOINTS]; - - void PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr); - -public: - ACM(USB *pusb, CDCAsyncOper *pasync); - - uint8_t SetCommFeature(uint16_t fid, uint8_t nbytes, uint8_t *dataptr); - uint8_t GetCommFeature(uint16_t fid, uint8_t nbytes, uint8_t *dataptr); - uint8_t ClearCommFeature(uint16_t fid); - uint8_t SetLineCoding(const LINE_CODING *dataptr); - uint8_t GetLineCoding(LINE_CODING *dataptr); - uint8_t SetControlLineState(uint8_t state); - uint8_t SendBreak(uint16_t duration); - uint8_t GetNotif( uint16_t *bytes_rcvd, uint8_t *dataptr ); - - // Methods for recieving and sending data - uint8_t RcvData(uint16_t *nbytesptr, uint8_t *dataptr); - uint8_t SndData(uint16_t nbytes, uint8_t *dataptr); - - // USBDeviceConfig implementation - virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed); - virtual uint8_t Release(); - virtual uint8_t Poll(); - virtual uint8_t GetAddress() { return bAddress; }; - virtual bool isReady() { return ready; }; - - // UsbConfigXtracter implementation - virtual void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep); -}; - +/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. + +This software may be distributed and modified under the terms of the GNU +General Public License version 2 (GPL2) as published by the Free Software +Foundation and appearing in the file GPL2.TXT included in the packaging of +this file. Please note that GPL2 Section 2[b] requires that all works based +on this software must also be made publicly available under the terms of +the GPL2 ("Copyleft"). + +Contact information +------------------- + +Circuits At Home, LTD +Web : http://www.circuitsathome.com +e-mail : support@circuitsathome.com + */ +#if !defined(__CDCACM_H__) +#define __CDCACM_H__ + +#include +#include +#include "avrpins.h" +#include "max3421e.h" +#include "usbhost.h" +#include "usb_ch9.h" +#include "Usb.h" + +#if defined(ARDUINO) && ARDUINO >=100 +#include "Arduino.h" +#else +#include +#endif + +#include "printhex.h" +#include "hexdump.h" +#include "message.h" + +#include "confdescparser.h" + +#define bmREQ_CDCOUT USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE +#define bmREQ_CDCIN USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE + +// CDC Subclass Constants +#define CDC_SUBCLASS_DLCM 0x01 // Direct Line Control Model +#define CDC_SUBCLASS_ACM 0x02 // Abstract Control Model +#define CDC_SUBCLASS_TCM 0x03 // Telephone Control Model +#define CDC_SUBCLASS_MCCM 0x04 // Multi Channel Control Model +#define CDC_SUBCLASS_CAPI 0x05 // CAPI Control Model +#define CDC_SUBCLASS_ETHERNET 0x06 // Ethernet Network Control Model +#define CDC_SUBCLASS_ATM 0x07 // ATM Network Control Model +#define CDC_SUBCLASS_WIRELESS_HANDSET 0x08 // Wireless Handset Control Model +#define CDC_SUBCLASS_DEVICE_MANAGEMENT 0x09 // Device Management +#define CDC_SUBCLASS_MOBILE_DIRECT_LINE 0x0A // Mobile Direct Line Model +#define CDC_SUBCLASS_OBEX 0x0B // OBEX +#define CDC_SUBCLASS_ETHERNET_EMU 0x0C // Ethernet Emulation Model + +// Communication Interface Class Control Protocol Codes +#define CDC_PROTOCOL_ITU_T_V_250 0x01 // AT Commands defined by ITU-T V.250 +#define CDC_PROTOCOL_PCCA_101 0x02 // AT Commands defined by PCCA-101 +#define CDC_PROTOCOL_PCCA_101_O 0x03 // AT Commands defined by PCCA-101 & Annex O +#define CDC_PROTOCOL_GSM_7_07 0x04 // AT Commands defined by GSM 7.07 +#define CDC_PROTOCOL_3GPP_27_07 0x05 // AT Commands defined by 3GPP 27.007 +#define CDC_PROTOCOL_C_S0017_0 0x06 // AT Commands defined by TIA for CDMA +#define CDC_PROTOCOL_USB_EEM 0x07 // Ethernet Emulation Model + +// CDC Commands defined by CDC 1.2 +#define CDC_SEND_ENCAPSULATED_COMMAND 0x00 +#define CDC_GET_ENCAPSULATED_RESPONSE 0x01 + +// CDC Commands defined by PSTN 1.2 +#define CDC_SET_COMM_FEATURE 0x02 +#define CDC_GET_COMM_FEATURE 0x03 +#define CDC_CLEAR_COMM_FEATURE 0x04 +#define CDC_SET_AUX_LINE_STATE 0x10 +#define CDC_SET_HOOK_STATE 0x11 +#define CDC_PULSE_SETUP 0x12 +#define CDC_SEND_PULSE 0x13 +#define CDC_SET_PULSE_TIME 0x14 +#define CDC_RING_AUX_JACK 0x15 +#define CDC_SET_LINE_CODING 0x20 +#define CDC_GET_LINE_CODING 0x21 +#define CDC_SET_CONTROL_LINE_STATE 0x22 +#define CDC_SEND_BREAK 0x23 +#define CDC_SET_RINGER_PARMS 0x30 +#define CDC_GET_RINGER_PARMS 0x31 +#define CDC_SET_OPERATION_PARMS 0x32 +#define CDC_GET_OPERATION_PARMS 0x33 +#define CDC_SET_LINE_PARMS 0x34 +#define CDC_GET_LINE_PARMS 0x35 +#define CDC_DIAL_DIGITS 0x36 + +// CDC Functional Descriptor Structures + +typedef struct { + uint8_t bFunctionLength; + uint8_t bDescriptorType; + uint8_t bDescriptorSubtype; + uint8_t bmCapabilities; + uint8_t bDataInterface; +} CALL_MGMNT_FUNC_DESCR; + +typedef struct { + uint8_t bFunctionLength; + uint8_t bDescriptorType; + uint8_t bDescriptorSubtype; + uint8_t bmCapabilities; +} ACM_FUNC_DESCR, DLM_FUNC_DESCR, TEL_OPER_MODES_FUNC_DESCR, +TEL_CALL_STATE_REP_CPBL_FUNC_DESCR; + +typedef struct { + uint8_t bFunctionLength; + uint8_t bDescriptorType; + uint8_t bDescriptorSubtype; + uint8_t bRingerVolSteps; + uint8_t bNumRingerPatterns; +} TEL_RINGER_FUNC_DESCR; + +typedef struct { + 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 bParityType; // 0 - None, 1 - Odd, 2 - Even, 3 - Mark, 4 - Space + uint8_t bDataBits; // Data bits (5, 6, 7, 8 or 16) +} LINE_CODING; + +class ACM; + +class CDCAsyncOper { +public: + virtual uint8_t OnInit(ACM *pacm) = 0; + //virtual void OnDataRcvd(ACM *pacm, uint8_t nbytes, uint8_t *dataptr) = 0; + //virtual void OnDisconnected(ACM *pacm) = 0; +}; + + +#define ACM_MAX_ENDPOINTS 4 + +class ACM : public USBDeviceConfig, public UsbConfigXtracter { +protected: + static const uint8_t epDataInIndex; // DataIn endpoint index + static const uint8_t epDataOutIndex; // DataOUT endpoint index + static const uint8_t epInterruptInIndex; // InterruptIN endpoint index + + USB *pUsb; + CDCAsyncOper *pAsync; + uint8_t bAddress; + uint8_t bConfNum; // configuration number + uint8_t bControlIface; // Control interface value + uint8_t bDataIface; // Data interface value + uint8_t bNumEP; // total number of EP in the configuration + uint32_t qNextPollTime; // next poll time + bool bPollEnable; // poll enable flag + + EpInfo epInfo[ACM_MAX_ENDPOINTS]; + + void PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr); + +public: + ACM(USB *pusb, CDCAsyncOper *pasync); + + uint8_t SetCommFeature(uint16_t fid, uint8_t nbytes, uint8_t *dataptr); + uint8_t GetCommFeature(uint16_t fid, uint8_t nbytes, uint8_t *dataptr); + uint8_t ClearCommFeature(uint16_t fid); + uint8_t SetLineCoding(const LINE_CODING *dataptr); + uint8_t GetLineCoding(LINE_CODING *dataptr); + uint8_t SetControlLineState(uint8_t state); + uint8_t SendBreak(uint16_t duration); + + // Methods for recieving and sending data + uint8_t RcvData(uint16_t *nbytesptr, uint8_t *dataptr); + uint8_t SndData(uint16_t nbytes, uint8_t *dataptr); + + // USBDeviceConfig implementation + virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed); + virtual uint8_t Release(); + virtual uint8_t Poll(); + + virtual uint8_t GetAddress() { + return bAddress; + }; + + // UsbConfigXtracter implementation + virtual void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep); +}; + #endif // __CDCACM_H__ \ No newline at end of file diff --git a/cdcftdi.cpp b/cdcftdi.cpp index 4dbbc267..2ebca7ab 100644 --- a/cdcftdi.cpp +++ b/cdcftdi.cpp @@ -1,348 +1,332 @@ -/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. - -This software may be distributed and modified under the terms of the GNU -General Public License version 2 (GPL2) as published by the Free Software -Foundation and appearing in the file GPL2.TXT included in the packaging of -this file. Please note that GPL2 Section 2[b] requires that all works based -on this software must also be made publicly available under the terms of -the GPL2 ("Copyleft"). - -Contact information -------------------- - -Circuits At Home, LTD -Web : http://www.circuitsathome.com -e-mail : support@circuitsathome.com -*/ -#include "cdcftdi.h" - -const uint8_t FTDI::epDataInIndex = 1; -const uint8_t FTDI::epDataOutIndex = 2; -const uint8_t FTDI::epInterruptInIndex = 3; - -FTDI::FTDI(USB *p, FTDIAsyncOper *pasync) : - pAsync(pasync), - pUsb(p), - bAddress(0), - bNumEP(1), - wFTDIType(0) -{ - for(uint8_t i=0; iRegisterDeviceClass(this); -} - -uint8_t FTDI::Init(uint8_t parent, uint8_t port, bool lowspeed) -{ - const uint8_t constBufSize = sizeof(USB_DEVICE_DESCRIPTOR); - - uint8_t buf[constBufSize]; - uint8_t rcode; - UsbDevice *p = NULL; - EpInfo *oldep_ptr = NULL; - uint8_t len = 0; - uint16_t cd_len = 0; - - uint8_t num_of_conf; // number of configurations - uint8_t num_of_intf; // number of interfaces - - AddressPool &addrPool = pUsb->GetAddressPool(); - - USBTRACE("FTDI Init\r\n"); - - if (bAddress) - return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE; - - // Get pointer to pseudo device with address 0 assigned - p = addrPool.GetUsbDevicePtr(0); - - if (!p) - return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; - - if (!p->epinfo) - { - USBTRACE("epinfo\r\n"); - return USB_ERROR_EPINFO_IS_NULL; - } - - // Save old pointer to EP_RECORD of address 0 - oldep_ptr = p->epinfo; - - // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence - p->epinfo = epInfo; - - p->lowspeed = lowspeed; - - // Get device descriptor - rcode = pUsb->getDevDescr( 0, 0, sizeof(USB_DEVICE_DESCRIPTOR), (uint8_t*)buf ); - - // Restore p->epinfo - p->epinfo = oldep_ptr; - - if( rcode ) - goto FailGetDevDescr; - - if (((USB_DEVICE_DESCRIPTOR*)buf)->idVendor != FTDI_VID || ((USB_DEVICE_DESCRIPTOR*)buf)->idProduct != FTDI_PID) - return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; - - // Save type of FTDI chip - wFTDIType = ((USB_DEVICE_DESCRIPTOR*)buf)->bcdDevice; - - // Allocate new address according to device class - bAddress = addrPool.AllocAddress(parent, false, port); - - if (!bAddress) - return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; - - // Extract Max Packet Size from the device descriptor - epInfo[0].maxPktSize = (uint8_t)((USB_DEVICE_DESCRIPTOR*)buf)->bMaxPacketSize0; - - // Assign new address to the device - rcode = pUsb->setAddr( 0, 0, bAddress ); - - if (rcode) - { - p->lowspeed = false; - addrPool.FreeAddress(bAddress); - bAddress = 0; - USBTRACE2("setAddr:",rcode); - return rcode; - } - - USBTRACE2("Addr:", bAddress); - - p->lowspeed = false; - - p = addrPool.GetUsbDevicePtr(bAddress); - - if (!p) - return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; - - p->lowspeed = lowspeed; - - num_of_conf = ((USB_DEVICE_DESCRIPTOR*)buf)->bNumConfigurations; - - // Assign epInfo to epinfo pointer - rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); - - if (rcode) - goto FailSetDevTblEntry; - - USBTRACE2("NC:", num_of_conf); - - for (uint8_t i=0; i HexDump; - ConfigDescParser<0xFF, 0xFF, 0xFF, CP_MASK_COMPARE_ALL> confDescrParser(this); - - rcode = pUsb->getConfDescr(bAddress, 0, i, &HexDump); - rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser); - - if (bNumEP > 1) - break; - } // for - - if (bNumEP < 2) - return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; - - USBTRACE2("NumEP:", bNumEP); - - // Assign epInfo to epinfo pointer - rcode = pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo); - - USBTRACE2("Conf:", bConfNum); - - // Set Configuration Value - rcode = pUsb->setConf(bAddress, 0, bConfNum); - - if (rcode) - goto FailSetConfDescr; - - rcode = pAsync->OnInit(this); - - if (rcode) - goto FailOnInit; - - USBTRACE("FTDI configured\r\n"); - - bPollEnable = true; - return 0; - -FailGetDevDescr: - USBTRACE("getDevDescr:"); - goto Fail; - -FailSetDevTblEntry: - USBTRACE("setDevTblEn:"); - goto Fail; - -FailGetConfDescr: - USBTRACE("getConf:"); - goto Fail; - -FailSetConfDescr: - USBTRACE("setConf:"); - goto Fail; - -FailSetBaudRate: - USBTRACE("SetBaudRate:"); - goto Fail; - -FailSetFlowControl: - USBTRACE("SetFlowControl:"); - goto Fail; - -FailOnInit: - USBTRACE("OnInit:"); - goto Fail; - -Fail: - Serial.println(rcode, HEX); - Release(); - return rcode; -} - - -void FTDI::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *pep) -{ - ErrorMessage(PSTR("Conf.Val"), conf); - ErrorMessage(PSTR("Iface Num"),iface); - ErrorMessage(PSTR("Alt.Set"), alt); - - bConfNum = conf; - - uint8_t index; - - if ((pep->bmAttributes & 0x03) == 3 && (pep->bEndpointAddress & 0x80) == 0x80) - index = epInterruptInIndex; - else - if ((pep->bmAttributes & 0x02) == 2) - index = ((pep->bEndpointAddress & 0x80) == 0x80) ? epDataInIndex : epDataOutIndex; - else - return; - - // Fill in the endpoint info structure - epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F); - epInfo[index].maxPktSize = (uint8_t)pep->wMaxPacketSize; - //epInfo[index].epAttribs = 0; - - bNumEP ++; - - PrintEndpointDescriptor(pep); -} - -uint8_t FTDI::Release() -{ - pUsb->GetAddressPool().FreeAddress(bAddress); - - bAddress = 0; - bNumEP = 1; - qNextPollTime = 0; - bPollEnable = false; - return 0; -} - -uint8_t FTDI::Poll() -{ - uint8_t rcode = 0; - - //if (!bPollEnable) - // return 0; - - //if (qNextPollTime <= millis()) - //{ - // Serial.println(bAddress, HEX); - - // qNextPollTime = millis() + 100; - //} - return rcode; -} - -uint8_t FTDI::SetBaudRate(uint32_t baud) -{ - uint16_t baud_value, baud_index = 0; - uint32_t divisor3; - - divisor3 = 48000000 / 2 / baud; // divisor shifted 3 bits to the left - - if (wFTDIType == FT232AM) - { - if ((divisor3 & 0x7) == 7) - divisor3 ++; // round x.7/8 up to x+1 - - baud_value = divisor3 >> 3; - divisor3 &= 0x7; - - if (divisor3 == 1) baud_value |= 0xc000; else // 0.125 - if (divisor3 >= 4) baud_value |= 0x4000; else // 0.5 - if (divisor3 != 0) baud_value |= 0x8000; // 0.25 - if (baud_value == 1) baud_value = 0; /* special case for maximum baud rate */ - } - else - { - 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 }; - - baud_value = divisor3 >> 3; - baud_value |= divfrac [divisor3 & 0x7] << 14; - baud_index = divindex[divisor3 & 0x7]; - - /* Deal with special cases for highest baud rates. */ - if (baud_value == 1) baud_value = 0; else // 1.0 - if (baud_value == 0x4001) baud_value = 1; // 1.5 - } - USBTRACE2("baud_value:", baud_value); - USBTRACE2("baud_index:", baud_index); - 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) -{ - 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) -{ - 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) -{ - 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) -{ - return pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, bytes_rcvd, dataptr); -} - -uint8_t FTDI::SndData(uint16_t nbytes, uint8_t *dataptr) -{ - return pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, nbytes, dataptr); -} - -void FTDI::PrintEndpointDescriptor( const USB_ENDPOINT_DESCRIPTOR* ep_ptr ) -{ - Notify(PSTR("Endpoint descriptor:")); - Notify(PSTR("\r\nLength:\t\t")); - PrintHex(ep_ptr->bLength); - Notify(PSTR("\r\nType:\t\t")); - PrintHex(ep_ptr->bDescriptorType); - Notify(PSTR("\r\nAddress:\t")); - PrintHex(ep_ptr->bEndpointAddress); - Notify(PSTR("\r\nAttributes:\t")); - PrintHex(ep_ptr->bmAttributes); - Notify(PSTR("\r\nMaxPktSize:\t")); - PrintHex(ep_ptr->wMaxPacketSize); - Notify(PSTR("\r\nPoll Intrv:\t")); - PrintHex(ep_ptr->bInterval); - Notify(PSTR("\r\n")); -} +/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. + +This software may be distributed and modified under the terms of the GNU +General Public License version 2 (GPL2) as published by the Free Software +Foundation and appearing in the file GPL2.TXT included in the packaging of +this file. Please note that GPL2 Section 2[b] requires that all works based +on this software must also be made publicly available under the terms of +the GPL2 ("Copyleft"). + +Contact information +------------------- + +Circuits At Home, LTD +Web : http://www.circuitsathome.com +e-mail : support@circuitsathome.com + */ +#include "cdcftdi.h" + +const uint8_t FTDI::epDataInIndex = 1; +const uint8_t FTDI::epDataOutIndex = 2; +const uint8_t FTDI::epInterruptInIndex = 3; + +FTDI::FTDI(USB *p, FTDIAsyncOper *pasync) : +pAsync(pasync), +pUsb(p), +bAddress(0), +bNumEP(1), +wFTDIType(0) { + for (uint8_t i = 0; i < FTDI_MAX_ENDPOINTS; i++) { + epInfo[i].epAddr = 0; + epInfo[i].maxPktSize = (i) ? 0 : 8; + epInfo[i].epAttribs = 0; + + //if (!i) + epInfo[i].bmNakPower = USB_NAK_MAX_POWER; + } + if (pUsb) + pUsb->RegisterDeviceClass(this); +} + +uint8_t FTDI::Init(uint8_t parent, uint8_t port, bool lowspeed) { + const uint8_t constBufSize = sizeof (USB_DEVICE_DESCRIPTOR); + + uint8_t buf[constBufSize]; + uint8_t rcode; + UsbDevice *p = NULL; + EpInfo *oldep_ptr = NULL; + //uint8_t len = 0; + //uint16_t cd_len = 0; + + uint8_t num_of_conf; // number of configurations + //uint8_t num_of_intf; // number of interfaces + + AddressPool &addrPool = pUsb->GetAddressPool(); + + USBTRACE("FTDI Init\r\n"); + + if (bAddress) + return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE; + + // Get pointer to pseudo device with address 0 assigned + p = addrPool.GetUsbDevicePtr(0); + + if (!p) + return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; + + if (!p->epinfo) { + USBTRACE("epinfo\r\n"); + return USB_ERROR_EPINFO_IS_NULL; + } + + // Save old pointer to EP_RECORD of address 0 + oldep_ptr = p->epinfo; + + // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence + p->epinfo = epInfo; + + p->lowspeed = lowspeed; + + // Get device descriptor + rcode = pUsb->getDevDescr(0, 0, sizeof (USB_DEVICE_DESCRIPTOR), (uint8_t*) buf); + + // Restore p->epinfo + p->epinfo = oldep_ptr; + + if (rcode) + goto FailGetDevDescr; + + if (((USB_DEVICE_DESCRIPTOR*) buf)->idVendor != FTDI_VID || ((USB_DEVICE_DESCRIPTOR*) buf)->idProduct != FTDI_PID) + return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; + + // Save type of FTDI chip + wFTDIType = ((USB_DEVICE_DESCRIPTOR*) buf)->bcdDevice; + + // Allocate new address according to device class + bAddress = addrPool.AllocAddress(parent, false, port); + + if (!bAddress) + return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; + + // Extract Max Packet Size from the device descriptor + epInfo[0].maxPktSize = (uint8_t) ((USB_DEVICE_DESCRIPTOR*) buf)->bMaxPacketSize0; + + // Assign new address to the device + rcode = pUsb->setAddr(0, 0, bAddress); + + if (rcode) { + p->lowspeed = false; + addrPool.FreeAddress(bAddress); + bAddress = 0; + USBTRACE2("setAddr:", rcode); + return rcode; + } + + USBTRACE2("Addr:", bAddress); + + p->lowspeed = false; + + p = addrPool.GetUsbDevicePtr(bAddress); + + if (!p) + return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; + + p->lowspeed = lowspeed; + + num_of_conf = ((USB_DEVICE_DESCRIPTOR*) buf)->bNumConfigurations; + + // Assign epInfo to epinfo pointer + rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); + + if (rcode) + goto FailSetDevTblEntry; + + USBTRACE2("NC:", num_of_conf); + + for (uint8_t i = 0; i < num_of_conf; i++) { + HexDumper HexDump; + ConfigDescParser < 0xFF, 0xFF, 0xFF, CP_MASK_COMPARE_ALL> confDescrParser(this); + + rcode = pUsb->getConfDescr(bAddress, 0, i, &HexDump); + + if (rcode) + goto FailGetConfDescr; + + rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser); + + if (rcode) + goto FailGetConfDescr; + + if (bNumEP > 1) + break; + } // for + + if (bNumEP < 2) + return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; + + USBTRACE2("NumEP:", bNumEP); + + // Assign epInfo to epinfo pointer + rcode = pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo); + + USBTRACE2("Conf:", bConfNum); + + // Set Configuration Value + rcode = pUsb->setConf(bAddress, 0, bConfNum); + + if (rcode) + goto FailSetConfDescr; + + rcode = pAsync->OnInit(this); + + if (rcode) + goto FailOnInit; + + USBTRACE("FTDI configured\r\n"); + + bPollEnable = true; + return 0; + +FailGetDevDescr: + USBTRACE("getDevDescr:"); + goto Fail; + +FailSetDevTblEntry: + USBTRACE("setDevTblEn:"); + goto Fail; + +FailGetConfDescr: + USBTRACE("getConf:"); + goto Fail; + +FailSetConfDescr: + USBTRACE("setConf:"); + goto Fail; + +FailOnInit: + USBTRACE("OnInit:"); + goto Fail; + +Fail: + PrintHex (rcode, 0x80); + Notify(PSTR("\r\n"), 0x80); + //Serial.println(rcode, HEX); + Release(); + return rcode; +} + +void FTDI::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *pep) { + ErrorMessage (PSTR("Conf.Val"), conf); + ErrorMessage (PSTR("Iface Num"), iface); + ErrorMessage (PSTR("Alt.Set"), alt); + + bConfNum = conf; + + uint8_t index; + + if ((pep->bmAttributes & 0x03) == 3 && (pep->bEndpointAddress & 0x80) == 0x80) + index = epInterruptInIndex; + else + if ((pep->bmAttributes & 0x02) == 2) + index = ((pep->bEndpointAddress & 0x80) == 0x80) ? epDataInIndex : epDataOutIndex; + else + return; + + // Fill in the endpoint info structure + epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F); + epInfo[index].maxPktSize = (uint8_t) pep->wMaxPacketSize; + epInfo[index].epAttribs = 0; + + bNumEP++; + + PrintEndpointDescriptor(pep); +} + +uint8_t FTDI::Release() { + pUsb->GetAddressPool().FreeAddress(bAddress); + + bAddress = 0; + bNumEP = 1; + qNextPollTime = 0; + bPollEnable = false; + return 0; +} + +uint8_t FTDI::Poll() { + uint8_t rcode = 0; + + //if (!bPollEnable) + // return 0; + + //if (qNextPollTime <= millis()) + //{ + // Serial.println(bAddress, HEX); + + // qNextPollTime = millis() + 100; + //} + return rcode; +} + +uint8_t FTDI::SetBaudRate(uint32_t baud) { + uint16_t baud_value, baud_index = 0; + uint32_t divisor3; + + divisor3 = 48000000 / 2 / baud; // divisor shifted 3 bits to the left + + if (wFTDIType == FT232AM) { + if ((divisor3 & 0x7) == 7) + divisor3++; // round x.7/8 up to x+1 + + baud_value = divisor3 >> 3; + divisor3 &= 0x7; + + if (divisor3 == 1) baud_value |= 0xc000; + else // 0.125 + if (divisor3 >= 4) baud_value |= 0x4000; + else // 0.5 + if (divisor3 != 0) baud_value |= 0x8000; // 0.25 + if (baud_value == 1) baud_value = 0; /* special case for maximum baud rate */ + } else { + 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}; + + baud_value = divisor3 >> 3; + baud_value |= divfrac [divisor3 & 0x7] << 14; + baud_index = divindex[divisor3 & 0x7]; + + /* Deal with special cases for highest baud rates. */ + if (baud_value == 1) baud_value = 0; + else // 1.0 + if (baud_value == 0x4001) baud_value = 1; // 1.5 + } + USBTRACE2("baud_value:", baud_value); + USBTRACE2("baud_index:", baud_index); + 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) { + 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) { + 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) { + 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) { + return pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, bytes_rcvd, dataptr); +} + +uint8_t FTDI::SndData(uint16_t nbytes, uint8_t *dataptr) { + return pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, nbytes, dataptr); +} + +void FTDI::PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr) { + Notify(PSTR("Endpoint descriptor:"), 0x80); + Notify(PSTR("\r\nLength:\t\t"), 0x80); + PrintHex (ep_ptr->bLength, 0x80); + Notify(PSTR("\r\nType:\t\t"), 0x80); + PrintHex (ep_ptr->bDescriptorType, 0x80); + Notify(PSTR("\r\nAddress:\t"), 0x80); + PrintHex (ep_ptr->bEndpointAddress, 0x80); + Notify(PSTR("\r\nAttributes:\t"), 0x80); + PrintHex (ep_ptr->bmAttributes, 0x80); + Notify(PSTR("\r\nMaxPktSize:\t"), 0x80); + PrintHex (ep_ptr->wMaxPacketSize, 0x80); + Notify(PSTR("\r\nPoll Intrv:\t"), 0x80); + PrintHex (ep_ptr->bInterval, 0x80); + Notify(PSTR("\r\n"), 0x80); +} diff --git a/cdcftdi.h b/cdcftdi.h index 41d0650c..1bd26430 100644 --- a/cdcftdi.h +++ b/cdcftdi.h @@ -1,150 +1,151 @@ -/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. - -This software may be distributed and modified under the terms of the GNU -General Public License version 2 (GPL2) as published by the Free Software -Foundation and appearing in the file GPL2.TXT included in the packaging of -this file. Please note that GPL2 Section 2[b] requires that all works based -on this software must also be made publicly available under the terms of -the GPL2 ("Copyleft"). - -Contact information -------------------- - -Circuits At Home, LTD -Web : http://www.circuitsathome.com -e-mail : support@circuitsathome.com -*/ -#if !defined(__CDCFTDI_H__) -#define __CDCFTDI_H__ - -#include -#include -#include "avrpins.h" -#include "max3421e.h" -#include "usbhost.h" -#include "usb_ch9.h" -#include "Usb.h" - -#if defined(ARDUINO) && ARDUINO >=100 -#include "Arduino.h" -#else -#include -#endif - -#include "printhex.h" -#include "hexdump.h" -#include "message.h" - -#include "confdescparser.h" - -#define bmREQ_FTDI_OUT 0x40 -#define bmREQ_FTDI_IN 0xc0 - -//#define bmREQ_FTDI_OUT USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE -//#define bmREQ_FTDI_IN USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE - -#define FTDI_VID 0x0403 // FTDI VID -#define FTDI_PID 0x6001 // FTDI PID - -#define FT232AM 0x0200 -#define FT232BM 0x0400 -#define FT2232 0x0500 -#define FT232R 0x0600 - -// Commands -#define FTDI_SIO_RESET 0 /* Reset the port */ -#define FTDI_SIO_MODEM_CTRL 1 /* Set the modem control register */ -#define FTDI_SIO_SET_FLOW_CTRL 2 /* Set flow control register */ -#define FTDI_SIO_SET_BAUD_RATE 3 /* Set baud rate */ -#define FTDI_SIO_SET_DATA 4 /* Set the data characteristics of the port */ -#define FTDI_SIO_GET_MODEM_STATUS 5 /* Retrieve current value of modem status register */ -#define FTDI_SIO_SET_EVENT_CHAR 6 /* Set the event character */ -#define FTDI_SIO_SET_ERROR_CHAR 7 /* Set the error character */ - -#define FTDI_SIO_RESET_SIO 0 -#define FTDI_SIO_RESET_PURGE_RX 1 -#define FTDI_SIO_RESET_PURGE_TX 2 - -#define FTDI_SIO_SET_DATA_PARITY_NONE (0x0 << 8 ) -#define FTDI_SIO_SET_DATA_PARITY_ODD (0x1 << 8 ) -#define FTDI_SIO_SET_DATA_PARITY_EVEN (0x2 << 8 ) -#define FTDI_SIO_SET_DATA_PARITY_MARK (0x3 << 8 ) -#define FTDI_SIO_SET_DATA_PARITY_SPACE (0x4 << 8 ) -#define FTDI_SIO_SET_DATA_STOP_BITS_1 (0x0 << 11) -#define FTDI_SIO_SET_DATA_STOP_BITS_15 (0x1 << 11) -#define FTDI_SIO_SET_DATA_STOP_BITS_2 (0x2 << 11) -#define FTDI_SIO_SET_BREAK (0x1 << 14) - -#define FTDI_SIO_SET_DTR_MASK 0x1 -#define FTDI_SIO_SET_DTR_HIGH ( 1 | ( FTDI_SIO_SET_DTR_MASK << 8)) -#define FTDI_SIO_SET_DTR_LOW ( 0 | ( FTDI_SIO_SET_DTR_MASK << 8)) -#define FTDI_SIO_SET_RTS_MASK 0x2 -#define FTDI_SIO_SET_RTS_HIGH ( 2 | ( FTDI_SIO_SET_RTS_MASK << 8 )) -#define FTDI_SIO_SET_RTS_LOW ( 0 | ( FTDI_SIO_SET_RTS_MASK << 8 )) - -#define FTDI_SIO_DISABLE_FLOW_CTRL 0x0 -#define FTDI_SIO_RTS_CTS_HS (0x1 << 8) -#define FTDI_SIO_DTR_DSR_HS (0x2 << 8) -#define FTDI_SIO_XON_XOFF_HS (0x4 << 8) - -#define FTDI_SIO_CTS_MASK 0x10 -#define FTDI_SIO_DSR_MASK 0x20 -#define FTDI_SIO_RI_MASK 0x40 -#define FTDI_SIO_RLSD_MASK 0x80 - -class FTDI; - -class FTDIAsyncOper -{ -public: - virtual uint8_t OnInit(FTDI *pftdi) = 0; -}; - - -// Only single port chips are currently supported by the library, -// so only three endpoints are allocated. -#define FTDI_MAX_ENDPOINTS 3 - -class FTDI : public USBDeviceConfig, public UsbConfigXtracter -{ - static const uint8_t epDataInIndex; // DataIn endpoint index - static const uint8_t epDataOutIndex; // DataOUT endpoint index - static const uint8_t epInterruptInIndex; // InterruptIN endpoint index - - FTDIAsyncOper *pAsync; - USB *pUsb; - uint8_t bAddress; - uint8_t bConfNum; // configuration number - uint8_t bNumIface; // number of interfaces in the configuration - uint8_t bNumEP; // total number of EP in the configuration - uint32_t qNextPollTime; // next poll time - bool bPollEnable; // poll enable flag - uint16_t wFTDIType; // Type of FTDI chip - - EpInfo epInfo[FTDI_MAX_ENDPOINTS]; - - void PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr); - -public: - FTDI(USB *pusb, FTDIAsyncOper *pasync); - - uint8_t SetBaudRate(uint32_t baud); - uint8_t SetModemControl(uint16_t control); - uint8_t SetFlowControl(uint8_t protocol, uint8_t xon = 0x11, uint8_t xoff = 0x13); - uint8_t SetData(uint16_t databm); - - // Methods for recieving and sending data - uint8_t RcvData(uint16_t *bytes_rcvd, uint8_t *dataptr); - uint8_t SndData(uint16_t nbytes, uint8_t *dataptr); - - // USBDeviceConfig implementation - virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed); - virtual uint8_t Release(); - virtual uint8_t Poll(); - virtual uint8_t GetAddress() { return bAddress; }; - - // UsbConfigXtracter implementation - virtual void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep); -}; - +/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. + +This software may be distributed and modified under the terms of the GNU +General Public License version 2 (GPL2) as published by the Free Software +Foundation and appearing in the file GPL2.TXT included in the packaging of +this file. Please note that GPL2 Section 2[b] requires that all works based +on this software must also be made publicly available under the terms of +the GPL2 ("Copyleft"). + +Contact information +------------------- + +Circuits At Home, LTD +Web : http://www.circuitsathome.com +e-mail : support@circuitsathome.com + */ +#if !defined(__CDCFTDI_H__) +#define __CDCFTDI_H__ + +#include +#include +#include "avrpins.h" +#include "max3421e.h" +#include "usbhost.h" +#include "usb_ch9.h" +#include "Usb.h" + +#if defined(ARDUINO) && ARDUINO >=100 +#include "Arduino.h" +#else +#include +#endif + +#include "printhex.h" +#include "hexdump.h" +#include "message.h" + +#include "confdescparser.h" + +#define bmREQ_FTDI_OUT 0x40 +#define bmREQ_FTDI_IN 0xc0 + +//#define bmREQ_FTDI_OUT USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE +//#define bmREQ_FTDI_IN USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE + +#define FTDI_VID 0x0403 // FTDI VID +#define FTDI_PID 0x6001 // FTDI PID + +#define FT232AM 0x0200 +#define FT232BM 0x0400 +#define FT2232 0x0500 +#define FT232R 0x0600 + +// Commands +#define FTDI_SIO_RESET 0 /* Reset the port */ +#define FTDI_SIO_MODEM_CTRL 1 /* Set the modem control register */ +#define FTDI_SIO_SET_FLOW_CTRL 2 /* Set flow control register */ +#define FTDI_SIO_SET_BAUD_RATE 3 /* Set baud rate */ +#define FTDI_SIO_SET_DATA 4 /* Set the data characteristics of the port */ +#define FTDI_SIO_GET_MODEM_STATUS 5 /* Retrieve current value of modem status register */ +#define FTDI_SIO_SET_EVENT_CHAR 6 /* Set the event character */ +#define FTDI_SIO_SET_ERROR_CHAR 7 /* Set the error character */ + +#define FTDI_SIO_RESET_SIO 0 +#define FTDI_SIO_RESET_PURGE_RX 1 +#define FTDI_SIO_RESET_PURGE_TX 2 + +#define FTDI_SIO_SET_DATA_PARITY_NONE (0x0 << 8 ) +#define FTDI_SIO_SET_DATA_PARITY_ODD (0x1 << 8 ) +#define FTDI_SIO_SET_DATA_PARITY_EVEN (0x2 << 8 ) +#define FTDI_SIO_SET_DATA_PARITY_MARK (0x3 << 8 ) +#define FTDI_SIO_SET_DATA_PARITY_SPACE (0x4 << 8 ) +#define FTDI_SIO_SET_DATA_STOP_BITS_1 (0x0 << 11) +#define FTDI_SIO_SET_DATA_STOP_BITS_15 (0x1 << 11) +#define FTDI_SIO_SET_DATA_STOP_BITS_2 (0x2 << 11) +#define FTDI_SIO_SET_BREAK (0x1 << 14) + +#define FTDI_SIO_SET_DTR_MASK 0x1 +#define FTDI_SIO_SET_DTR_HIGH ( 1 | ( FTDI_SIO_SET_DTR_MASK << 8)) +#define FTDI_SIO_SET_DTR_LOW ( 0 | ( FTDI_SIO_SET_DTR_MASK << 8)) +#define FTDI_SIO_SET_RTS_MASK 0x2 +#define FTDI_SIO_SET_RTS_HIGH ( 2 | ( FTDI_SIO_SET_RTS_MASK << 8 )) +#define FTDI_SIO_SET_RTS_LOW ( 0 | ( FTDI_SIO_SET_RTS_MASK << 8 )) + +#define FTDI_SIO_DISABLE_FLOW_CTRL 0x0 +#define FTDI_SIO_RTS_CTS_HS (0x1 << 8) +#define FTDI_SIO_DTR_DSR_HS (0x2 << 8) +#define FTDI_SIO_XON_XOFF_HS (0x4 << 8) + +#define FTDI_SIO_CTS_MASK 0x10 +#define FTDI_SIO_DSR_MASK 0x20 +#define FTDI_SIO_RI_MASK 0x40 +#define FTDI_SIO_RLSD_MASK 0x80 + +class FTDI; + +class FTDIAsyncOper { +public: + virtual uint8_t OnInit(FTDI *pftdi) = 0; +}; + + +// Only single port chips are currently supported by the library, +// so only three endpoints are allocated. +#define FTDI_MAX_ENDPOINTS 3 + +class FTDI : public USBDeviceConfig, public UsbConfigXtracter { + static const uint8_t epDataInIndex; // DataIn endpoint index + static const uint8_t epDataOutIndex; // DataOUT endpoint index + static const uint8_t epInterruptInIndex; // InterruptIN endpoint index + + FTDIAsyncOper *pAsync; + USB *pUsb; + uint8_t bAddress; + uint8_t bConfNum; // configuration number + uint8_t bNumIface; // number of interfaces in the configuration + uint8_t bNumEP; // total number of EP in the configuration + uint32_t qNextPollTime; // next poll time + bool bPollEnable; // poll enable flag + uint16_t wFTDIType; // Type of FTDI chip + + EpInfo epInfo[FTDI_MAX_ENDPOINTS]; + + void PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr); + +public: + FTDI(USB *pusb, FTDIAsyncOper *pasync); + + uint8_t SetBaudRate(uint32_t baud); + uint8_t SetModemControl(uint16_t control); + uint8_t SetFlowControl(uint8_t protocol, uint8_t xon = 0x11, uint8_t xoff = 0x13); + uint8_t SetData(uint16_t databm); + + // Methods for recieving and sending data + uint8_t RcvData(uint16_t *bytes_rcvd, uint8_t *dataptr); + uint8_t SndData(uint16_t nbytes, uint8_t *dataptr); + + // USBDeviceConfig implementation + virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed); + virtual uint8_t Release(); + virtual uint8_t Poll(); + + virtual uint8_t GetAddress() { + return bAddress; + }; + + // UsbConfigXtracter implementation + virtual void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep); +}; + #endif // __CDCFTDI_H__ \ No newline at end of file diff --git a/cdcprolific.cpp b/cdcprolific.cpp index ec27defe..f0317730 100644 --- a/cdcprolific.cpp +++ b/cdcprolific.cpp @@ -1,243 +1,201 @@ -/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. - -This software may be distributed and modified under the terms of the GNU -General Public License version 2 (GPL2) as published by the Free Software -Foundation and appearing in the file GPL2.TXT included in the packaging of -this file. Please note that GPL2 Section 2[b] requires that all works based -on this software must also be made publicly available under the terms of -the GPL2 ("Copyleft"). - -Contact information -------------------- - -Circuits At Home, LTD -Web : http://www.circuitsathome.com -e-mail : support@circuitsathome.com -*/ -#include "cdcprolific.h" - -PL2303::PL2303(USB *p, CDCAsyncOper *pasync) : - ACM(p, pasync) - //wPLType(0) -{ -} - -uint8_t PL2303::Init(uint8_t parent, uint8_t port, bool lowspeed) -{ - const uint8_t constBufSize = sizeof(USB_DEVICE_DESCRIPTOR); - - uint8_t buf[constBufSize]; - uint8_t rcode; - UsbDevice *p = NULL; - EpInfo *oldep_ptr = NULL; - uint8_t num_of_conf; // number of configurations - enum pl2303_type pltype = unknown; - - AddressPool &addrPool = pUsb->GetAddressPool(); - - USBTRACE("PL Init\r\n"); - - if (bAddress) - return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE; - - // Get pointer to pseudo device with address 0 assigned - p = addrPool.GetUsbDevicePtr(0); - - if (!p) - return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; - - if (!p->epinfo) - { - USBTRACE("epinfo\r\n"); - return USB_ERROR_EPINFO_IS_NULL; - } - - // Save old pointer to EP_RECORD of address 0 - oldep_ptr = p->epinfo; - - // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence - p->epinfo = epInfo; - - p->lowspeed = lowspeed; - - // Get device descriptor - rcode = pUsb->getDevDescr( 0, 0, sizeof(USB_DEVICE_DESCRIPTOR), (uint8_t*)buf ); - - // Restore p->epinfo - p->epinfo = oldep_ptr; - - if( rcode ) - goto FailGetDevDescr; - - if (((USB_DEVICE_DESCRIPTOR*)buf)->idVendor != PL_VID && ((USB_DEVICE_DESCRIPTOR*)buf)->idProduct != PL_PID ) { - return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; - } - - /* determine chip variant */ - - 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 - bAddress = addrPool.AllocAddress(parent, false, port); - - if (!bAddress) - return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; - - // Extract Max Packet Size from the device descriptor - epInfo[0].maxPktSize = (uint8_t)((USB_DEVICE_DESCRIPTOR*)buf)->bMaxPacketSize0; - - // Assign new address to the device - rcode = pUsb->setAddr( 0, 0, bAddress ); - - if (rcode) - { - p->lowspeed = false; - addrPool.FreeAddress(bAddress); - bAddress = 0; - USBTRACE2("setAddr:",rcode); - return rcode; - } - - USBTRACE2("Addr:", bAddress); - - p->lowspeed = false; - - p = addrPool.GetUsbDevicePtr(bAddress); - - if (!p) - return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; - - p->lowspeed = lowspeed; - - num_of_conf = ((USB_DEVICE_DESCRIPTOR*)buf)->bNumConfigurations; - - // Assign epInfo to epinfo pointer - rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); - - if (rcode) - goto FailSetDevTblEntry; - - USBTRACE2("NC:", num_of_conf); - - for( uint8_t i=0; i HexDump; - ConfigDescParser<0xFF, 0, 0, CP_MASK_COMPARE_CLASS> confDescrParser(this); - - //rcode = pUsb->getConfDescr(bAddress, 0, i, &HexDump); - rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser); - - if (bNumEP > 1) - break; - } // for - - if ( bNumEP < 2 ) - return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; - - // Assign epInfo to epinfo pointer - rcode = pUsb->setEpInfoEntry( bAddress, bNumEP, epInfo ); - - USBTRACE2("Conf:", bConfNum); - - // Set Configuration Value - rcode = pUsb->setConf(bAddress, 0, bConfNum); - - if (rcode) - 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); - - if (rcode) - goto FailOnInit; - - USBTRACE("PL configured\r\n"); - - //bPollEnable = true; - ready = true; - return 0; - -FailGetDevDescr: - USBTRACE("getDevDescr:"); - goto Fail; - -FailSetDevTblEntry: - USBTRACE("setDevTblEn:"); - goto Fail; - -FailGetConfDescr: - USBTRACE("getConf:"); - goto Fail; - -FailSetConfDescr: - USBTRACE("setConf:"); - goto Fail; - -FailSetControlLineState: - USBTRACE("SetControlLineState:"); - goto Fail; - -FailSetLineCoding: - USBTRACE("SetLineCoding:"); - goto Fail; - -FailOnInit: - USBTRACE("OnInit:"); - goto Fail; - -Fail: - Serial.println(rcode, HEX); - Release(); - return rcode; -} - -//uint8_t PL::Poll() -//{ -// uint8_t rcode = 0; -// -// //if (!bPollEnable) -// // return 0; -// -// //if (qNextPollTime <= millis()) -// //{ -// // Serial.println(bAddress, HEX); -// -// // qNextPollTime = millis() + 100; -// //} -// return rcode; -//} - - +/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. + +This software may be distributed and modified under the terms of the GNU +General Public License version 2 (GPL2) as published by the Free Software +Foundation and appearing in the file GPL2.TXT included in the packaging of +this file. Please note that GPL2 Section 2[b] requires that all works based +on this software must also be made publicly available under the terms of +the GPL2 ("Copyleft"). + +Contact information +------------------- + +Circuits At Home, LTD +Web : http://www.circuitsathome.com +e-mail : support@circuitsathome.com + */ +#include "cdcprolific.h" + +PL2303::PL2303(USB *p, CDCAsyncOper *pasync) : +ACM(p, pasync), +wPLType(0) { +} + +uint8_t PL2303::Init(uint8_t parent, uint8_t port, bool lowspeed) { + const uint8_t constBufSize = sizeof (USB_DEVICE_DESCRIPTOR); + + uint8_t buf[constBufSize]; + uint8_t rcode; + UsbDevice *p = NULL; + EpInfo *oldep_ptr = NULL; + uint8_t num_of_conf; // number of configurations + + AddressPool &addrPool = pUsb->GetAddressPool(); + + USBTRACE("PL Init\r\n"); + + if (bAddress) + return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE; + + // Get pointer to pseudo device with address 0 assigned + p = addrPool.GetUsbDevicePtr(0); + + if (!p) + return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; + + if (!p->epinfo) { + USBTRACE("epinfo\r\n"); + return USB_ERROR_EPINFO_IS_NULL; + } + + // Save old pointer to EP_RECORD of address 0 + oldep_ptr = p->epinfo; + + // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence + p->epinfo = epInfo; + + p->lowspeed = lowspeed; + + // Get device descriptor + rcode = pUsb->getDevDescr(0, 0, sizeof (USB_DEVICE_DESCRIPTOR), (uint8_t*) buf); + + // Restore p->epinfo + p->epinfo = oldep_ptr; + + if (rcode) + goto FailGetDevDescr; + + if (((USB_DEVICE_DESCRIPTOR*) buf)->idVendor != PL_VID && ((USB_DEVICE_DESCRIPTOR*) buf)->idProduct != PL_PID) + return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; + + // Save type of PL chip + wPLType = ((USB_DEVICE_DESCRIPTOR*) buf)->bcdDevice; + + // Allocate new address according to device class + bAddress = addrPool.AllocAddress(parent, false, port); + + if (!bAddress) + return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; + + // Extract Max Packet Size from the device descriptor + epInfo[0].maxPktSize = (uint8_t) ((USB_DEVICE_DESCRIPTOR*) buf)->bMaxPacketSize0; + + // Assign new address to the device + rcode = pUsb->setAddr(0, 0, bAddress); + + if (rcode) { + p->lowspeed = false; + addrPool.FreeAddress(bAddress); + bAddress = 0; + USBTRACE2("setAddr:", rcode); + return rcode; + } + + USBTRACE2("Addr:", bAddress); + + p->lowspeed = false; + + p = addrPool.GetUsbDevicePtr(bAddress); + + if (!p) + return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; + + p->lowspeed = lowspeed; + + num_of_conf = ((USB_DEVICE_DESCRIPTOR*) buf)->bNumConfigurations; + + // Assign epInfo to epinfo pointer + rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); + + if (rcode) + goto FailSetDevTblEntry; + + USBTRACE2("NC:", num_of_conf); + + for (uint8_t i = 0; i < num_of_conf; i++) { + HexDumper HexDump; + ConfigDescParser < 0xFF, 0, 0, CP_MASK_COMPARE_CLASS> confDescrParser(this); + + rcode = pUsb->getConfDescr(bAddress, 0, i, &HexDump); + + if (rcode) + goto FailGetConfDescr; + + rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser); + + if (rcode) + goto FailGetConfDescr; + + if (bNumEP > 1) + break; + } // for + + if (bNumEP < 2) + return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; + + // Assign epInfo to epinfo pointer + rcode = pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo); + + USBTRACE2("Conf:", bConfNum); + + // Set Configuration Value + rcode = pUsb->setConf(bAddress, 0, bConfNum); + + if (rcode) + goto FailSetConfDescr; + + rcode = pAsync->OnInit(this); + + if (rcode) + goto FailOnInit; + + USBTRACE("PL configured\r\n"); + + bPollEnable = true; + return 0; + +FailGetDevDescr: + USBTRACE("getDevDescr:"); + goto Fail; + +FailSetDevTblEntry: + USBTRACE("setDevTblEn:"); + goto Fail; + +FailGetConfDescr: + USBTRACE("getConf:"); + goto Fail; + +FailSetConfDescr: + USBTRACE("setConf:"); + goto Fail; + +FailOnInit: + USBTRACE("OnInit:"); + goto Fail; + +Fail: + PrintHex (rcode, 0x80); + Notify(PSTR("\r\n"), 0x80); + //Serial.println(rcode, HEX); + Release(); + return rcode; +} + +//uint8_t PL::Poll() +//{ +// uint8_t rcode = 0; +// +// //if (!bPollEnable) +// // return 0; +// +// //if (qNextPollTime <= millis()) +// //{ +// // Serial.println(bAddress, HEX); +// +// // qNextPollTime = millis() + 100; +// //} +// return rcode; +//} + + diff --git a/cdcprolific.h b/cdcprolific.h index 38e7d032..9d7a31ce 100644 --- a/cdcprolific.h +++ b/cdcprolific.h @@ -1,179 +1,153 @@ -/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. - -This software may be distributed and modified under the terms of the GNU -General Public License version 2 (GPL2) as published by the Free Software -Foundation and appearing in the file GPL2.TXT included in the packaging of -this file. Please note that GPL2 Section 2[b] requires that all works based -on this software must also be made publicly available under the terms of -the GPL2 ("Copyleft"). - -Contact information -------------------- - -Circuits At Home, LTD -Web : http://www.circuitsathome.com -e-mail : support@circuitsathome.com -*/ -#if !defined(__CDCPROLIFIC_H__) -#define __CDCPROLIFIC_H__ - -#include -#include -#include "avrpins.h" -#include "max3421e.h" -#include "usbhost.h" -#include "usb_ch9.h" -#include "Usb.h" - -#if defined(ARDUINO) && ARDUINO >=100 -#include "Arduino.h" -#else -#include -#endif - -#include "printhex.h" -#include "hexdump.h" -#include "message.h" - -#include "confdescparser.h" -#include "cdcacm.h" - -//#define PL2303_COMPAT //uncomment it if you have compatibility problems - -#define PL_VID 0x067B -#define PL_PID ( 0x2303 || 0x0609 ) - -#define PROLIFIC_REV_H 0x0202 -#define PROLIFIC_REV_X 0x0300 -#define PROLIFIC_REV_HX_CHIP_D 0x0400 -#define PROLIFIC_REV_1 0x0001 - -#define kXOnChar '\x11' -#define kXOffChar '\x13' - -#define SPECIAL_SHIFT (5) -#define SPECIAL_MASK ((1<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 )); -} - +/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. + +This software may be distributed and modified under the terms of the GNU +General Public License version 2 (GPL2) as published by the Free Software +Foundation and appearing in the file GPL2.TXT included in the packaging of +this file. Please note that GPL2 Section 2[b] requires that all works based +on this software must also be made publicly available under the terms of +the GPL2 ("Copyleft"). + +Contact information +------------------- + +Circuits At Home, LTD +Web : http://www.circuitsathome.com +e-mail : support@circuitsathome.com + */ +#if !defined(__CDCPROLIFIC_H__) +#define __CDCPROLIFIC_H__ + +#include +#include +#include "avrpins.h" +#include "max3421e.h" +#include "usbhost.h" +#include "usb_ch9.h" +#include "Usb.h" + +#if defined(ARDUINO) && ARDUINO >=100 +#include "Arduino.h" +#else +#include +#endif + +#include "printhex.h" +#include "hexdump.h" +#include "message.h" + +#include "confdescparser.h" +#include "cdcacm.h" + +#define PL_VID 0x067B +#define PL_PID ( 0x2303 || 0x0609 ) + +//#define PL_PID 0x0609 + +#define PROLIFIC_REV_H 0x0202 +#define PROLIFIC_REV_X 0x0300 +#define PROLIFIC_REV_HX_CHIP_D 0x0400 +#define PROLIFIC_REV_1 0x0001 + +#define kXOnChar '\x11' +#define kXOffChar '\x13' + +#define SPECIAL_SHIFT (5) +#define SPECIAL_MASK ((1< - -#include -#include "printhex.h" -#include "hexdump.h" -#include "message.h" -#include "parsetools.h" - -//#include "hid.h" - -class UsbConfigXtracter -{ -public: - //virtual void ConfigXtract(const USB_CONFIGURATION_DESCRIPTOR *conf) = 0; - //virtual void InterfaceXtract(uint8_t conf, const USB_INTERFACE_DESCRIPTOR *iface) = 0; - virtual void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep) = 0; -}; - -#define CP_MASK_COMPARE_CLASS 1 -#define CP_MASK_COMPARE_SUBCLASS 2 -#define CP_MASK_COMPARE_PROTOCOL 4 -#define CP_MASK_COMPARE_ALL 7 - -// Configuration Descriptor Parser Class Template -template -class ConfigDescParser : public USBReadParser -{ - UsbConfigXtracter *theXtractor; - MultiValueBuffer theBuffer; - MultiByteValueParser valParser; - ByteSkipper theSkipper; - uint8_t varBuffer[16 /*sizeof(USB_CONFIGURATION_DESCRIPTOR)*/]; - - uint8_t stateParseDescr; // ParseDescriptor state - - uint8_t dscrLen; // Descriptor length - uint8_t dscrType; // Descriptor type - - bool isGoodInterface; // Apropriate interface flag - uint8_t confValue; // Configuration value - uint8_t protoValue; // Protocol value - uint8_t ifaceNumber; // Interface number - uint8_t ifaceAltSet; // Interface alternate settings - - bool ParseDescriptor(uint8_t **pp, uint16_t *pcntdn); - - void PrintHidDescriptor(const USB_HID_DESCRIPTOR *pDesc); - -public: - ConfigDescParser(UsbConfigXtracter *xtractor); - virtual void Parse(const uint16_t len, const uint8_t *pbuf, const uint16_t &offset); -}; - -template -ConfigDescParser::ConfigDescParser(UsbConfigXtracter *xtractor) : - stateParseDescr(0), - dscrLen(0), - dscrType(0), - theXtractor(xtractor) -{ - theBuffer.pValue = varBuffer; - valParser.Initialize(&theBuffer); - theSkipper.Initialize(&theBuffer); -}; - -template -void ConfigDescParser::Parse(const uint16_t len, const uint8_t *pbuf, const uint16_t &offset) -{ - uint16_t cntdn = (uint16_t)len; - uint8_t *p = (uint8_t*)pbuf; - - while(cntdn) - if (!ParseDescriptor(&p, &cntdn)) - return; -} -/* 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 */ -template -bool ConfigDescParser::ParseDescriptor(uint8_t **pp, uint16_t *pcntdn) -{ - switch (stateParseDescr) - { - case 0: - theBuffer.valueSize = 2; - valParser.Initialize(&theBuffer); - stateParseDescr = 1; - case 1: - if (!valParser.Parse(pp, pcntdn)) - return false; - dscrLen = *((uint8_t*)theBuffer.pValue); - dscrType = *((uint8_t*)theBuffer.pValue + 1); - stateParseDescr = 2; - case 2: - // This is a sort of hack. Assuming that two bytes are already in the buffer - // 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. - // This should be used carefuly. varBuffer should be used directly to handle data - // in the buffer. - theBuffer.pValue = varBuffer + 2; - stateParseDescr = 3; - case 3: - switch (dscrType) - { - case USB_DESCRIPTOR_INTERFACE: - isGoodInterface = false; - case USB_DESCRIPTOR_CONFIGURATION: - theBuffer.valueSize = sizeof(USB_CONFIGURATION_DESCRIPTOR) - 2; - break; - case USB_DESCRIPTOR_ENDPOINT: - theBuffer.valueSize = sizeof(USB_ENDPOINT_DESCRIPTOR) - 2; - break; - case HID_DESCRIPTOR_HID: - theBuffer.valueSize = dscrLen - 2; - break; - } - valParser.Initialize(&theBuffer); - stateParseDescr = 4; - case 4: - switch (dscrType) - { - case USB_DESCRIPTOR_CONFIGURATION: - if (!valParser.Parse(pp, pcntdn)) - return false; - confValue = ((USB_CONFIGURATION_DESCRIPTOR*)varBuffer)->bConfigurationValue; - break; - case USB_DESCRIPTOR_INTERFACE: - if (!valParser.Parse(pp, pcntdn)) - return false; - if ((MASK & CP_MASK_COMPARE_CLASS) && ((USB_INTERFACE_DESCRIPTOR*)varBuffer)->bInterfaceClass != CLASS_ID) - break; - if ((MASK & CP_MASK_COMPARE_SUBCLASS) && ((USB_INTERFACE_DESCRIPTOR*)varBuffer)->bInterfaceSubClass != SUBCLASS_ID) - break; - if ((MASK & CP_MASK_COMPARE_PROTOCOL) && ((USB_INTERFACE_DESCRIPTOR*)varBuffer)->bInterfaceProtocol != PROTOCOL_ID) - break; - - isGoodInterface = true; - ifaceNumber = ((USB_INTERFACE_DESCRIPTOR*)varBuffer)->bInterfaceNumber; - ifaceAltSet = ((USB_INTERFACE_DESCRIPTOR*)varBuffer)->bAlternateSetting; - protoValue = ((USB_INTERFACE_DESCRIPTOR*)varBuffer)->bInterfaceProtocol; - break; - case USB_DESCRIPTOR_ENDPOINT: - if (!valParser.Parse(pp, pcntdn)) - return false; - if (isGoodInterface) - if (theXtractor) - theXtractor->EndpointXtract(confValue, ifaceNumber, ifaceAltSet, protoValue, (USB_ENDPOINT_DESCRIPTOR*)varBuffer); - break; - //case HID_DESCRIPTOR_HID: - // if (!valParser.Parse(pp, pcntdn)) - // return false; - // PrintHidDescriptor((const USB_HID_DESCRIPTOR*)varBuffer); - // break; - default: - if (!theSkipper.Skip(pp, pcntdn, dscrLen-2)) - return false; - } - theBuffer.pValue = varBuffer; - stateParseDescr = 0; - } - return true; -} - -template -void ConfigDescParser::PrintHidDescriptor(const USB_HID_DESCRIPTOR *pDesc) -{ - Notify(PSTR("\r\n\r\nHID Descriptor:\r\n")); - Notify(PSTR("bDescLength:\t\t")); - PrintHex(pDesc->bLength); - - Notify(PSTR("\r\nbDescriptorType:\t")); - PrintHex(pDesc->bDescriptorType); - - Notify(PSTR("\r\nbcdHID:\t\t\t")); - PrintHex(pDesc->bcdHID); - - Notify(PSTR("\r\nbCountryCode:\t\t")); - PrintHex(pDesc->bCountryCode); - - Notify(PSTR("\r\nbNumDescriptors:\t")); - PrintHex(pDesc->bNumDescriptors); - - //Notify(PSTR("\r\nbDescrType:\t\t")); - //PrintHex(pDesc->bDescrType); - // - //Notify(PSTR("\r\nwDescriptorLength:\t")); - //PrintHex(pDesc->wDescriptorLength); - - for (uint8_t i=0; ibNumDescriptors; i++) - { - HID_CLASS_DESCRIPTOR_LEN_AND_TYPE *pLT = (HID_CLASS_DESCRIPTOR_LEN_AND_TYPE*)&(pDesc->bDescrType); - - Notify(PSTR("\r\nbDescrType:\t\t")); - PrintHex(pLT[i].bDescrType); - - Notify(PSTR("\r\nwDescriptorLength:\t")); - PrintHex(pLT[i].wDescriptorLength); - } - Notify(PSTR("\r\n")); -} - - +/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. + +This software may be distributed and modified under the terms of the GNU +General Public License version 2 (GPL2) as published by the Free Software +Foundation and appearing in the file GPL2.TXT included in the packaging of +this file. Please note that GPL2 Section 2[b] requires that all works based +on this software must also be made publicly available under the terms of +the GPL2 ("Copyleft"). + +Contact information +------------------- + +Circuits At Home, LTD +Web : http://www.circuitsathome.com +e-mail : support@circuitsathome.com + */ +#if !defined(__CONFDESCPARSER_H__) +#define __CONFDESCPARSER_H__ + +#include + +#include +#include "printhex.h" +#include "hexdump.h" +#include "message.h" +#include "parsetools.h" + +//#include "hid.h" + +class UsbConfigXtracter { +public: + //virtual void ConfigXtract(const USB_CONFIGURATION_DESCRIPTOR *conf) = 0; + //virtual void InterfaceXtract(uint8_t conf, const USB_INTERFACE_DESCRIPTOR *iface) = 0; + virtual void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep) = 0; +}; + +#define CP_MASK_COMPARE_CLASS 1 +#define CP_MASK_COMPARE_SUBCLASS 2 +#define CP_MASK_COMPARE_PROTOCOL 4 +#define CP_MASK_COMPARE_ALL 7 + +// Configuration Descriptor Parser Class Template + +template +class ConfigDescParser : public USBReadParser { + UsbConfigXtracter *theXtractor; + MultiValueBuffer theBuffer; + MultiByteValueParser valParser; + ByteSkipper theSkipper; + uint8_t varBuffer[16 /*sizeof(USB_CONFIGURATION_DESCRIPTOR)*/]; + + uint8_t stateParseDescr; // ParseDescriptor state + + uint8_t dscrLen; // Descriptor length + uint8_t dscrType; // Descriptor type + + bool isGoodInterface; // Apropriate interface flag + uint8_t confValue; // Configuration value + uint8_t protoValue; // Protocol value + uint8_t ifaceNumber; // Interface number + uint8_t ifaceAltSet; // Interface alternate settings + + bool ParseDescriptor(uint8_t **pp, uint16_t *pcntdn); + + void PrintHidDescriptor(const USB_HID_DESCRIPTOR *pDesc); + +public: + ConfigDescParser(UsbConfigXtracter *xtractor); + virtual void Parse(const uint16_t len, const uint8_t *pbuf, const uint16_t &offset); +}; + +template +ConfigDescParser::ConfigDescParser(UsbConfigXtracter *xtractor) : +theXtractor(xtractor), +stateParseDescr(0), +dscrLen(0), +dscrType(0) { + theBuffer.pValue = varBuffer; + valParser.Initialize(&theBuffer); + theSkipper.Initialize(&theBuffer); +}; + +template +void ConfigDescParser::Parse(const uint16_t len, const uint8_t *pbuf, const uint16_t &offset) { + uint16_t cntdn = (uint16_t) len; + uint8_t *p = (uint8_t*) pbuf; + + while (cntdn) + if (!ParseDescriptor(&p, &cntdn)) + return; +} + +/* 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 */ +template +bool ConfigDescParser::ParseDescriptor(uint8_t **pp, uint16_t *pcntdn) { + switch (stateParseDescr) { + case 0: + theBuffer.valueSize = 2; + valParser.Initialize(&theBuffer); + stateParseDescr = 1; + case 1: + if (!valParser.Parse(pp, pcntdn)) + return false; + dscrLen = *((uint8_t*) theBuffer.pValue); + dscrType = *((uint8_t*) theBuffer.pValue + 1); + stateParseDescr = 2; + case 2: + // 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 + // to be read right after the size and the type fields. + // This should be used carefuly. varBuffer should be used directly to handle data + // in the buffer. + theBuffer.pValue = varBuffer + 2; + stateParseDescr = 3; + case 3: + switch (dscrType) { + case USB_DESCRIPTOR_INTERFACE: + isGoodInterface = false; + case USB_DESCRIPTOR_CONFIGURATION: + theBuffer.valueSize = sizeof (USB_CONFIGURATION_DESCRIPTOR) - 2; + break; + case USB_DESCRIPTOR_ENDPOINT: + theBuffer.valueSize = sizeof (USB_ENDPOINT_DESCRIPTOR) - 2; + break; + case HID_DESCRIPTOR_HID: + theBuffer.valueSize = dscrLen - 2; + break; + } + valParser.Initialize(&theBuffer); + stateParseDescr = 4; + case 4: + switch (dscrType) { + case USB_DESCRIPTOR_CONFIGURATION: + if (!valParser.Parse(pp, pcntdn)) + return false; + confValue = ((USB_CONFIGURATION_DESCRIPTOR*) varBuffer)->bConfigurationValue; + break; + case USB_DESCRIPTOR_INTERFACE: + if (!valParser.Parse(pp, pcntdn)) + return false; + if ((MASK & CP_MASK_COMPARE_CLASS) && ((USB_INTERFACE_DESCRIPTOR*) varBuffer)->bInterfaceClass != CLASS_ID) + break; + if ((MASK & CP_MASK_COMPARE_SUBCLASS) && ((USB_INTERFACE_DESCRIPTOR*) varBuffer)->bInterfaceSubClass != SUBCLASS_ID) + break; + if ((MASK & CP_MASK_COMPARE_PROTOCOL) && ((USB_INTERFACE_DESCRIPTOR*) varBuffer)->bInterfaceProtocol != PROTOCOL_ID) + break; + + isGoodInterface = true; + ifaceNumber = ((USB_INTERFACE_DESCRIPTOR*) varBuffer)->bInterfaceNumber; + ifaceAltSet = ((USB_INTERFACE_DESCRIPTOR*) varBuffer)->bAlternateSetting; + protoValue = ((USB_INTERFACE_DESCRIPTOR*) varBuffer)->bInterfaceProtocol; + break; + case USB_DESCRIPTOR_ENDPOINT: + if (!valParser.Parse(pp, pcntdn)) + return false; + if (isGoodInterface) + if (theXtractor) + theXtractor->EndpointXtract(confValue, ifaceNumber, ifaceAltSet, protoValue, (USB_ENDPOINT_DESCRIPTOR*) varBuffer); + break; + //case HID_DESCRIPTOR_HID: + // if (!valParser.Parse(pp, pcntdn)) + // return false; + // PrintHidDescriptor((const USB_HID_DESCRIPTOR*)varBuffer); + // break; + default: + if (!theSkipper.Skip(pp, pcntdn, dscrLen - 2)) + return false; + } + theBuffer.pValue = varBuffer; + stateParseDescr = 0; + } + return true; +} + +template +void ConfigDescParser::PrintHidDescriptor(const USB_HID_DESCRIPTOR *pDesc) { + Notify(PSTR("\r\n\r\nHID Descriptor:\r\n"), 0x80); + Notify(PSTR("bDescLength:\t\t"), 0x80); + PrintHex (pDesc->bLength, 0x80); + + Notify(PSTR("\r\nbDescriptorType:\t"), 0x80); + PrintHex (pDesc->bDescriptorType, 0x80); + + Notify(PSTR("\r\nbcdHID:\t\t\t"), 0x80); + PrintHex (pDesc->bcdHID, 0x80); + + Notify(PSTR("\r\nbCountryCode:\t\t"), 0x80); + PrintHex (pDesc->bCountryCode, 0x80); + + Notify(PSTR("\r\nbNumDescriptors:\t"), 0x80); + PrintHex (pDesc->bNumDescriptors, 0x80); + + //Notify(PSTR("\r\nbDescrType:\t\t")); + //PrintHex(pDesc->bDescrType); + // + //Notify(PSTR("\r\nwDescriptorLength:\t")); + //PrintHex(pDesc->wDescriptorLength); + + for (uint8_t i = 0; i < pDesc->bNumDescriptors; i++) { + HID_CLASS_DESCRIPTOR_LEN_AND_TYPE *pLT = (HID_CLASS_DESCRIPTOR_LEN_AND_TYPE*)&(pDesc->bDescrType); + + Notify(PSTR("\r\nbDescrType:\t\t"), 0x80); + PrintHex (pLT[i].bDescrType, 0x80); + + Notify(PSTR("\r\nwDescriptorLength:\t"), 0x80); + PrintHex (pLT[i].wDescriptorLength, 0x80); + } + Notify(PSTR("\r\n"), 0x80); +} + + #endif // __CONFDESCPARSER_H__ \ No newline at end of file diff --git a/gpl2.txt b/gpl2.txt index 5b6e7c66..45645b4b 100644 --- a/gpl2.txt +++ b/gpl2.txt @@ -1,340 +1,340 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Library General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Library General -Public License instead of this License. + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/hexdump.h b/hexdump.h index e63376af..e70317a3 100644 --- a/hexdump.h +++ b/hexdump.h @@ -1,58 +1,59 @@ -/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. - -This software may be distributed and modified under the terms of the GNU -General Public License version 2 (GPL2) as published by the Free Software -Foundation and appearing in the file GPL2.TXT included in the packaging of -this file. Please note that GPL2 Section 2[b] requires that all works based -on this software must also be made publicly available under the terms of -the GPL2 ("Copyleft"). - -Contact information -------------------- - -Circuits At Home, LTD -Web : http://www.circuitsathome.com -e-mail : support@circuitsathome.com -*/ -#if !defined(__HEXDUMP_H__) -#define __HEXDUMP_H__ - -#include -#include -#include "printhex.h" - -template -class HexDumper : public BASE_CLASS -{ - uint8_t byteCount; - OFFSET_TYPE byteTotal; - -public: - 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); -}; - -template -void HexDumper::Parse(const LEN_TYPE len, const uint8_t *pbuf, const OFFSET_TYPE &offset) -{ - for (LEN_TYPE j=0; j(byteTotal); - Serial.print(": "); - } - PrintHex(pbuf[j]); - Serial.print(" "); - - if (byteCount == 15) - { - Serial.println(""); - byteCount = 0xFF; - } - } -} - +/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. + +This software may be distributed and modified under the terms of the GNU +General Public License version 2 (GPL2) as published by the Free Software +Foundation and appearing in the file GPL2.TXT included in the packaging of +this file. Please note that GPL2 Section 2[b] requires that all works based +on this software must also be made publicly available under the terms of +the GPL2 ("Copyleft"). + +Contact information +------------------- + +Circuits At Home, LTD +Web : http://www.circuitsathome.com +e-mail : support@circuitsathome.com + */ +#if !defined(__HEXDUMP_H__) +#define __HEXDUMP_H__ + +#include +#include +#include "printhex.h" + +template +class HexDumper : public BASE_CLASS { + uint8_t byteCount; + OFFSET_TYPE byteTotal; + +public: + + 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); +}; + +template +void HexDumper::Parse(const LEN_TYPE len, const uint8_t *pbuf, const OFFSET_TYPE &offset) { + for (LEN_TYPE j = 0; j < len; j++, byteCount++, byteTotal++) { + if (!byteCount) { + SerialPrintHex (byteTotal); + Serial.print(": "); + } + SerialPrintHex (pbuf[j]); + Serial.print(" "); + + if (byteCount == 15) { + Serial.println(""); + byteCount = 0xFF; + } + } +} + #endif // __HEXDUMP_H__ \ No newline at end of file diff --git a/hid.cpp b/hid.cpp index 4796e782..7d61c8fb 100644 --- a/hid.cpp +++ b/hid.cpp @@ -1,84 +1,82 @@ -#include "hid.h" - -//get HID report descriptor -uint8_t HID::GetReportDescr( uint8_t ep, USBReadParser *parser ) -{ - const uint8_t constBufLen = 64; - uint8_t buf[constBufLen]; - - uint8_t rcode = pUsb->ctrlReq( bAddress, ep, bmREQ_HIDREPORT, USB_REQUEST_GET_DESCRIPTOR, 0x00, - HID_DESCRIPTOR_REPORT, 0x0000, 128, constBufLen, buf, (USBReadParser*)parser ); - - //return ((rcode != hrSTALL) ? rcode : 0); - return rcode; -} -//uint8_t HID::getHidDescr( uint8_t ep, uint16_t nbytes, uint8_t* 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 ) -{ - 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 ) -{ - 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 ) -{ - 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 ) -{ - 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 ) -{ - 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 ) -{ - 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 ) -{ - Notify(PSTR("Endpoint descriptor:")); - Notify(PSTR("\r\nLength:\t\t")); - PrintHex(ep_ptr->bLength); - Notify(PSTR("\r\nType:\t\t")); - PrintHex(ep_ptr->bDescriptorType); - Notify(PSTR("\r\nAddress:\t")); - PrintHex(ep_ptr->bEndpointAddress); - Notify(PSTR("\r\nAttributes:\t")); - PrintHex(ep_ptr->bmAttributes); - Notify(PSTR("\r\nMaxPktSize:\t")); - PrintHex(ep_ptr->wMaxPacketSize); - Notify(PSTR("\r\nPoll Intrv:\t")); - PrintHex(ep_ptr->bInterval); -} - -void HID::PrintHidDescriptor(const USB_HID_DESCRIPTOR *pDesc) -{ - Notify(PSTR("\r\n\r\nHID Descriptor:\r\n")); - Notify(PSTR("bDescLength:\t\t")); - PrintHex(pDesc->bLength); - - Notify(PSTR("\r\nbDescriptorType:\t")); - PrintHex(pDesc->bDescriptorType); - - Notify(PSTR("\r\nbcdHID:\t\t\t")); - PrintHex(pDesc->bcdHID); - - Notify(PSTR("\r\nbCountryCode:\t\t")); - PrintHex(pDesc->bCountryCode); - - Notify(PSTR("\r\nbNumDescriptors:\t")); - PrintHex(pDesc->bNumDescriptors); - - Notify(PSTR("\r\nbDescrType:\t\t")); - PrintHex(pDesc->bDescrType); - - Notify(PSTR("\r\nwDescriptorLength:\t")); - PrintHex(pDesc->wDescriptorLength); -} +#include "hid.h" + +//get HID report descriptor + +uint8_t HID::GetReportDescr(uint8_t ep, USBReadParser *parser) { + const uint8_t constBufLen = 64; + uint8_t buf[constBufLen]; + + uint8_t rcode = pUsb->ctrlReq(bAddress, ep, bmREQ_HIDREPORT, USB_REQUEST_GET_DESCRIPTOR, 0x00, + HID_DESCRIPTOR_REPORT, 0x0000, 128, constBufLen, buf, (USBReadParser*) parser); + + //return ((rcode != hrSTALL) ? rcode : 0); + return rcode; +} +//uint8_t HID::getHidDescr( uint8_t ep, uint16_t nbytes, uint8_t* 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) { + 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) { + 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) { + 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) { + 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) { + 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) { + 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) { + Notify(PSTR("Endpoint descriptor:"), 0x80); + Notify(PSTR("\r\nLength:\t\t"), 0x80); + PrintHex (ep_ptr->bLength, 0x80); + Notify(PSTR("\r\nType:\t\t"), 0x80); + PrintHex (ep_ptr->bDescriptorType, 0x80); + Notify(PSTR("\r\nAddress:\t"), 0x80); + PrintHex (ep_ptr->bEndpointAddress, 0x80); + Notify(PSTR("\r\nAttributes:\t"), 0x80); + PrintHex (ep_ptr->bmAttributes, 0x80); + Notify(PSTR("\r\nMaxPktSize:\t"), 0x80); + PrintHex (ep_ptr->wMaxPacketSize, 0x80); + Notify(PSTR("\r\nPoll Intrv:\t"), 0x80); + PrintHex (ep_ptr->bInterval, 0x80); +} + +void HID::PrintHidDescriptor(const USB_HID_DESCRIPTOR *pDesc) { + Notify(PSTR("\r\n\r\nHID Descriptor:\r\n"), 0x80); + Notify(PSTR("bDescLength:\t\t"), 0x80); + PrintHex (pDesc->bLength, 0x80); + + Notify(PSTR("\r\nbDescriptorType:\t"), 0x80); + PrintHex (pDesc->bDescriptorType, 0x80); + + Notify(PSTR("\r\nbcdHID:\t\t\t"), 0x80); + PrintHex (pDesc->bcdHID, 0x80); + + Notify(PSTR("\r\nbCountryCode:\t\t"), 0x80); + PrintHex (pDesc->bCountryCode, 0x80); + + Notify(PSTR("\r\nbNumDescriptors:\t"), 0x80); + PrintHex (pDesc->bNumDescriptors, 0x80); + + Notify(PSTR("\r\nbDescrType:\t\t"), 0x80); + PrintHex (pDesc->bDescrType, 0x80); + + Notify(PSTR("\r\nwDescriptorLength:\t"), 0x80); + PrintHex (pDesc->wDescriptorLength, 0x80); +} diff --git a/hid.h b/hid.h index 28ed53a6..f894a64d 100644 --- a/hid.h +++ b/hid.h @@ -1,201 +1,201 @@ -/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. - -This software may be distributed and modified under the terms of the GNU -General Public License version 2 (GPL2) as published by the Free Software -Foundation and appearing in the file GPL2.TXT included in the packaging of -this file. Please note that GPL2 Section 2[b] requires that all works based -on this software must also be made publicly available under the terms of -the GPL2 ("Copyleft"). - -Contact information -------------------- - -Circuits At Home, LTD -Web : http://www.circuitsathome.com -e-mail : support@circuitsathome.com -*/ -#if !defined(__HID_H__) -#define __HID_H__ - -#include -#include -#include "avrpins.h" -#include "max3421e.h" -#include "usbhost.h" -#include "usb_ch9.h" -#include "Usb.h" - -#if defined(ARDUINO) && ARDUINO >=100 -#include "Arduino.h" -#else -#include -#endif - -#include "printhex.h" -#include "hexdump.h" -#include "message.h" - -#include "confdescparser.h" -#include "hidusagestr.h" - -#define DATA_SIZE_MASK 0x03 -#define TYPE_MASK 0x0C -#define TAG_MASK 0xF0 - -#define DATA_SIZE_0 0x00 -#define DATA_SIZE_1 0x01 -#define DATA_SIZE_2 0x02 -#define DATA_SIZE_4 0x03 - -#define TYPE_MAIN 0x00 -#define TYPE_GLOBAL 0x04 -#define TYPE_LOCAL 0x08 - -#define TAG_MAIN_INPUT 0x80 -#define TAG_MAIN_OUTPUT 0x90 -#define TAG_MAIN_COLLECTION 0xA0 -#define TAG_MAIN_FEATURE 0xB0 -#define TAG_MAIN_ENDCOLLECTION 0xC0 - -#define TAG_GLOBAL_USAGEPAGE 0x00 -#define TAG_GLOBAL_LOGICALMIN 0x10 -#define TAG_GLOBAL_LOGICALMAX 0x20 -#define TAG_GLOBAL_PHYSMIN 0x30 -#define TAG_GLOBAL_PHYSMAX 0x40 -#define TAG_GLOBAL_UNITEXP 0x50 -#define TAG_GLOBAL_UNIT 0x60 -#define TAG_GLOBAL_REPORTSIZE 0x70 -#define TAG_GLOBAL_REPORTID 0x80 -#define TAG_GLOBAL_REPORTCOUNT 0x90 -#define TAG_GLOBAL_PUSH 0xA0 -#define TAG_GLOBAL_POP 0xB0 - -#define TAG_LOCAL_USAGE 0x00 -#define TAG_LOCAL_USAGEMIN 0x10 -#define TAG_LOCAL_USAGEMAX 0x20 - -/* HID requests */ -#define bmREQ_HIDOUT USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE -#define bmREQ_HIDIN USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE -#define bmREQ_HIDREPORT USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_STANDARD|USB_SETUP_RECIPIENT_INTERFACE - -/* HID constants. Not part of chapter 9 */ -/* Class-Specific Requests */ -#define HID_REQUEST_GET_REPORT 0x01 -#define HID_REQUEST_GET_IDLE 0x02 -#define HID_REQUEST_GET_PROTOCOL 0x03 -#define HID_REQUEST_SET_REPORT 0x09 -#define HID_REQUEST_SET_IDLE 0x0A -#define HID_REQUEST_SET_PROTOCOL 0x0B - -/* Class Descriptor Types */ -#define HID_DESCRIPTOR_HID 0x21 -#define HID_DESCRIPTOR_REPORT 0x22 -#define HID_DESRIPTOR_PHY 0x23 - -/* Protocol Selection */ -#define HID_BOOT_PROTOCOL 0x00 -#define HID_RPT_PROTOCOL 0x01 - -/* HID Interface Class Code */ -#define HID_INTF 0x03 - -/* HID Interface Class SubClass Codes */ -#define HID_BOOT_INTF_SUBCLASS 0x01 - -/* HID Interface Class Protocol Codes */ -#define HID_PROTOCOL_NONE 0x00 -#define HID_PROTOCOL_KEYBOARD 0x01 -#define HID_PROTOCOL_MOUSE 0x02 - -struct HidItemPrefix -{ - uint8_t bSize : 2; - uint8_t bType : 2; - uint8_t bTag : 4; -}; - -#define HID_ITEM_TYPE_MAIN 0 -#define HID_ITEM_TYPE_GLOBAL 1 -#define HID_ITEM_TYPE_LOCAL 2 -#define HID_ITEM_TYPE_RESERVED 3 - -#define HID_LONG_ITEM_PREFIX 0xfe // Long item prefix value - -#define bmHID_MAIN_ITEM_TAG 0xfc // Main item tag mask - -#define bmHID_MAIN_ITEM_INPUT 0x80 // Main item Input tag value -#define bmHID_MAIN_ITEM_OUTPUT 0x90 // Main item Output tag value -#define bmHID_MAIN_ITEM_FEATURE 0xb0 // Main item Feature tag value -#define bmHID_MAIN_ITEM_COLLECTION 0xa0 // Main item Collection tag value -#define bmHID_MAIN_ITEM_END_COLLECTION 0xce // Main item End Collection tag value - -#define HID_MAIN_ITEM_COLLECTION_PHYSICAL 0 -#define HID_MAIN_ITEM_COLLECTION_APPLICATION 1 -#define HID_MAIN_ITEM_COLLECTION_LOGICAL 2 -#define HID_MAIN_ITEM_COLLECTION_REPORT 3 -#define HID_MAIN_ITEM_COLLECTION_NAMED_ARRAY 4 -#define HID_MAIN_ITEM_COLLECTION_USAGE_SWITCH 5 -#define HID_MAIN_ITEM_COLLECTION_USAGE_MODIFIER 6 - -struct MainItemIOFeature -{ - uint8_t bmIsConstantOrData : 1; - uint8_t bmIsArrayOrVariable : 1; - uint8_t bmIsRelativeOrAbsolute : 1; - uint8_t bmIsWrapOrNoWrap : 1; - uint8_t bmIsNonLonearOrLinear : 1; - uint8_t bmIsNoPreferedOrPrefered : 1; - uint8_t bmIsNullOrNoNull : 1; - uint8_t bmIsVolatileOrNonVolatile : 1; -}; - -class HID; - -class HIDReportParser -{ -public: - virtual void Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf) = 0; -}; - -#define MAX_REPORT_PARSERS 2 -#define HID_MAX_HID_CLASS_DESCRIPTORS 5 - -class HID : public USBDeviceConfig, public UsbConfigXtracter -{ -protected: - USB *pUsb; // USB class instance pointer - uint8_t bAddress; // address - -protected: - static const uint8_t epInterruptInIndex = 1; // InterruptIN endpoint index - static const uint8_t epInterruptOutIndex = 2; // InterruptOUT endpoint index - - static const uint8_t maxHidInterfaces = 3; - static const uint8_t maxEpPerInterface = 2; - static const uint8_t totalEndpoints = (maxHidInterfaces * maxEpPerInterface + 1); - - void PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr); - void PrintHidDescriptor(const USB_HID_DESCRIPTOR *pDesc); - - virtual HIDReportParser* GetReportParser(uint8_t id); - -public: - HID(USB *pusb) : pUsb(pusb) {}; - - const USB* GetUsb() { return pUsb; }; - virtual bool SetReportParser(uint8_t id, HIDReportParser *prs); - - uint8_t SetProtocol( uint8_t iface, uint8_t protocol ); - uint8_t GetProtocol( uint8_t iface, uint8_t* dataptr ); - uint8_t GetIdle( uint8_t iface, uint8_t reportID, uint8_t* dataptr ); - uint8_t SetIdle( uint8_t iface, uint8_t reportID, uint8_t duration ); - - uint8_t GetReportDescr( uint8_t ep, USBReadParser *parser = NULL); - - uint8_t GetHidDescr( uint8_t ep, uint16_t nbytes, uint8_t* dataptr ); - uint8_t GetReport( uint8_t ep, uint8_t iface, uint8_t report_type, uint8_t report_id, uint16_t nbytes, uint8_t* dataptr ); - uint8_t SetReport( uint8_t ep, uint8_t iface, uint8_t report_type, uint8_t report_id, uint16_t nbytes, uint8_t* dataptr ); -}; - +/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. + +This software may be distributed and modified under the terms of the GNU +General Public License version 2 (GPL2) as published by the Free Software +Foundation and appearing in the file GPL2.TXT included in the packaging of +this file. Please note that GPL2 Section 2[b] requires that all works based +on this software must also be made publicly available under the terms of +the GPL2 ("Copyleft"). + +Contact information +------------------- + +Circuits At Home, LTD +Web : http://www.circuitsathome.com +e-mail : support@circuitsathome.com + */ +#if !defined(__HID_H__) +#define __HID_H__ + +#include +#include +#include "avrpins.h" +#include "max3421e.h" +#include "usbhost.h" +#include "usb_ch9.h" +#include "Usb.h" + +#if defined(ARDUINO) && ARDUINO >=100 +#include "Arduino.h" +#else +#include +#endif + +#include "printhex.h" +#include "hexdump.h" +#include "message.h" + +#include "confdescparser.h" +#include "hidusagestr.h" + +#define DATA_SIZE_MASK 0x03 +#define TYPE_MASK 0x0C +#define TAG_MASK 0xF0 + +#define DATA_SIZE_0 0x00 +#define DATA_SIZE_1 0x01 +#define DATA_SIZE_2 0x02 +#define DATA_SIZE_4 0x03 + +#define TYPE_MAIN 0x00 +#define TYPE_GLOBAL 0x04 +#define TYPE_LOCAL 0x08 + +#define TAG_MAIN_INPUT 0x80 +#define TAG_MAIN_OUTPUT 0x90 +#define TAG_MAIN_COLLECTION 0xA0 +#define TAG_MAIN_FEATURE 0xB0 +#define TAG_MAIN_ENDCOLLECTION 0xC0 + +#define TAG_GLOBAL_USAGEPAGE 0x00 +#define TAG_GLOBAL_LOGICALMIN 0x10 +#define TAG_GLOBAL_LOGICALMAX 0x20 +#define TAG_GLOBAL_PHYSMIN 0x30 +#define TAG_GLOBAL_PHYSMAX 0x40 +#define TAG_GLOBAL_UNITEXP 0x50 +#define TAG_GLOBAL_UNIT 0x60 +#define TAG_GLOBAL_REPORTSIZE 0x70 +#define TAG_GLOBAL_REPORTID 0x80 +#define TAG_GLOBAL_REPORTCOUNT 0x90 +#define TAG_GLOBAL_PUSH 0xA0 +#define TAG_GLOBAL_POP 0xB0 + +#define TAG_LOCAL_USAGE 0x00 +#define TAG_LOCAL_USAGEMIN 0x10 +#define TAG_LOCAL_USAGEMAX 0x20 + +/* HID requests */ +#define bmREQ_HIDOUT USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE +#define bmREQ_HIDIN USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE +#define bmREQ_HIDREPORT USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_STANDARD|USB_SETUP_RECIPIENT_INTERFACE + +/* HID constants. Not part of chapter 9 */ +/* Class-Specific Requests */ +#define HID_REQUEST_GET_REPORT 0x01 +#define HID_REQUEST_GET_IDLE 0x02 +#define HID_REQUEST_GET_PROTOCOL 0x03 +#define HID_REQUEST_SET_REPORT 0x09 +#define HID_REQUEST_SET_IDLE 0x0A +#define HID_REQUEST_SET_PROTOCOL 0x0B + +/* Class Descriptor Types */ +#define HID_DESCRIPTOR_HID 0x21 +#define HID_DESCRIPTOR_REPORT 0x22 +#define HID_DESRIPTOR_PHY 0x23 + +/* Protocol Selection */ +#define HID_BOOT_PROTOCOL 0x00 +#define HID_RPT_PROTOCOL 0x01 + +/* HID Interface Class Code */ +#define HID_INTF 0x03 + +/* HID Interface Class SubClass Codes */ +#define HID_BOOT_INTF_SUBCLASS 0x01 + +/* HID Interface Class Protocol Codes */ +#define HID_PROTOCOL_NONE 0x00 +#define HID_PROTOCOL_KEYBOARD 0x01 +#define HID_PROTOCOL_MOUSE 0x02 + +struct HidItemPrefix { + uint8_t bSize : 2; + uint8_t bType : 2; + uint8_t bTag : 4; +}; + +#define HID_ITEM_TYPE_MAIN 0 +#define HID_ITEM_TYPE_GLOBAL 1 +#define HID_ITEM_TYPE_LOCAL 2 +#define HID_ITEM_TYPE_RESERVED 3 + +#define HID_LONG_ITEM_PREFIX 0xfe // Long item prefix value + +#define bmHID_MAIN_ITEM_TAG 0xfc // Main item tag mask + +#define bmHID_MAIN_ITEM_INPUT 0x80 // Main item Input tag value +#define bmHID_MAIN_ITEM_OUTPUT 0x90 // Main item Output tag value +#define bmHID_MAIN_ITEM_FEATURE 0xb0 // Main item Feature tag value +#define bmHID_MAIN_ITEM_COLLECTION 0xa0 // Main item Collection tag value +#define bmHID_MAIN_ITEM_END_COLLECTION 0xce // Main item End Collection tag value + +#define HID_MAIN_ITEM_COLLECTION_PHYSICAL 0 +#define HID_MAIN_ITEM_COLLECTION_APPLICATION 1 +#define HID_MAIN_ITEM_COLLECTION_LOGICAL 2 +#define HID_MAIN_ITEM_COLLECTION_REPORT 3 +#define HID_MAIN_ITEM_COLLECTION_NAMED_ARRAY 4 +#define HID_MAIN_ITEM_COLLECTION_USAGE_SWITCH 5 +#define HID_MAIN_ITEM_COLLECTION_USAGE_MODIFIER 6 + +struct MainItemIOFeature { + uint8_t bmIsConstantOrData : 1; + uint8_t bmIsArrayOrVariable : 1; + uint8_t bmIsRelativeOrAbsolute : 1; + uint8_t bmIsWrapOrNoWrap : 1; + uint8_t bmIsNonLonearOrLinear : 1; + uint8_t bmIsNoPreferedOrPrefered : 1; + uint8_t bmIsNullOrNoNull : 1; + uint8_t bmIsVolatileOrNonVolatile : 1; +}; + +class HID; + +class HIDReportParser { +public: + virtual void Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf) = 0; +}; + +#define MAX_REPORT_PARSERS 2 +#define HID_MAX_HID_CLASS_DESCRIPTORS 5 + +class HID : public USBDeviceConfig, public UsbConfigXtracter { +protected: + USB *pUsb; // USB class instance pointer + uint8_t bAddress; // address + +protected: + static const uint8_t epInterruptInIndex = 1; // InterruptIN endpoint index + static const uint8_t epInterruptOutIndex = 2; // InterruptOUT endpoint index + + static const uint8_t maxHidInterfaces = 3; + static const uint8_t maxEpPerInterface = 2; + static const uint8_t totalEndpoints = (maxHidInterfaces * maxEpPerInterface + 1); + + void PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr); + void PrintHidDescriptor(const USB_HID_DESCRIPTOR *pDesc); + + virtual HIDReportParser* GetReportParser(uint8_t id); + +public: + + HID(USB *pusb) : pUsb(pusb) { + }; + + const USB* GetUsb() { + return pUsb; + }; + virtual bool SetReportParser(uint8_t id, HIDReportParser *prs); + + uint8_t SetProtocol(uint8_t iface, uint8_t protocol); + uint8_t GetProtocol(uint8_t iface, uint8_t* dataptr); + uint8_t GetIdle(uint8_t iface, uint8_t reportID, uint8_t* dataptr); + uint8_t SetIdle(uint8_t iface, uint8_t reportID, uint8_t duration); + + uint8_t GetReportDescr(uint8_t ep, USBReadParser *parser = NULL); + + uint8_t GetHidDescr(uint8_t ep, uint16_t nbytes, uint8_t* dataptr); + uint8_t GetReport(uint8_t ep, uint8_t iface, uint8_t report_type, uint8_t report_id, uint16_t nbytes, uint8_t* dataptr); + uint8_t SetReport(uint8_t ep, uint8_t iface, uint8_t report_type, uint8_t report_id, uint16_t nbytes, uint8_t* dataptr); +}; + #endif // __HID_H__ \ No newline at end of file diff --git a/hidboot.cpp b/hidboot.cpp index 2458401a..2168ecc7 100644 --- a/hidboot.cpp +++ b/hidboot.cpp @@ -1,154 +1,139 @@ -/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. - -This software may be distributed and modified under the terms of the GNU -General Public License version 2 (GPL2) as published by the Free Software -Foundation and appearing in the file GPL2.TXT included in the packaging of -this file. Please note that GPL2 Section 2[b] requires that all works based -on this software must also be made publicly available under the terms of -the GPL2 ("Copyleft"). - -Contact information -------------------- - -Circuits At Home, LTD -Web : http://www.circuitsathome.com -e-mail : support@circuitsathome.com -*/ -#include "hidboot.h" - -void MouseReportParser::Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf) -{ - MOUSEINFO *pmi = (MOUSEINFO*)buf; - - if (prevState.mouseInfo.bmLeftButton == 0 && pmi->bmLeftButton == 1) - OnLeftButtonDown(pmi); - - if (prevState.mouseInfo.bmLeftButton == 1 && pmi->bmLeftButton == 0) - OnLeftButtonUp(pmi); - - if (prevState.mouseInfo.bmRightButton == 0 && pmi->bmRightButton == 1) - OnRightButtonDown(pmi); - - if (prevState.mouseInfo.bmRightButton == 1 && pmi->bmRightButton == 0) - OnRightButtonUp(pmi); - - if (prevState.mouseInfo.bmMiddleButton == 0 && pmi->bmMiddleButton == 1) - OnMiddleButtonDown(pmi); - - if (prevState.mouseInfo.bmMiddleButton == 1 && pmi->bmMiddleButton == 0) - OnMiddleButtonUp(pmi); - - if (prevState.mouseInfo.dX != pmi->dX || prevState.mouseInfo.dY != pmi->dY) - OnMouseMove(pmi); - - for (uint8_t i=0; i<3; i++) - prevState.bInfo[i] = buf[i]; -}; - -void KeyboardReportParser::Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf) -{ - // On error - return - if (buf[2] == 1) - return; - - KBDINFO *pki = (KBDINFO*)buf; - - for (uint8_t i=2; i<8; i++) - { - bool down = false; - bool up = false; - - for (uint8_t j=2; j<8; j++) - { - if (buf[i] == prevState.bInfo[j] && buf[i] != 1) - down = true; - if (buf[j] == prevState.bInfo[i] && prevState.bInfo[i] != 1) - up = true; - } - if (!down) - { - HandleLockingKeys(hid, buf[i]); - OnKeyDown(*buf, buf[i]); - } - if (!up) - OnKeyUp(prevState.bInfo[0], prevState.bInfo[i]); - } - for (uint8_t i=0; i<8; i++) - prevState.bInfo[i] = buf[i]; -}; - -uint8_t KeyboardReportParser::HandleLockingKeys(HID *hid, uint8_t key) -{ - uint8_t old_keys = kbdLockingKeys.bLeds; - - switch (key) - { - case KEY_NUM_LOCK: - kbdLockingKeys.kbdLeds.bmNumLock = ~kbdLockingKeys.kbdLeds.bmNumLock; - break; - case KEY_CAPS_LOCK: - kbdLockingKeys.kbdLeds.bmCapsLock = ~kbdLockingKeys.kbdLeds.bmCapsLock; - break; - case KEY_SCROLL_LOCK: - kbdLockingKeys.kbdLeds.bmScrollLock = ~kbdLockingKeys.kbdLeds.bmScrollLock; - break; - } - - if (old_keys != kbdLockingKeys.bLeds && hid) - return (hid->SetReport(0, 0/*hid->GetIface()*/, 2, 0, 1, &kbdLockingKeys.bLeds)); - - return 0; -} - -const uint8_t KeyboardReportParser::numKeys[] PROGMEM = { '!', '@', '#', '$', '%', '^', '&', '*', '(', ')' }; -const uint8_t KeyboardReportParser::symKeysUp[] PROGMEM = { '_', '+', '{', '}', '|', '~', ':', '"', '~', '<', '>', '?' }; -const uint8_t KeyboardReportParser::symKeysLo[] PROGMEM = { '-', '=', '[', ']', '\\', ' ', ';', '\'', '`', ',', '.', '/' }; -const uint8_t KeyboardReportParser::padKeys[] PROGMEM = { '/', '*', '-', '+', 0x13 }; - -uint8_t KeyboardReportParser::OemToAscii(uint8_t mod, uint8_t key) -{ - uint8_t shift = (mod & 0x22); - - // [a-z] - if (key > 0x03 && key < 0x1e) - { - // Upper case letters - if ( (kbdLockingKeys.kbdLeds.bmCapsLock == 0 && (mod & 2)) || - (kbdLockingKeys.kbdLeds.bmCapsLock == 1 && (mod & 2) == 0) ) - return (key - 4 + 'A'); - - // Lower case letters - else - return (key - 4 + 'a'); - } - // Numbers - else if (key > 0x1d && key < 0x27) - { - if (shift) - return ((uint8_t)pgm_read_byte(&numKeys[key - 0x1e])); - else - return (key - 0x1e + '1'); - } - // Keypad Numbers - else if (key > 0x58 && key < 0x62) - { - if (kbdLockingKeys.kbdLeds.bmNumLock == 1) - return (key - 0x59 + '1'); - } - else if (key > 0x2c && key < 0x39) - return ((shift) ? (uint8_t)pgm_read_byte(&symKeysUp[key-0x2d]) : (uint8_t)pgm_read_byte(&symKeysLo[key-0x2d])); - else if (key > 0x53 && key < 0x59) - return (uint8_t)pgm_read_byte(&padKeys[key - 0x54]); - else - { - switch (key) - { - case KEY_SPACE: return(0x20); - case KEY_ENTER: return(0x13); - case KEY_ZERO: return((shift) ? ')' : '0'); - case KEY_ZERO2: return((kbdLockingKeys.kbdLeds.bmNumLock == 1) ? '0' : 0); - case KEY_PERIOD: return((kbdLockingKeys.kbdLeds.bmNumLock == 1) ? '.' : 0); - } - } - return( 0 ); -} +/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. + +This software may be distributed and modified under the terms of the GNU +General Public License version 2 (GPL2) as published by the Free Software +Foundation and appearing in the file GPL2.TXT included in the packaging of +this file. Please note that GPL2 Section 2[b] requires that all works based +on this software must also be made publicly available under the terms of +the GPL2 ("Copyleft"). + +Contact information +------------------- + +Circuits At Home, LTD +Web : http://www.circuitsathome.com +e-mail : support@circuitsathome.com + */ +#include "hidboot.h" + +void MouseReportParser::Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf) { + MOUSEINFO *pmi = (MOUSEINFO*) buf; + + if (prevState.mouseInfo.bmLeftButton == 0 && pmi->bmLeftButton == 1) + OnLeftButtonDown(pmi); + + if (prevState.mouseInfo.bmLeftButton == 1 && pmi->bmLeftButton == 0) + OnLeftButtonUp(pmi); + + if (prevState.mouseInfo.bmRightButton == 0 && pmi->bmRightButton == 1) + OnRightButtonDown(pmi); + + if (prevState.mouseInfo.bmRightButton == 1 && pmi->bmRightButton == 0) + OnRightButtonUp(pmi); + + if (prevState.mouseInfo.bmMiddleButton == 0 && pmi->bmMiddleButton == 1) + OnMiddleButtonDown(pmi); + + if (prevState.mouseInfo.bmMiddleButton == 1 && pmi->bmMiddleButton == 0) + OnMiddleButtonUp(pmi); + + if (prevState.mouseInfo.dX != pmi->dX || prevState.mouseInfo.dY != pmi->dY) + OnMouseMove(pmi); + + if (len > sizeof (MOUSEINFO)) + for (uint8_t i = 0; iSetReport(0, 0/*hid->GetIface()*/, 2, 0, 1, &kbdLockingKeys.bLeds)); + + return 0; +} + +const uint8_t KeyboardReportParser::numKeys[] PROGMEM = {'!', '@', '#', '$', '%', '^', '&', '*', '(', ')'}; +const uint8_t KeyboardReportParser::symKeysUp[] PROGMEM = {'_', '+', '{', '}', '|', '~', ':', '"', '~', '<', '>', '?'}; +const uint8_t KeyboardReportParser::symKeysLo[] PROGMEM = {'-', '=', '[', ']', '\\', ' ', ';', '\'', '`', ',', '.', '/'}; +const uint8_t KeyboardReportParser::padKeys[] PROGMEM = {'/', '*', '-', '+', 0x13}; + +uint8_t KeyboardReportParser::OemToAscii(uint8_t mod, uint8_t key) { + uint8_t shift = (mod & 0x22); + + // [a-z] + if (key > 0x03 && key < 0x1e) { + // Upper case letters + if ((kbdLockingKeys.kbdLeds.bmCapsLock == 0 && (mod & 2)) || + (kbdLockingKeys.kbdLeds.bmCapsLock == 1 && (mod & 2) == 0)) + return (key - 4 + 'A'); + + // Lower case letters + else + return (key - 4 + 'a'); + } // Numbers + else if (key > 0x1d && key < 0x27) { + if (shift) + return ((uint8_t) pgm_read_byte(&numKeys[key - 0x1e])); + else + return (key - 0x1e + '1'); + } // Keypad Numbers + else if (key > 0x58 && key < 0x62) { + if (kbdLockingKeys.kbdLeds.bmNumLock == 1) + return (key - 0x59 + '1'); + } else if (key > 0x2c && key < 0x39) + return ((shift) ? (uint8_t) pgm_read_byte(&symKeysUp[key - 0x2d]) : (uint8_t) pgm_read_byte(&symKeysLo[key - 0x2d])); + else if (key > 0x53 && key < 0x59) + return (uint8_t) pgm_read_byte(&padKeys[key - 0x54]); + else { + switch (key) { + case KEY_SPACE: return (0x20); + case KEY_ENTER: return (0x13); + case KEY_ZERO: return ((shift) ? ')': '0'); + case KEY_ZERO2: return ((kbdLockingKeys.kbdLeds.bmNumLock == 1) ? '0': 0); + case KEY_PERIOD: return ((kbdLockingKeys.kbdLeds.bmNumLock == 1) ? '.': 0); + } + } + return ( 0); +} diff --git a/hidboot.h b/hidboot.h index 26ac451b..71e813d4 100644 --- a/hidboot.h +++ b/hidboot.h @@ -1,495 +1,494 @@ -/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. - -This software may be distributed and modified under the terms of the GNU -General Public License version 2 (GPL2) as published by the Free Software -Foundation and appearing in the file GPL2.TXT included in the packaging of -this file. Please note that GPL2 Section 2[b] requires that all works based -on this software must also be made publicly available under the terms of -the GPL2 ("Copyleft"). - -Contact information -------------------- - -Circuits At Home, LTD -Web : http://www.circuitsathome.com -e-mail : support@circuitsathome.com -*/ -#if !defined(__HIDBOOT_H__) -#define __HIDBOOT_H__ - -#include -#include -#include "avrpins.h" -#include "max3421e.h" -#include "usbhost.h" -#include "usb_ch9.h" -#include "Usb.h" -#include "hid.h" - -#if defined(ARDUINO) && ARDUINO >=100 -#include "Arduino.h" -#else -#include -#endif - -#include "printhex.h" -#include "hexdump.h" -#include "message.h" - -#include "confdescparser.h" - -#define KEY_SPACE 0x2c -#define KEY_ZERO 0x27 -#define KEY_ZERO2 0x62 -#define KEY_ENTER 0x28 -#define KEY_PERIOD 0x63 - -struct MOUSEINFO -{ - struct - { - uint8_t bmLeftButton : 1; - uint8_t bmRightButton : 1; - uint8_t bmMiddleButton : 1; - uint8_t bmDummy : 1; - }; - int8_t dX; - int8_t dY; -}; - -class MouseReportParser : public HIDReportParser -{ - union - { - MOUSEINFO mouseInfo; - uint8_t bInfo[3]; - } prevState; - -public: - virtual void Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf); - -protected: - virtual void OnMouseMove (MOUSEINFO *mi) {}; - 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 bmLeftShift : 1; - uint8_t bmLeftAlt : 1; - uint8_t bmLeftGUI : 1; - uint8_t bmRightCtrl : 1; - uint8_t bmRightShift : 1; - uint8_t bmRightAlt : 1; - uint8_t bmRightGUI : 1; -}; - -struct KBDINFO -{ - struct - { - uint8_t bmLeftCtrl : 1; - uint8_t bmLeftShift : 1; - uint8_t bmLeftAlt : 1; - uint8_t bmLeftGUI : 1; - uint8_t bmRightCtrl : 1; - uint8_t bmRightShift : 1; - uint8_t bmRightAlt : 1; - uint8_t bmRightGUI : 1; - }; - uint8_t bReserved; - uint8_t Keys[6]; -}; - -struct KBDLEDS -{ - uint8_t bmNumLock : 1; - uint8_t bmCapsLock : 1; - uint8_t bmScrollLock : 1; - uint8_t bmCompose : 1; - uint8_t bmKana : 1; - uint8_t bmReserved : 3; -}; - -#define KEY_NUM_LOCK 0x53 -#define KEY_CAPS_LOCK 0x39 -#define KEY_SCROLL_LOCK 0x47 - -class KeyboardReportParser : public HIDReportParser -{ - static const uint8_t numKeys[]; - static const uint8_t symKeysUp[]; - static const uint8_t symKeysLo[]; - static const uint8_t padKeys[]; - -protected: - union - { - KBDINFO kbdInfo; - uint8_t bInfo[sizeof(KBDINFO)]; - } prevState; - - union - { - KBDLEDS kbdLeds; - uint8_t bLeds; - } kbdLockingKeys; - - uint8_t OemToAscii(uint8_t mod, uint8_t key); - -public: - KeyboardReportParser() { kbdLockingKeys.bLeds = 0; }; - - virtual void Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf); - -protected: - uint8_t HandleLockingKeys(HID* hid, uint8_t key); - - virtual void OnKeyDown (uint8_t mod, uint8_t key) {}; - virtual void OnKeyUp (uint8_t mod, uint8_t key) {}; -}; - -#define totalEndpoints 2 - -#define HID_MAX_HID_CLASS_DESCRIPTORS 5 - -template -class HIDBoot : public HID //public USBDeviceConfig, public UsbConfigXtracter -{ - EpInfo epInfo[totalEndpoints]; - - HIDReportParser *pRptParser; - - uint8_t bConfNum; // configuration number - uint8_t bIfaceNum; // Interface Number - uint8_t bNumIface; // number of interfaces in the configuration - uint8_t bNumEP; // total number of EP in the configuration - uint32_t qNextPollTime; // next poll time - bool bPollEnable; // poll enable flag - - void Initialize(); - - virtual HIDReportParser* GetReportParser(uint8_t id) { return pRptParser; }; - -public: - HIDBoot(USB *p); - - virtual bool SetReportParser(uint8_t id, HIDReportParser *prs) { pRptParser = prs; }; - - // USBDeviceConfig implementation - virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed); - virtual uint8_t Release(); - virtual uint8_t Poll(); - virtual uint8_t GetAddress() { return bAddress; }; - - // UsbConfigXtracter implementation - virtual void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep); -}; - -template -HIDBoot::HIDBoot(USB *p) : - HID(p), - qNextPollTime(0), - bPollEnable(false), - pRptParser(NULL) -{ - Initialize(); - - if (pUsb) - pUsb->RegisterDeviceClass(this); -} - -template -void HIDBoot::Initialize() -{ - for(uint8_t i=0; i -uint8_t HIDBoot::Init(uint8_t parent, uint8_t port, bool lowspeed) -{ - const uint8_t constBufSize = sizeof(USB_DEVICE_DESCRIPTOR); - - uint8_t buf[constBufSize]; - uint8_t rcode; - UsbDevice *p = NULL; - EpInfo *oldep_ptr = NULL; - uint8_t len = 0; - uint16_t cd_len = 0; - - uint8_t num_of_conf; // number of configurations - uint8_t num_of_intf; // number of interfaces - - AddressPool &addrPool = pUsb->GetAddressPool(); - - USBTRACE("BM Init\r\n"); - - if (bAddress) - return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE; - - // Get pointer to pseudo device with address 0 assigned - p = addrPool.GetUsbDevicePtr(0); - - if (!p) - return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; - - if (!p->epinfo) - { - USBTRACE("epinfo\r\n"); - return USB_ERROR_EPINFO_IS_NULL; - } - - // Save old pointer to EP_RECORD of address 0 - oldep_ptr = p->epinfo; - - // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence - p->epinfo = epInfo; - - p->lowspeed = lowspeed; - - // Get device descriptor - rcode = pUsb->getDevDescr( 0, 0, 8, (uint8_t*)buf ); - - if (!rcode) - len = (buf[0] > constBufSize) ? constBufSize : buf[0]; - - if( rcode ) - { - // Restore p->epinfo - p->epinfo = oldep_ptr; - - goto FailGetDevDescr; - } - - // Restore p->epinfo - p->epinfo = oldep_ptr; - - // Allocate new address according to device class - bAddress = addrPool.AllocAddress(parent, false, port); - - if (!bAddress) - return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; - - // Extract Max Packet Size from the device descriptor - epInfo[0].maxPktSize = (uint8_t)((USB_DEVICE_DESCRIPTOR*)buf)->bMaxPacketSize0; - - // Assign new address to the device - rcode = pUsb->setAddr( 0, 0, bAddress ); - - if (rcode) - { - p->lowspeed = false; - addrPool.FreeAddress(bAddress); - bAddress = 0; - USBTRACE2("setAddr:",rcode); - return rcode; - } - - USBTRACE2("Addr:", bAddress); - - p->lowspeed = false; - - p = addrPool.GetUsbDevicePtr(bAddress); - - if (!p) - return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; - - p->lowspeed = lowspeed; - - if (len) - rcode = pUsb->getDevDescr( bAddress, 0, len, (uint8_t*)buf ); - - if(rcode) - goto FailGetDevDescr; - - num_of_conf = ((USB_DEVICE_DESCRIPTOR*)buf)->bNumConfigurations; - - // Assign epInfo to epinfo pointer - rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); - - if (rcode) - goto FailSetDevTblEntry; - - //USBTRACE2("NC:", num_of_conf); - - for (uint8_t i=0; i HexDump; - ConfigDescParser< - USB_CLASS_HID, - HID_BOOT_INTF_SUBCLASS, - BOOT_PROTOCOL, - CP_MASK_COMPARE_ALL> confDescrParser(this); - - //rcode = pUsb->getConfDescr(bAddress, 0, i, &HexDump); - rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser); - - if (bNumEP > 1) - break; - } // for - - if (bNumEP < 2) - return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; - - //USBTRACE2("\r\nbAddr:", bAddress); - //USBTRACE2("\r\nbNumEP:", bNumEP); - - // Assign epInfo to epinfo pointer - rcode = pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo); - - //USBTRACE2("\r\nCnf:", bConfNum); - - // Set Configuration Value - rcode = pUsb->setConf(bAddress, 0, bConfNum); - - if (rcode) - goto FailSetConfDescr; - - //USBTRACE2("\r\nIf:", bIfaceNum); - - rcode = SetProtocol(bIfaceNum, HID_BOOT_PROTOCOL); - - if (rcode) - goto FailSetProtocol; - - if (BOOT_PROTOCOL == 1) - { - rcode = SetIdle(bIfaceNum, 0, 0); - - if (rcode) - goto FailSetIdle; - } - USBTRACE("BM configured\r\n"); - - bPollEnable = true; - return 0; - -FailGetDevDescr: - USBTRACE("getDevDescr:"); - goto Fail; - -FailSetDevTblEntry: - USBTRACE("setDevTblEn:"); - goto Fail; - -FailGetConfDescr: - USBTRACE("getConf:"); - goto Fail; - -FailSetProtocol: - USBTRACE("SetProto:"); - goto Fail; - -FailSetIdle: - USBTRACE("SetIdle:"); - goto Fail; - -FailSetConfDescr: - USBTRACE("setConf:"); - goto Fail; - -Fail: - Serial.println(rcode, HEX); - Release(); - return rcode; -} - -template -void HIDBoot::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *pep) -{ - // If the first configuration satisfies, the others are not concidered. - if (bNumEP > 1 && conf != bConfNum) - return; - - //ErrorMessage(PSTR("\r\nConf.Val"), conf); - //ErrorMessage(PSTR("Iface Num"), iface); - //ErrorMessage(PSTR("Alt.Set"), alt); - - bConfNum = conf; - bIfaceNum = iface; - - uint8_t index; - - if ((pep->bmAttributes & 0x03) == 3 && (pep->bEndpointAddress & 0x80) == 0x80) - { - index = epInterruptInIndex; - - // Fill in the endpoint info structure - epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F); - epInfo[index].maxPktSize = (uint8_t)pep->wMaxPacketSize; - epInfo[index].epAttribs = 0; - - bNumEP ++; - - //PrintEndpointDescriptor(pep); - } -} - - -template -uint8_t HIDBoot::Release() -{ - pUsb->GetAddressPool().FreeAddress(bAddress); - - bConfNum = 0; - bIfaceNum = 0; - bNumEP = 1; - bAddress = 0; - qNextPollTime = 0; - bPollEnable = false; - return 0; -} - -template -uint8_t HIDBoot::Poll() -{ - uint8_t rcode = 0; - - if (!bPollEnable) - return 0; - - if (qNextPollTime <= millis()) - { - qNextPollTime = millis() + 10; - - const uint8_t const_buff_len = 16; - uint8_t buf[const_buff_len]; - - uint16_t read = (uint16_t)epInfo[epInterruptInIndex].maxPktSize; - - uint8_t rcode = pUsb->inTransfer(bAddress, epInfo[epInterruptInIndex].epAddr, &read, buf); - - if (rcode) - { - if (rcode != hrNAK) - USBTRACE2("Poll:", rcode); - return rcode; - } - //for (uint8_t i=0; i(buf[i]); - //if (read) - // Serial.println(""); - - if (pRptParser) - pRptParser->Parse((HID*)this, 0, (uint8_t)read, buf); - } - return rcode; -} - - +/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. + +This software may be distributed and modified under the terms of the GNU +General Public License version 2 (GPL2) as published by the Free Software +Foundation and appearing in the file GPL2.TXT included in the packaging of +this file. Please note that GPL2 Section 2[b] requires that all works based +on this software must also be made publicly available under the terms of +the GPL2 ("Copyleft"). + +Contact information +------------------- + +Circuits At Home, LTD +Web : http://www.circuitsathome.com +e-mail : support@circuitsathome.com + */ +#if !defined(__HIDBOOT_H__) +#define __HIDBOOT_H__ + +#include +#include +#include "avrpins.h" +#include "max3421e.h" +#include "usbhost.h" +#include "usb_ch9.h" +#include "Usb.h" +#include "hid.h" + +#if defined(ARDUINO) && ARDUINO >=100 +#include "Arduino.h" +#else +#include +#endif + +#include "printhex.h" +#include "hexdump.h" +#include "message.h" + +#include "confdescparser.h" + +#define KEY_SPACE 0x2c +#define KEY_ZERO 0x27 +#define KEY_ZERO2 0x62 +#define KEY_ENTER 0x28 +#define KEY_PERIOD 0x63 + +struct MOUSEINFO { + + struct { + uint8_t bmLeftButton : 1; + uint8_t bmRightButton : 1; + uint8_t bmMiddleButton : 1; + uint8_t bmDummy : 1; + }; + int8_t dX; + int8_t dY; +}; + +class MouseReportParser : public HIDReportParser { + + union { + MOUSEINFO mouseInfo; + uint8_t bInfo[sizeof (MOUSEINFO)]; + } prevState; + +public: + virtual void Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf); + +protected: + + virtual void OnMouseMove(MOUSEINFO *mi) { + }; + + 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 bmLeftShift : 1; + uint8_t bmLeftAlt : 1; + uint8_t bmLeftGUI : 1; + uint8_t bmRightCtrl : 1; + uint8_t bmRightShift : 1; + uint8_t bmRightAlt : 1; + uint8_t bmRightGUI : 1; +}; + +struct KBDINFO { + + struct { + uint8_t bmLeftCtrl : 1; + uint8_t bmLeftShift : 1; + uint8_t bmLeftAlt : 1; + uint8_t bmLeftGUI : 1; + uint8_t bmRightCtrl : 1; + uint8_t bmRightShift : 1; + uint8_t bmRightAlt : 1; + uint8_t bmRightGUI : 1; + }; + uint8_t bReserved; + uint8_t Keys[6]; +}; + +struct KBDLEDS { + uint8_t bmNumLock : 1; + uint8_t bmCapsLock : 1; + uint8_t bmScrollLock : 1; + uint8_t bmCompose : 1; + uint8_t bmKana : 1; + uint8_t bmReserved : 3; +}; + +#define KEY_NUM_LOCK 0x53 +#define KEY_CAPS_LOCK 0x39 +#define KEY_SCROLL_LOCK 0x47 + +class KeyboardReportParser : public HIDReportParser { + static const uint8_t numKeys[]; + static const uint8_t symKeysUp[]; + static const uint8_t symKeysLo[]; + static const uint8_t padKeys[]; + +protected: + + union { + KBDINFO kbdInfo; + uint8_t bInfo[sizeof (KBDINFO)]; + } prevState; + + union { + KBDLEDS kbdLeds; + uint8_t bLeds; + } kbdLockingKeys; + + uint8_t OemToAscii(uint8_t mod, uint8_t key); + +public: + + KeyboardReportParser() { + kbdLockingKeys.bLeds = 0; + }; + + virtual void Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf); + +protected: + uint8_t HandleLockingKeys(HID* hid, uint8_t key); + + virtual void OnKeyDown(uint8_t mod, uint8_t key) { + }; + + virtual void OnKeyUp(uint8_t mod, uint8_t key) { + }; +}; + +#define totalEndpoints 2 + +#define HID_MAX_HID_CLASS_DESCRIPTORS 5 + +template +class HIDBoot : public HID //public USBDeviceConfig, public UsbConfigXtracter +{ + EpInfo epInfo[totalEndpoints]; + + HIDReportParser *pRptParser; + + uint8_t bConfNum; // configuration number + uint8_t bIfaceNum; // Interface Number + uint8_t bNumIface; // number of interfaces in the configuration + uint8_t bNumEP; // total number of EP in the configuration + uint32_t qNextPollTime; // next poll time + bool bPollEnable; // poll enable flag + + void Initialize(); + + virtual HIDReportParser* GetReportParser(uint8_t id) { + return pRptParser; + }; + +public: + HIDBoot(USB *p); + + virtual bool SetReportParser(uint8_t id, HIDReportParser *prs) { + pRptParser = prs; + return true; + }; + + // USBDeviceConfig implementation + virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed); + virtual uint8_t Release(); + virtual uint8_t Poll(); + + virtual uint8_t GetAddress() { + return bAddress; + }; + + // UsbConfigXtracter implementation + virtual void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep); +}; + +template +HIDBoot::HIDBoot(USB *p) : +HID(p), +qNextPollTime(0), +bPollEnable(false), +pRptParser(NULL) { + Initialize(); + + if (pUsb) + pUsb->RegisterDeviceClass(this); +} + +template +void HIDBoot::Initialize() { + for (uint8_t i = 0; i < totalEndpoints; i++) { + epInfo[i].epAddr = 0; + epInfo[i].maxPktSize = (i) ? 0 : 8; + epInfo[i].epAttribs = 0; + epInfo[i].bmNakPower = (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER; + } + bNumEP = 1; + bNumIface = 0; + bConfNum = 0; +} + +template +uint8_t HIDBoot::Init(uint8_t parent, uint8_t port, bool lowspeed) { + const uint8_t constBufSize = sizeof (USB_DEVICE_DESCRIPTOR); + + uint8_t buf[constBufSize]; + uint8_t rcode; + UsbDevice *p = NULL; + EpInfo *oldep_ptr = NULL; + uint8_t len = 0; + uint16_t cd_len = 0; + + uint8_t num_of_conf; // number of configurations + uint8_t num_of_intf; // number of interfaces + + AddressPool &addrPool = pUsb->GetAddressPool(); + + USBTRACE("BM Init\r\n"); + + if (bAddress) + return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE; + + // Get pointer to pseudo device with address 0 assigned + p = addrPool.GetUsbDevicePtr(0); + + if (!p) + return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; + + if (!p->epinfo) { + USBTRACE("epinfo\r\n"); + return USB_ERROR_EPINFO_IS_NULL; + } + + // Save old pointer to EP_RECORD of address 0 + oldep_ptr = p->epinfo; + + // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence + p->epinfo = epInfo; + + p->lowspeed = lowspeed; + + // Get device descriptor + rcode = pUsb->getDevDescr(0, 0, 8, (uint8_t*) buf); + + if (!rcode) + len = (buf[0] > constBufSize) ? constBufSize : buf[0]; + + if (rcode) { + // Restore p->epinfo + p->epinfo = oldep_ptr; + + goto FailGetDevDescr; + } + + // Restore p->epinfo + p->epinfo = oldep_ptr; + + // Allocate new address according to device class + bAddress = addrPool.AllocAddress(parent, false, port); + + if (!bAddress) + return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; + + // Extract Max Packet Size from the device descriptor + epInfo[0].maxPktSize = (uint8_t) ((USB_DEVICE_DESCRIPTOR*) buf)->bMaxPacketSize0; + + // Assign new address to the device + rcode = pUsb->setAddr(0, 0, bAddress); + + if (rcode) { + p->lowspeed = false; + addrPool.FreeAddress(bAddress); + bAddress = 0; + USBTRACE2("setAddr:", rcode); + return rcode; + } + + USBTRACE2("Addr:", bAddress); + + p->lowspeed = false; + + p = addrPool.GetUsbDevicePtr(bAddress); + + if (!p) + return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; + + p->lowspeed = lowspeed; + + if (len) + rcode = pUsb->getDevDescr(bAddress, 0, len, (uint8_t*) buf); + + if (rcode) + goto FailGetDevDescr; + + num_of_conf = ((USB_DEVICE_DESCRIPTOR*) buf)->bNumConfigurations; + + // Assign epInfo to epinfo pointer + rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); + + if (rcode) + goto FailSetDevTblEntry; + + //USBTRACE2("NC:", num_of_conf); + + for (uint8_t i = 0; i < num_of_conf; i++) { + ConfigDescParser< + USB_CLASS_HID, + HID_BOOT_INTF_SUBCLASS, + BOOT_PROTOCOL, + CP_MASK_COMPARE_ALL> confDescrParser(this); + + rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser); + + if (bNumEP > 1) + break; + } // for + + if (bNumEP < 2) + return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; + + //USBTRACE2("\r\nbAddr:", bAddress); + //USBTRACE2("\r\nbNumEP:", bNumEP); + + // Assign epInfo to epinfo pointer + rcode = pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo); + + //USBTRACE2("\r\nCnf:", bConfNum); + + // Set Configuration Value + rcode = pUsb->setConf(bAddress, 0, bConfNum); + + if (rcode) + goto FailSetConfDescr; + + //USBTRACE2("\r\nIf:", bIfaceNum); + + rcode = SetProtocol(bIfaceNum, HID_BOOT_PROTOCOL); + + if (rcode) + goto FailSetProtocol; + + if (BOOT_PROTOCOL == 1) { + rcode = SetIdle(bIfaceNum, 0, 0); + + if (rcode) + goto FailSetIdle; + } + USBTRACE("BM configured\r\n"); + + bPollEnable = true; + return 0; + +FailGetDevDescr: + USBTRACE("getDevDescr:"); + goto Fail; + +FailSetDevTblEntry: + USBTRACE("setDevTblEn:"); + goto Fail; + +FailGetConfDescr: + USBTRACE("getConf:"); + goto Fail; + +FailSetProtocol: + USBTRACE("SetProto:"); + goto Fail; + +FailSetIdle: + USBTRACE("SetIdle:"); + goto Fail; + +FailSetConfDescr: + USBTRACE("setConf:"); + goto Fail; + +Fail: + PrintHex (rcode, 0x80); + Notify(PSTR("\n"), 0x80); + // Serial.println(rcode, HEX); + Release(); + return rcode; +} + +template +void HIDBoot::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *pep) { + // If the first configuration satisfies, the others are not concidered. + if (bNumEP > 1 && conf != bConfNum) + return; + + bConfNum = conf; + bIfaceNum = iface; + + uint8_t index; + + if ((pep->bmAttributes & 0x03) == 3 && (pep->bEndpointAddress & 0x80) == 0x80) { + index = epInterruptInIndex; + + // Fill in the endpoint info structure + epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F); + epInfo[index].maxPktSize = (uint8_t) pep->wMaxPacketSize; + epInfo[index].epAttribs = 0; + + bNumEP++; + } +} + +template +uint8_t HIDBoot::Release() { + pUsb->GetAddressPool().FreeAddress(bAddress); + + bConfNum = 0; + bIfaceNum = 0; + bNumEP = 1; + bAddress = 0; + qNextPollTime = 0; + bPollEnable = false; + return 0; +} + +template +uint8_t HIDBoot::Poll() { + uint8_t rcode = 0; + + if (!bPollEnable) + return 0; + + if (qNextPollTime <= millis()) { + qNextPollTime = millis() + 10; + + const uint8_t const_buff_len = 16; + uint8_t buf[const_buff_len]; + + uint16_t read = (uint16_t) epInfo[epInterruptInIndex].maxPktSize; + + uint8_t rcode = pUsb->inTransfer(bAddress, epInfo[epInterruptInIndex].epAddr, &read, buf); + + if (rcode) { + if (rcode != hrNAK) + USBTRACE2("Poll:", rcode); + return rcode; + } + //for (uint8_t i=0; i(buf[i]); + //if (read) + // Serial.println(""); + + if (pRptParser) + pRptParser->Parse((HID*)this, 0, (uint8_t) read, buf); + } + return rcode; +} + + #endif // __HIDBOOTMOUSE_H__ \ No newline at end of file diff --git a/hidescriptorparser.cpp b/hidescriptorparser.cpp index af4fc55d..ddb001da 100644 --- a/hidescriptorparser.cpp +++ b/hidescriptorparser.cpp @@ -1,1713 +1,1626 @@ -#include "hidescriptorparser.h" - -const char *ReportDescParserBase::usagePageTitles0[] PROGMEM = -{ - pstrUsagePageGenericDesktopControls , - pstrUsagePageSimulationControls , - pstrUsagePageVRControls , - pstrUsagePageSportControls , - pstrUsagePageGameControls , - pstrUsagePageGenericDeviceControls , - pstrUsagePageKeyboardKeypad , - pstrUsagePageLEDs , - pstrUsagePageButton , - pstrUsagePageOrdinal , - pstrUsagePageTelephone , - pstrUsagePageConsumer , - pstrUsagePageDigitizer , - pstrUsagePagePID , - pstrUsagePageUnicode -}; - -const char *ReportDescParserBase::usagePageTitles1[] PROGMEM = -{ - pstrUsagePageBarCodeScanner , - pstrUsagePageScale , - pstrUsagePageMSRDevices , - pstrUsagePagePointOfSale , - pstrUsagePageCameraControl , - pstrUsagePageArcade -}; -const char *ReportDescParserBase::genDesktopTitles0[] PROGMEM = -{ - pstrUsagePointer , - pstrUsageMouse , - pstrUsageJoystick , - pstrUsageGamePad , - pstrUsageKeyboard , - pstrUsageKeypad , - pstrUsageMultiAxisController , - pstrUsageTabletPCSystemControls - -}; -const char *ReportDescParserBase::genDesktopTitles1[] PROGMEM = -{ - pstrUsageX , - pstrUsageY , - pstrUsageZ , - pstrUsageRx , - pstrUsageRy , - pstrUsageRz , - pstrUsageSlider , - pstrUsageDial , - pstrUsageWheel , - pstrUsageHatSwitch , - pstrUsageCountedBuffer , - pstrUsageByteCount , - pstrUsageMotionWakeup , - pstrUsageStart , - pstrUsageSelect , - pstrUsagePageReserved , - pstrUsageVx , - pstrUsageVy , - pstrUsageVz , - pstrUsageVbrx , - pstrUsageVbry , - pstrUsageVbrz , - pstrUsageVno , - pstrUsageFeatureNotification , - pstrUsageResolutionMultiplier -}; -const char *ReportDescParserBase::genDesktopTitles2[] PROGMEM = -{ - pstrUsageSystemControl , - pstrUsageSystemPowerDown , - pstrUsageSystemSleep , - pstrUsageSystemWakeup , - pstrUsageSystemContextMenu , - pstrUsageSystemMainMenu , - pstrUsageSystemAppMenu , - pstrUsageSystemMenuHelp , - pstrUsageSystemMenuExit , - pstrUsageSystemMenuSelect , - pstrUsageSystemMenuRight , - pstrUsageSystemMenuLeft , - pstrUsageSystemMenuUp , - pstrUsageSystemMenuDown , - pstrUsageSystemColdRestart , - pstrUsageSystemWarmRestart , - pstrUsageDPadUp , - pstrUsageDPadDown , - pstrUsageDPadRight , - pstrUsageDPadLeft -}; -const char *ReportDescParserBase::genDesktopTitles3[] PROGMEM = -{ - pstrUsageSystemDock , - pstrUsageSystemUndock , - pstrUsageSystemSetup , - pstrUsageSystemBreak , - pstrUsageSystemDebuggerBreak , - pstrUsageApplicationBreak , - pstrUsageApplicationDebuggerBreak, - pstrUsageSystemSpeakerMute , - pstrUsageSystemHibernate -}; -const char *ReportDescParserBase::genDesktopTitles4[] PROGMEM = -{ - pstrUsageSystemDisplayInvert , - pstrUsageSystemDisplayInternal , - pstrUsageSystemDisplayExternal , - pstrUsageSystemDisplayBoth , - pstrUsageSystemDisplayDual , - pstrUsageSystemDisplayToggleIntExt , - pstrUsageSystemDisplaySwapPriSec , - pstrUsageSystemDisplayLCDAutoscale -}; -const char *ReportDescParserBase::simuTitles0[] PROGMEM = -{ - pstrUsageFlightSimulationDevice , - pstrUsageAutomobileSimulationDevice , - pstrUsageTankSimulationDevice , - pstrUsageSpaceshipSimulationDevice , - pstrUsageSubmarineSimulationDevice , - pstrUsageSailingSimulationDevice , - pstrUsageMotocicleSimulationDevice , - pstrUsageSportsSimulationDevice , - pstrUsageAirplaneSimulationDevice , - pstrUsageHelicopterSimulationDevice , - pstrUsageMagicCarpetSimulationDevice, - pstrUsageBicycleSimulationDevice -}; -const char *ReportDescParserBase::simuTitles1[] PROGMEM = -{ - pstrUsageFlightControlStick , - pstrUsageFlightStick , - pstrUsageCyclicControl , - pstrUsageCyclicTrim , - pstrUsageFlightYoke , - pstrUsageTrackControl -}; -const char *ReportDescParserBase::simuTitles2[] PROGMEM = -{ - pstrUsageAileron , - pstrUsageAileronTrim , - pstrUsageAntiTorqueControl , - pstrUsageAutopilotEnable , - pstrUsageChaffRelease , - pstrUsageCollectiveControl , - pstrUsageDiveBrake , - pstrUsageElectronicCountermeasures , - pstrUsageElevator , - pstrUsageElevatorTrim , - pstrUsageRudder , - pstrUsageThrottle , - pstrUsageFlightCommunications , - pstrUsageFlareRelease , - pstrUsageLandingGear , - pstrUsageToeBrake , - pstrUsageTrigger , - pstrUsageWeaponsArm , - pstrUsageWeaponsSelect , - pstrUsageWingFlaps , - pstrUsageAccelerator , - pstrUsageBrake , - pstrUsageClutch , - pstrUsageShifter , - pstrUsageSteering , - pstrUsageTurretDirection , - pstrUsageBarrelElevation , - pstrUsageDivePlane , - pstrUsageBallast , - pstrUsageBicycleCrank , - pstrUsageHandleBars , - pstrUsageFrontBrake , - pstrUsageRearBrake -}; -const char *ReportDescParserBase::vrTitles0[] PROGMEM = -{ - pstrUsageBelt , - pstrUsageBodySuit , - pstrUsageFlexor , - pstrUsageGlove , - pstrUsageHeadTracker , - pstrUsageHeadMountedDisplay , - pstrUsageHandTracker , - pstrUsageOculometer , - pstrUsageVest , - pstrUsageAnimatronicDevice -}; -const char *ReportDescParserBase::vrTitles1[] PROGMEM = -{ - pstrUsageStereoEnable , - pstrUsageDisplayEnable -}; -const char *ReportDescParserBase::sportsCtrlTitles0[] PROGMEM = -{ - pstrUsageBaseballBat , - pstrUsageGolfClub , - pstrUsageRowingMachine , - pstrUsageTreadmill -}; -const char *ReportDescParserBase::sportsCtrlTitles1[] PROGMEM = -{ - pstrUsageOar , - pstrUsageSlope , - pstrUsageRate , - pstrUsageStickSpeed , - pstrUsageStickFaceAngle , - pstrUsageStickHeelToe , - pstrUsageStickFollowThough , - pstrUsageStickTempo , - pstrUsageStickType , - pstrUsageStickHeight -}; -const char *ReportDescParserBase::sportsCtrlTitles2[] PROGMEM = -{ - pstrUsagePutter , - pstrUsage1Iron , - pstrUsage2Iron , - pstrUsage3Iron , - pstrUsage4Iron , - pstrUsage5Iron , - pstrUsage6Iron , - pstrUsage7Iron , - pstrUsage8Iron , - pstrUsage9Iron , - pstrUsage10Iron , - pstrUsage11Iron , - pstrUsageSandWedge , - pstrUsageLoftWedge , - pstrUsagePowerWedge , - pstrUsage1Wood , - pstrUsage3Wood , - pstrUsage5Wood , - pstrUsage7Wood , - pstrUsage9Wood -}; -const char *ReportDescParserBase::gameTitles0[] PROGMEM = -{ - pstrUsage3DGameController , - pstrUsagePinballDevice , - pstrUsageGunDevice -}; -const char *ReportDescParserBase::gameTitles1[] PROGMEM = -{ - pstrUsagePointOfView , - pstrUsageTurnRightLeft , - pstrUsagePitchForwardBackward , - pstrUsageRollRightLeft , - pstrUsageMoveRightLeft , - pstrUsageMoveForwardBackward , - pstrUsageMoveUpDown , - pstrUsageLeanRightLeft , - pstrUsageLeanForwardBackward , - pstrUsageHeightOfPOV , - pstrUsageFlipper , - pstrUsageSecondaryFlipper , - pstrUsageBump , - pstrUsageNewGame , - pstrUsageShootBall , - pstrUsagePlayer , - pstrUsageGunBolt , - pstrUsageGunClip , - pstrUsageGunSelector , - pstrUsageGunSingleShot , - pstrUsageGunBurst , - pstrUsageGunAutomatic , - pstrUsageGunSafety , - pstrUsageGamepadFireJump , - pstrUsageGamepadTrigger -}; -const char *ReportDescParserBase::genDevCtrlTitles[] PROGMEM = -{ - pstrUsageBatteryStrength, - pstrUsageWirelessChannel, - pstrUsageWirelessID, - pstrUsageDiscoverWirelessControl, - pstrUsageSecurityCodeCharEntered, - pstrUsageSecurityCodeCharErased, - pstrUsageSecurityCodeCleared -}; -const char *ReportDescParserBase::ledTitles[] PROGMEM = -{ - pstrUsageNumLock , - pstrUsageCapsLock , - pstrUsageScrollLock , - pstrUsageCompose , - pstrUsageKana , - pstrUsagePower , - pstrUsageShift , - pstrUsageDoNotDisturb , - pstrUsageMute , - pstrUsageToneEnable , - pstrUsageHighCutFilter , - pstrUsageLowCutFilter , - pstrUsageEqualizerEnable , - pstrUsageSoundFieldOn , - pstrUsageSurroundOn , - pstrUsageRepeat , - pstrUsageStereo , - pstrUsageSamplingRateDetect , - pstrUsageSpinning , - pstrUsageCAV , - pstrUsageCLV , - pstrUsageRecordingFormatDetect , - pstrUsageOffHook , - pstrUsageRing , - pstrUsageMessageWaiting , - pstrUsageDataMode , - pstrUsageBatteryOperation , - pstrUsageBatteryOK , - pstrUsageBatteryLow , - pstrUsageSpeaker , - pstrUsageHeadSet , - pstrUsageHold , - pstrUsageMicrophone , - pstrUsageCoverage , - pstrUsageNightMode , - pstrUsageSendCalls , - pstrUsageCallPickup , - pstrUsageConference , - pstrUsageStandBy , - pstrUsageCameraOn , - pstrUsageCameraOff , - pstrUsageOnLine , - pstrUsageOffLine , - pstrUsageBusy , - pstrUsageReady , - pstrUsagePaperOut , - pstrUsagePaperJam , - pstrUsageRemote , - pstrUsageForward , - pstrUsageReverse , - pstrUsageStop , - pstrUsageRewind , - pstrUsageFastForward , - pstrUsagePlay , - pstrUsagePause , - pstrUsageRecord , - pstrUsageError , - pstrUsageSelectedIndicator , - pstrUsageInUseIndicator , - pstrUsageMultiModeIndicator , - pstrUsageIndicatorOn , - pstrUsageIndicatorFlash , - pstrUsageIndicatorSlowBlink , - pstrUsageIndicatorFastBlink , - pstrUsageIndicatorOff , - pstrUsageFlashOnTime , - pstrUsageSlowBlinkOnTime , - pstrUsageSlowBlinkOffTime , - pstrUsageFastBlinkOnTime , - pstrUsageFastBlinkOffTime , - pstrUsageIndicatorColor , - pstrUsageIndicatorRed , - pstrUsageIndicatorGreen , - pstrUsageIndicatorAmber , - pstrUsageGenericIndicator , - pstrUsageSystemSuspend , - pstrUsageExternalPowerConnected -}; -const char *ReportDescParserBase::telTitles0 [] PROGMEM = -{ - pstrUsagePhone , - pstrUsageAnsweringMachine , - pstrUsageMessageControls , - pstrUsageHandset , - pstrUsageHeadset , - pstrUsageTelephonyKeyPad , - pstrUsageProgrammableButton -}; -const char *ReportDescParserBase::telTitles1 [] PROGMEM = -{ - pstrUsageHookSwitch , - pstrUsageFlash , - pstrUsageFeature , - pstrUsageHold , - pstrUsageRedial , - pstrUsageTransfer , - pstrUsageDrop , - pstrUsagePark , - pstrUsageForwardCalls , - pstrUsageAlternateFunction , - pstrUsageLine , - pstrUsageSpeakerPhone , - pstrUsageConference , - pstrUsageRingEnable , - pstrUsageRingSelect , - pstrUsagePhoneMute , - pstrUsageCallerID , - pstrUsageSend -}; -const char *ReportDescParserBase::telTitles2 [] PROGMEM = -{ - pstrUsageSpeedDial , - pstrUsageStoreNumber , - pstrUsageRecallNumber , - pstrUsagePhoneDirectory -}; -const char *ReportDescParserBase::telTitles3 [] PROGMEM = -{ - pstrUsageVoiceMail , - pstrUsageScreenCalls , - pstrUsageDoNotDisturb , - pstrUsageMessage , - pstrUsageAnswerOnOff -}; -const char *ReportDescParserBase::telTitles4 [] PROGMEM = -{ - pstrUsageInsideDialTone , - pstrUsageOutsideDialTone , - pstrUsageInsideRingTone , - pstrUsageOutsideRingTone , - pstrUsagePriorityRingTone , - pstrUsageInsideRingback , - pstrUsagePriorityRingback , - pstrUsageLineBusyTone , - pstrUsageReorderTone , - pstrUsageCallWaitingTone , - pstrUsageConfirmationTone1 , - pstrUsageConfirmationTone2 , - pstrUsageTonesOff , - pstrUsageOutsideRingback , - pstrUsageRinger -}; -const char *ReportDescParserBase::telTitles5 [] PROGMEM = -{ - pstrUsagePhoneKey0 , - pstrUsagePhoneKey1 , - pstrUsagePhoneKey2 , - pstrUsagePhoneKey3 , - pstrUsagePhoneKey4 , - pstrUsagePhoneKey5 , - pstrUsagePhoneKey6 , - pstrUsagePhoneKey7 , - pstrUsagePhoneKey8 , - pstrUsagePhoneKey9 , - pstrUsagePhoneKeyStar , - pstrUsagePhoneKeyPound , - pstrUsagePhoneKeyA , - pstrUsagePhoneKeyB , - pstrUsagePhoneKeyC , - pstrUsagePhoneKeyD -}; -const char *ReportDescParserBase::consTitles0[] PROGMEM = -{ - pstrUsageConsumerControl, - pstrUsageNumericKeyPad, - pstrUsageProgrammableButton, - pstrUsageMicrophone, - pstrUsageHeadphone, - pstrUsageGraphicEqualizer -}; -const char *ReportDescParserBase::consTitles1[] PROGMEM = -{ - pstrUsagePlus10 , - pstrUsagePlus100, - pstrUsageAMPM -}; -const char *ReportDescParserBase::consTitles2[] PROGMEM = -{ - pstrUsagePower , - pstrUsageReset , - pstrUsageSleep , - pstrUsageSleepAfter , - pstrUsageSleepMode , - pstrUsageIllumination , - pstrUsageFunctionButtons - -}; -const char *ReportDescParserBase::consTitles3[] PROGMEM = -{ - pstrUsageMenu , - pstrUsageMenuPick , - pstrUsageMenuUp , - pstrUsageMenuDown , - pstrUsageMenuLeft , - pstrUsageMenuRight , - pstrUsageMenuEscape , - pstrUsageMenuValueIncrease, - pstrUsageMenuValueDecrease -}; -const char *ReportDescParserBase::consTitles4[] PROGMEM = -{ - pstrUsageDataOnScreen , - pstrUsageClosedCaption , - pstrUsageClosedCaptionSelect, - pstrUsageVCRTV , - pstrUsageBroadcastMode , - pstrUsageSnapshot , - pstrUsageStill -}; -const char *ReportDescParserBase::consTitles5[] PROGMEM = -{ - pstrUsageSelection , - pstrUsageAssignSelection , - pstrUsageModeStep , - pstrUsageRecallLast , - pstrUsageEnterChannel , - pstrUsageOrderMovie , - pstrUsageChannel , - pstrUsageMediaSelection , - pstrUsageMediaSelectComputer , - pstrUsageMediaSelectTV , - pstrUsageMediaSelectWWW , - pstrUsageMediaSelectDVD , - pstrUsageMediaSelectTelephone , - pstrUsageMediaSelectProgramGuide , - pstrUsageMediaSelectVideoPhone , - pstrUsageMediaSelectGames , - pstrUsageMediaSelectMessages , - pstrUsageMediaSelectCD , - pstrUsageMediaSelectVCR , - pstrUsageMediaSelectTuner , - pstrUsageQuit , - pstrUsageHelp , - pstrUsageMediaSelectTape , - pstrUsageMediaSelectCable , - pstrUsageMediaSelectSatellite , - pstrUsageMediaSelectSecurity , - pstrUsageMediaSelectHome , - pstrUsageMediaSelectCall , - pstrUsageChannelIncrement , - pstrUsageChannelDecrement , - pstrUsageMediaSelectSAP , - pstrUsagePageReserved , - pstrUsageVCRPlus , - pstrUsageOnce , - pstrUsageDaily , - pstrUsageWeekly , - pstrUsageMonthly -}; -const char *ReportDescParserBase::consTitles6[] PROGMEM = -{ - pstrUsagePlay , - pstrUsagePause , - pstrUsageRecord , - pstrUsageFastForward , - pstrUsageRewind , - pstrUsageScanNextTrack , - pstrUsageScanPreviousTrack , - pstrUsageStop , - pstrUsageEject , - pstrUsageRandomPlay , - pstrUsageSelectDisk , - pstrUsageEnterDisk , - pstrUsageRepeat , - pstrUsageTracking , - pstrUsageTrackNormal , - pstrUsageSlowTracking , - pstrUsageFrameForward , - pstrUsageFrameBackwards , - pstrUsageMark , - pstrUsageClearMark , - pstrUsageRepeatFromMark , - pstrUsageReturnToMark , - pstrUsageSearchMarkForward , - pstrUsageSearchMarkBackwards , - pstrUsageCounterReset , - pstrUsageShowCounter , - pstrUsageTrackingIncrement , - pstrUsageTrackingDecrement , - pstrUsageStopEject , - pstrUsagePlayPause , - pstrUsagePlaySkip -}; -const char *ReportDescParserBase::consTitles7[] PROGMEM = -{ - pstrUsageVolume , - pstrUsageBalance , - pstrUsageMute , - pstrUsageBass , - pstrUsageTreble , - pstrUsageBassBoost , - pstrUsageSurroundMode , - pstrUsageLoudness , - pstrUsageMPX , - pstrUsageVolumeIncrement , - pstrUsageVolumeDecrement -}; -const char *ReportDescParserBase::consTitles8[] PROGMEM = -{ - pstrUsageSpeedSelect , - pstrUsagePlaybackSpeed , - pstrUsageStandardPlay , - pstrUsageLongPlay , - pstrUsageExtendedPlay , - pstrUsageSlow -}; -const char *ReportDescParserBase::consTitles9[] PROGMEM = -{ - pstrUsageFanEnable , - pstrUsageFanSpeed , - pstrUsageLightEnable , - pstrUsageLightIlluminationLevel , - pstrUsageClimateControlEnable , - pstrUsageRoomTemperature , - pstrUsageSecurityEnable , - pstrUsageFireAlarm , - pstrUsagePoliceAlarm , - pstrUsageProximity , - pstrUsageMotion , - pstrUsageDuresAlarm , - pstrUsageHoldupAlarm , - pstrUsageMedicalAlarm -}; -const char *ReportDescParserBase::consTitlesA[] PROGMEM = -{ - pstrUsageBalanceRight , - pstrUsageBalanceLeft , - pstrUsageBassIncrement , - pstrUsageBassDecrement , - pstrUsageTrebleIncrement , - pstrUsageTrebleDecrement -}; -const char *ReportDescParserBase::consTitlesB[] PROGMEM = -{ - pstrUsageSpeakerSystem , - pstrUsageChannelLeft , - pstrUsageChannelRight , - pstrUsageChannelCenter , - pstrUsageChannelFront , - pstrUsageChannelCenterFront , - pstrUsageChannelSide , - pstrUsageChannelSurround , - pstrUsageChannelLowFreqEnhancement , - pstrUsageChannelTop , - pstrUsageChannelUnknown -}; -const char *ReportDescParserBase::consTitlesC[] PROGMEM = -{ - pstrUsageSubChannel , - pstrUsageSubChannelIncrement , - pstrUsageSubChannelDecrement , - pstrUsageAlternateAudioIncrement , - pstrUsageAlternateAudioDecrement -}; -const char *ReportDescParserBase::consTitlesD[] PROGMEM = -{ - pstrUsageApplicationLaunchButtons , - pstrUsageALLaunchButtonConfigTool , - pstrUsageALProgrammableButton , - pstrUsageALConsumerControlConfig , - pstrUsageALWordProcessor , - pstrUsageALTextEditor , - pstrUsageALSpreadsheet , - pstrUsageALGraphicsEditor , - pstrUsageALPresentationApp , - pstrUsageALDatabaseApp , - pstrUsageALEmailReader , - pstrUsageALNewsreader , - pstrUsageALVoicemail , - pstrUsageALContactsAddressBook , - pstrUsageALCalendarSchedule , - pstrUsageALTaskProjectManager , - pstrUsageALLogJournalTimecard , - pstrUsageALCheckbookFinance , - pstrUsageALCalculator , - pstrUsageALAVCapturePlayback , - pstrUsageALLocalMachineBrowser , - pstrUsageALLANWANBrow , - pstrUsageALInternetBrowser , - pstrUsageALRemoteNetISPConnect , - pstrUsageALNetworkConference , - pstrUsageALNetworkChat , - pstrUsageALTelephonyDialer , - pstrUsageALLogon , - pstrUsageALLogoff , - pstrUsageALLogonLogoff , - pstrUsageALTermLockScrSav , - pstrUsageALControlPannel , - pstrUsageALCommandLineProcessorRun , - pstrUsageALProcessTaskManager , - pstrUsageALSelectTaskApplication , - pstrUsageALNextTaskApplication , - pstrUsageALPreviousTaskApplication , - pstrUsageALPreemptiveHaltTaskApp , - pstrUsageALIntegratedHelpCenter , - pstrUsageALDocuments , - pstrUsageALThesaurus , - pstrUsageALDictionary , - pstrUsageALDesktop , - pstrUsageALSpellCheck , - pstrUsageALGrammarCheck , - pstrUsageALWirelessStatus , - pstrUsageALKeyboardLayout , - pstrUsageALVirusProtection , - pstrUsageALEncryption , - pstrUsageALScreenSaver , - pstrUsageALAlarms , - pstrUsageALClock , - pstrUsageALFileBrowser , - pstrUsageALPowerStatus , - pstrUsageALImageBrowser , - pstrUsageALAudioBrowser , - pstrUsageALMovieBrowser , - pstrUsageALDigitalRightsManager , - pstrUsageALDigitalWallet , - pstrUsagePageReserved , - pstrUsageALInstantMessaging , - pstrUsageALOEMFeaturesBrowser , - pstrUsageALOEMHelp , - pstrUsageALOnlineCommunity , - pstrUsageALEntertainmentContentBrow , - pstrUsageALOnlineShoppingBrowser , - pstrUsageALSmartCardInfoHelp , - pstrUsageALMarketMonitorFinBrowser , - pstrUsageALCustomCorpNewsBrowser , - pstrUsageALOnlineActivityBrowser , - pstrUsageALResearchSearchBrowser , - pstrUsageALAudioPlayer -}; -const char *ReportDescParserBase::consTitlesE[] PROGMEM = -{ - pstrUsageGenericGUIAppControls , - pstrUsageACNew , - pstrUsageACOpen , - pstrUsageACClose , - pstrUsageACExit , - pstrUsageACMaximize , - pstrUsageACMinimize , - pstrUsageACSave , - pstrUsageACPrint , - pstrUsageACProperties , - pstrUsageACUndo , - pstrUsageACCopy , - pstrUsageACCut , - pstrUsageACPaste , - pstrUsageACSelectAll , - pstrUsageACFind , - pstrUsageACFindAndReplace , - pstrUsageACSearch , - pstrUsageACGoto , - pstrUsageACHome , - pstrUsageACBack , - pstrUsageACForward , - pstrUsageACStop , - pstrUsageACRefresh , - pstrUsageACPreviousLink , - pstrUsageACNextLink , - pstrUsageACBookmarks , - pstrUsageACHistory , - pstrUsageACSubscriptions , - pstrUsageACZoomIn , - pstrUsageACZoomOut , - pstrUsageACZoom , - pstrUsageACFullScreenView , - pstrUsageACNormalView , - pstrUsageACViewToggle , - pstrUsageACScrollUp , - pstrUsageACScrollDown , - pstrUsageACScroll , - pstrUsageACPanLeft , - pstrUsageACPanRight , - pstrUsageACPan , - pstrUsageACNewWindow , - pstrUsageACTileHoriz , - pstrUsageACTileVert , - pstrUsageACFormat , - pstrUsageACEdit , - pstrUsageACBold , - pstrUsageACItalics , - pstrUsageACUnderline , - pstrUsageACStrikethrough , - pstrUsageACSubscript , - pstrUsageACSuperscript , - pstrUsageACAllCaps , - pstrUsageACRotate , - pstrUsageACResize , - pstrUsageACFlipHorizontal , - pstrUsageACFlipVertical , - pstrUsageACMirrorHorizontal , - pstrUsageACMirrorVertical , - pstrUsageACFontSelect , - pstrUsageACFontColor , - pstrUsageACFontSize , - pstrUsageACJustifyLeft , - pstrUsageACJustifyCenterH , - pstrUsageACJustifyRight , - pstrUsageACJustifyBlockH , - pstrUsageACJustifyTop , - pstrUsageACJustifyCenterV , - pstrUsageACJustifyBottom , - pstrUsageACJustifyBlockV , - pstrUsageACIndentDecrease , - pstrUsageACIndentIncrease , - pstrUsageACNumberedList , - pstrUsageACRestartNumbering , - pstrUsageACBulletedList , - pstrUsageACPromote , - pstrUsageACDemote , - pstrUsageACYes , - pstrUsageACNo , - pstrUsageACCancel , - pstrUsageACCatalog , - pstrUsageACBuyChkout , - pstrUsageACAddToCart , - pstrUsageACExpand , - pstrUsageACExpandAll , - pstrUsageACCollapse , - pstrUsageACCollapseAll , - pstrUsageACPrintPreview , - pstrUsageACPasteSpecial , - pstrUsageACInsertMode , - pstrUsageACDelete , - pstrUsageACLock , - pstrUsageACUnlock , - pstrUsageACProtect , - pstrUsageACUnprotect , - pstrUsageACAttachComment , - pstrUsageACDeleteComment , - pstrUsageACViewComment , - pstrUsageACSelectWord , - pstrUsageACSelectSentence , - pstrUsageACSelectParagraph , - pstrUsageACSelectColumn , - pstrUsageACSelectRow , - pstrUsageACSelectTable , - pstrUsageACSelectObject , - pstrUsageACRedoRepeat , - pstrUsageACSort , - pstrUsageACSortAscending , - pstrUsageACSortDescending , - pstrUsageACFilter , - pstrUsageACSetClock , - pstrUsageACViewClock , - pstrUsageACSelectTimeZone , - pstrUsageACEditTimeZone , - pstrUsageACSetAlarm , - pstrUsageACClearAlarm , - pstrUsageACSnoozeAlarm , - pstrUsageACResetAlarm , - pstrUsageACSyncronize , - pstrUsageACSendReceive , - pstrUsageACSendTo , - pstrUsageACReply , - pstrUsageACReplyAll , - pstrUsageACForwardMessage , - pstrUsageACSend , - pstrUsageACAttachFile , - pstrUsageACUpload , - pstrUsageACDownload , - pstrUsageACSetBorders , - pstrUsageACInsertRow , - pstrUsageACInsertColumn , - pstrUsageACInsertFile , - pstrUsageACInsertPicture , - pstrUsageACInsertObject , - pstrUsageACInsertSymbol , - pstrUsageACSaveAndClose , - pstrUsageACRename , - pstrUsageACMerge , - pstrUsageACSplit , - pstrUsageACDistributeHorizontaly , - pstrUsageACDistributeVerticaly -}; -const char *ReportDescParserBase::digitTitles0[] PROGMEM = -{ - pstrUsageDigitizer , - pstrUsagePen , - pstrUsageLightPen , - pstrUsageTouchScreen , - pstrUsageTouchPad , - pstrUsageWhiteBoard , - pstrUsageCoordinateMeasuringMachine , - pstrUsage3DDigitizer , - pstrUsageStereoPlotter , - pstrUsageArticulatedArm , - pstrUsageArmature , - pstrUsageMultiplePointDigitizer , - pstrUsageFreeSpaceWand -}; -const char *ReportDescParserBase::digitTitles1[] PROGMEM = -{ - pstrUsageStylus , - pstrUsagePuck , - pstrUsageFinger - -}; -const char *ReportDescParserBase::digitTitles2[] PROGMEM = -{ - pstrUsageTipPressure , - pstrUsageBarrelPressure , - pstrUsageInRange , - pstrUsageTouch , - pstrUsageUntouch , - pstrUsageTap , - pstrUsageQuality , - pstrUsageDataValid , - pstrUsageTransducerIndex , - pstrUsageTabletFunctionKeys , - pstrUsageProgramChangeKeys , - pstrUsageBatteryStrength , - pstrUsageInvert , - pstrUsageXTilt , - pstrUsageYTilt , - pstrUsageAzimuth , - pstrUsageAltitude , - pstrUsageTwist , - pstrUsageTipSwitch , - pstrUsageSecondaryTipSwitch , - pstrUsageBarrelSwitch , - pstrUsageEraser , - pstrUsageTabletPick -}; -const char *ReportDescParserBase::aplphanumTitles0[] PROGMEM = -{ - pstrUsageAlphanumericDisplay, - pstrUsageBitmappedDisplay -}; -const char *ReportDescParserBase::aplphanumTitles1[] PROGMEM = -{ - pstrUsageDisplayAttributesReport , - pstrUsageASCIICharacterSet , - pstrUsageDataReadBack , - pstrUsageFontReadBack , - pstrUsageDisplayControlReport , - pstrUsageClearDisplay , - pstrUsageDisplayEnable , - pstrUsageScreenSaverDelay , - pstrUsageScreenSaverEnable , - pstrUsageVerticalScroll , - pstrUsageHorizontalScroll , - pstrUsageCharacterReport , - pstrUsageDisplayData , - pstrUsageDisplayStatus , - pstrUsageStatusNotReady , - pstrUsageStatusReady , - pstrUsageErrorNotALoadableCharacter , - pstrUsageErrorFotDataCanNotBeRead , - pstrUsageCursorPositionReport , - pstrUsageRow , - pstrUsageColumn , - pstrUsageRows , - pstrUsageColumns , - pstrUsageCursorPixelPosition , - pstrUsageCursorMode , - pstrUsageCursorEnable , - pstrUsageCursorBlink , - pstrUsageFontReport , - pstrUsageFontData , - pstrUsageCharacterWidth , - pstrUsageCharacterHeight , - pstrUsageCharacterSpacingHorizontal , - pstrUsageCharacterSpacingVertical , - pstrUsageUnicodeCharset , - pstrUsageFont7Segment , - pstrUsage7SegmentDirectMap , - pstrUsageFont14Segment , - pstrUsage14SegmentDirectMap , - pstrUsageDisplayBrightness , - pstrUsageDisplayContrast , - pstrUsageCharacterAttribute , - pstrUsageAttributeReadback , - pstrUsageAttributeData , - pstrUsageCharAttributeEnhance , - pstrUsageCharAttributeUnderline , - pstrUsageCharAttributeBlink -}; -const char *ReportDescParserBase::aplphanumTitles2[] PROGMEM = -{ - pstrUsageBitmapSizeX , - pstrUsageBitmapSizeY , - pstrUsagePageReserved , - pstrUsageBitDepthFormat , - pstrUsageDisplayOrientation , - pstrUsagePaletteReport , - pstrUsagePaletteDataSize , - pstrUsagePaletteDataOffset , - pstrUsagePaletteData , - pstrUsageBlitReport , - pstrUsageBlitRectangleX1 , - pstrUsageBlitRectangleY1 , - pstrUsageBlitRectangleX2 , - pstrUsageBlitRectangleY2 , - pstrUsageBlitData , - pstrUsageSoftButton , - pstrUsageSoftButtonID , - pstrUsageSoftButtonSide , - pstrUsageSoftButtonOffset1 , - pstrUsageSoftButtonOffset2 , - pstrUsageSoftButtonReport -}; -const char *ReportDescParserBase::medInstrTitles0[] PROGMEM = -{ - pstrUsageVCRAcquisition , - pstrUsageFreezeThaw , - pstrUsageClipStore , - pstrUsageUpdate , - pstrUsageNext , - pstrUsageSave , - pstrUsagePrint , - pstrUsageMicrophoneEnable -}; -const char *ReportDescParserBase::medInstrTitles1[] PROGMEM = -{ - pstrUsageCine , - pstrUsageTransmitPower , - pstrUsageVolume , - pstrUsageFocus , - pstrUsageDepth -}; -const char *ReportDescParserBase::medInstrTitles2[] PROGMEM = -{ - pstrUsageSoftStepPrimary , - pstrUsageSoftStepSecondary -}; -const char *ReportDescParserBase::medInstrTitles3[] PROGMEM = -{ - pstrUsageZoomSelect , - pstrUsageZoomAdjust , - pstrUsageSpectralDopplerModeSelect , - pstrUsageSpectralDopplerModeAdjust , - pstrUsageColorDopplerModeSelect , - pstrUsageColorDopplerModeAdjust , - pstrUsageMotionModeSelect , - pstrUsageMotionModeAdjust , - pstrUsage2DModeSelect , - pstrUsage2DModeAdjust -}; -const char *ReportDescParserBase::medInstrTitles4[] PROGMEM = -{ - pstrUsageSoftControlSelect , - pstrUsageSoftControlAdjust -}; - -void ReportDescParserBase::Parse(const uint16_t len, const uint8_t *pbuf, const uint16_t &offset) -{ - uint16_t cntdn = (uint16_t)len; - uint8_t *p = (uint8_t*)pbuf; - - - totalSize = 0; - - while(cntdn) - { - //Serial.println(""); - //PrintHex(offset + len - cntdn); - //Serial.print(":"); - - ParseItem(&p, &cntdn); - - //if (ParseItem(&p, &cntdn)) - // return; - } - //USBTRACE2("Total:", totalSize); -} - -void ReportDescParserBase::PrintValue(uint8_t *p, uint8_t len) -{ - Notify(PSTR("(")); - for (; len; p++, len--) - PrintHex(*p); - Notify(PSTR(")")); -} - -void ReportDescParserBase::PrintByteValue(uint8_t data) -{ - Notify(PSTR("(")); - PrintHex(data); - Notify(PSTR(")")); -} - -void ReportDescParserBase::PrintItemTitle(uint8_t prefix) -{ - switch (prefix & (TYPE_MASK | TAG_MASK)) - { - case (TYPE_GLOBAL | TAG_GLOBAL_PUSH): - Notify(PSTR("\r\nPush")); - break; - case (TYPE_GLOBAL | TAG_GLOBAL_POP): - Notify(PSTR("\r\nPop")); - break; - case (TYPE_GLOBAL | TAG_GLOBAL_USAGEPAGE): - Notify(PSTR("\r\nUsage Page")); - break; - case (TYPE_GLOBAL | TAG_GLOBAL_LOGICALMIN): - Notify(PSTR("\r\nLogical Min")); - break; - case (TYPE_GLOBAL | TAG_GLOBAL_LOGICALMAX): - Notify(PSTR("\r\nLogical Max")); - break; - case (TYPE_GLOBAL | TAG_GLOBAL_PHYSMIN): - Notify(PSTR("\r\nPhysical Min")); - break; - case (TYPE_GLOBAL | TAG_GLOBAL_PHYSMAX): - Notify(PSTR("\r\nPhysical Max")); - break; - case (TYPE_GLOBAL | TAG_GLOBAL_UNITEXP): - Notify(PSTR("\r\nUnit Exp")); - break; - case (TYPE_GLOBAL | TAG_GLOBAL_UNIT): - Notify(PSTR("\r\nUnit")); - break; - case (TYPE_GLOBAL | TAG_GLOBAL_REPORTSIZE): - Notify(PSTR("\r\nReport Size")); - break; - case (TYPE_GLOBAL | TAG_GLOBAL_REPORTCOUNT): - Notify(PSTR("\r\nReport Count")); - break; - case (TYPE_GLOBAL | TAG_GLOBAL_REPORTID): - Notify(PSTR("\r\nReport Id")); - break; - case (TYPE_LOCAL | TAG_LOCAL_USAGE): - Notify(PSTR("\r\nUsage")); - break; - case (TYPE_LOCAL | TAG_LOCAL_USAGEMIN): - Notify(PSTR("\r\nUsage Min")); - break; - case (TYPE_LOCAL | TAG_LOCAL_USAGEMAX): - Notify(PSTR("\r\nUsage Max")); - break; - case (TYPE_MAIN | TAG_MAIN_COLLECTION): - Notify(PSTR("\r\nCollection")); - break; - case (TYPE_MAIN | TAG_MAIN_ENDCOLLECTION): - Notify(PSTR("\r\nEnd Collection")); - break; - case (TYPE_MAIN | TAG_MAIN_INPUT): - Notify(PSTR("\r\nInput")); - break; - case (TYPE_MAIN | TAG_MAIN_OUTPUT): - Notify(PSTR("\r\nOutput")); - break; - case (TYPE_MAIN | TAG_MAIN_FEATURE): - Notify(PSTR("\r\nFeature")); - break; - } // switch (**pp & (TYPE_MASK | TAG_MASK)) -} -uint8_t ReportDescParserBase::ParseItem(uint8_t **pp, uint16_t *pcntdn) -{ - uint8_t ret = enErrorSuccess; - - switch (itemParseState) - { - case 0: - if (**pp == HID_LONG_ITEM_PREFIX) - USBTRACE("\r\nLONG\r\n"); - else - { - uint8_t size = ((**pp) & DATA_SIZE_MASK); - - itemPrefix = (**pp); - itemSize = 1 + ((size == DATA_SIZE_4) ? 4 : size); - - PrintItemTitle(itemPrefix); - } - (*pp) ++; - (*pcntdn) --; - itemSize --; - itemParseState = 1; - - if (!itemSize) - break; - - if (!pcntdn) - return enErrorIncomplete; - case 1: - //USBTRACE2("\r\niSz:",itemSize); - - theBuffer.valueSize = itemSize; - valParser.Initialize(&theBuffer); - itemParseState = 2; - case 2: - if (!valParser.Parse(pp, pcntdn)) - return enErrorIncomplete; - itemParseState = 3; - case 3: - { - uint8_t data = *((uint8_t*)varBuffer); - - switch (itemPrefix & (TYPE_MASK | TAG_MASK)) - { - case (TYPE_LOCAL | TAG_LOCAL_USAGE): - if (pfUsage) - if (theBuffer.valueSize > 1) - pfUsage(*((uint16_t*)varBuffer)); - else - pfUsage(data); - break; - case (TYPE_GLOBAL | TAG_GLOBAL_REPORTSIZE): - rptSize = data; - PrintByteValue(data); - break; - case (TYPE_GLOBAL | TAG_GLOBAL_REPORTCOUNT): - rptCount = data; - PrintByteValue(data); - break; - case (TYPE_GLOBAL | TAG_GLOBAL_LOGICALMIN): - case (TYPE_GLOBAL | TAG_GLOBAL_LOGICALMAX): - case (TYPE_GLOBAL | TAG_GLOBAL_PHYSMIN): - case (TYPE_GLOBAL | TAG_GLOBAL_PHYSMAX): - case (TYPE_GLOBAL | TAG_GLOBAL_REPORTID): - case (TYPE_LOCAL | TAG_LOCAL_USAGEMIN): - case (TYPE_LOCAL | TAG_LOCAL_USAGEMAX): - case (TYPE_GLOBAL | TAG_GLOBAL_UNITEXP): - case (TYPE_GLOBAL | TAG_GLOBAL_UNIT): - PrintValue(varBuffer, theBuffer.valueSize); - break; - case (TYPE_GLOBAL | TAG_GLOBAL_PUSH): - case (TYPE_GLOBAL | TAG_GLOBAL_POP): - break; - case (TYPE_GLOBAL | TAG_GLOBAL_USAGEPAGE): - SetUsagePage(data); - PrintUsagePage(data); - PrintByteValue(data); - break; - case (TYPE_MAIN | TAG_MAIN_COLLECTION): - case (TYPE_MAIN | TAG_MAIN_ENDCOLLECTION): - switch (data) - { - case 0x00: - Notify(PSTR(" Physical")); - break; - case 0x01: - Notify(PSTR(" Application")); - break; - case 0x02: - Notify(PSTR(" Logical")); - break; - case 0x03: - Notify(PSTR(" Report")); - break; - case 0x04: - Notify(PSTR(" Named Array")); - break; - case 0x05: - Notify(PSTR(" Usage Switch")); - break; - case 0x06: - Notify(PSTR(" Usage Modifier")); - break; - default: - Notify(PSTR(" Vendor Defined(")); - PrintHex(data); - Notify(PSTR(")")); - } - break; - case (TYPE_MAIN | TAG_MAIN_INPUT): - case (TYPE_MAIN | TAG_MAIN_OUTPUT): - case (TYPE_MAIN | TAG_MAIN_FEATURE): - totalSize += (uint16_t)rptSize * (uint16_t)rptCount; - rptSize = 0; - rptCount = 0; - Notify(PSTR("(")); - PrintBin(data); - Notify(PSTR(")")); - break; - } // switch (**pp & (TYPE_MASK | TAG_MASK)) - } - } // switch (itemParseState) - itemParseState = 0; - return enErrorSuccess; -} - -ReportDescParserBase::UsagePageFunc ReportDescParserBase::usagePageFunctions[] /*PROGMEM*/ = -{ - &ReportDescParserBase::PrintGenericDesktopPageUsage, - &ReportDescParserBase::PrintSimulationControlsPageUsage, - &ReportDescParserBase::PrintVRControlsPageUsage, - &ReportDescParserBase::PrintSportsControlsPageUsage, - &ReportDescParserBase::PrintGameControlsPageUsage, - &ReportDescParserBase::PrintGenericDeviceControlsPageUsage, - NULL, // Keyboard/Keypad - &ReportDescParserBase::PrintLEDPageUsage, - &ReportDescParserBase::PrintButtonPageUsage, - &ReportDescParserBase::PrintOrdinalPageUsage, - &ReportDescParserBase::PrintTelephonyPageUsage, - &ReportDescParserBase::PrintConsumerPageUsage, - &ReportDescParserBase::PrintDigitizerPageUsage, - NULL, // Reserved - NULL, // PID - NULL // Unicode -}; - -void ReportDescParserBase::SetUsagePage(uint16_t page) -{ - pfUsage = NULL; - - if (page > 0x00 && page < 0x11) - pfUsage = /*(UsagePageFunc)pgm_read_word*/(usagePageFunctions[page - 1]); - //else if (page > 0x7f && page < 0x84) - // Notify(pstrUsagePageMonitor); - //else if (page > 0x83 && page < 0x8c) - // Notify(pstrUsagePagePower); - //else if (page > 0x8b && page < 0x92) - // Notify((char*)pgm_read_word(&usagePageTitles1[page - 0x8c])); - //else if (page > 0xfeff && page <= 0xffff) - // Notify(pstrUsagePageVendorDefined); - else - switch (page) - { - case 0x14: - pfUsage = &ReportDescParserBase::PrintAlphanumDisplayPageUsage; - break; - case 0x40: - pfUsage = &ReportDescParserBase::PrintMedicalInstrumentPageUsage; - break; - } -} - -void ReportDescParserBase::PrintUsagePage(uint16_t page) -{ - Notify(pstrSpace); - - if (page > 0x00 && page < 0x11) - Notify((char*)pgm_read_word(&usagePageTitles0[page - 1])); - else if (page > 0x7f && page < 0x84) - Notify(pstrUsagePageMonitor); - else if (page > 0x83 && page < 0x8c) - Notify(pstrUsagePagePower); - else if (page > 0x8b && page < 0x92) - Notify((char*)pgm_read_word(&usagePageTitles1[page - 0x8c])); - else if (page > 0xfeff && page <= 0xffff) - Notify(pstrUsagePageVendorDefined); - else - switch (page) - { - case 0x14: - Notify(pstrUsagePageAlphaNumericDisplay); - break; - case 0x40: - Notify(pstrUsagePageMedicalInstruments); - break; - default: - Notify(pstrUsagePageUndefined); - } -} - -void ReportDescParserBase::PrintButtonPageUsage(uint16_t usage) -{ - Notify(pstrSpace); - Notify(PSTR("Btn")); - Serial.print(usage, HEX); -} - -void ReportDescParserBase::PrintOrdinalPageUsage(uint16_t usage) -{ - Notify(pstrSpace); - Notify(PSTR("Inst")); - Serial.print(usage, DEC); -} - -void ReportDescParserBase::PrintGenericDesktopPageUsage(uint16_t usage) -{ - Notify(pstrSpace); - - if (usage > 0x00 && usage < 0x0a) - Notify((char*)pgm_read_word(&genDesktopTitles0[usage - 1])); - else if (usage > 0x2f && usage < 0x49) - Notify((char*)pgm_read_word(&genDesktopTitles1[usage - 0x30])); - else if (usage > 0x7f && usage < 0x94) - Notify((char*)pgm_read_word(&genDesktopTitles2[usage - 0x80])); - else if (usage > 0x9f && usage < 0xa9) - Notify((char*)pgm_read_word(&genDesktopTitles3[usage - 0xa0])); - else if (usage > 0xaf && usage < 0xb8) - Notify((char*)pgm_read_word(&genDesktopTitles4[usage - 0xb0])); - else - Notify(pstrUsagePageUndefined); -} - -void ReportDescParserBase::PrintSimulationControlsPageUsage(uint16_t usage) -{ - Notify(pstrSpace); - - if (usage > 0x00 && usage < 0x0d) - Notify((char*)pgm_read_word(&simuTitles0[usage - 1])); - else if (usage > 0x1f && usage < 0x26) - Notify((char*)pgm_read_word(&simuTitles1[usage - 0x20])); - else if (usage > 0xaf && usage < 0xd1) - Notify((char*)pgm_read_word(&simuTitles2[usage - 0xb0])); - else - Notify(pstrUsagePageUndefined); -} - -void ReportDescParserBase::PrintVRControlsPageUsage(uint16_t usage) -{ - Notify(pstrSpace); - - if (usage > 0x00 && usage < 0x0b) - Notify((char*)pgm_read_word(&vrTitles0[usage - 1])); - else if (usage > 0x1f && usage < 0x22) - Notify((char*)pgm_read_word(&vrTitles1[usage - 0x20])); - else - Notify(pstrUsagePageUndefined); -} - -void ReportDescParserBase::PrintSportsControlsPageUsage(uint16_t usage) -{ - Notify(pstrSpace); - - if (usage > 0x00 && usage < 0x05) - Notify((char*)pgm_read_word(&sportsCtrlTitles0[usage - 1])); - else if (usage > 0x2f && usage < 0x3a) - Notify((char*)pgm_read_word(&sportsCtrlTitles1[usage - 0x30])); - else if (usage > 0x4f && usage < 0x64) - Notify((char*)pgm_read_word(&sportsCtrlTitles2[usage - 0x50])); - else - Notify(pstrUsagePageUndefined); -} - -void ReportDescParserBase::PrintGameControlsPageUsage(uint16_t usage) -{ - Notify(pstrSpace); - - if (usage > 0x00 && usage < 0x04) - Notify((char*)pgm_read_word(&gameTitles0[usage - 1])); - else if (usage > 0x1f && usage < 0x3a) - Notify((char*)pgm_read_word(&gameTitles1[usage - 0x20])); - else - Notify(pstrUsagePageUndefined); -} - -void ReportDescParserBase::PrintGenericDeviceControlsPageUsage(uint16_t usage) -{ - Notify(pstrSpace); - - if (usage > 0x1f && usage < 0x27) - Notify((char*)pgm_read_word(&genDevCtrlTitles[usage - 0x20])); - else - Notify(pstrUsagePageUndefined); -} - -void ReportDescParserBase::PrintLEDPageUsage(uint16_t usage) -{ - Notify(pstrSpace); - - if (usage > 0x00 && usage < 0x4e) - Notify((char*)pgm_read_word(&ledTitles[usage - 1])); - else - Notify(pstrUsagePageUndefined); -} - -void ReportDescParserBase::PrintTelephonyPageUsage(uint16_t usage) -{ - Notify(pstrSpace); - - if (usage > 0x00 && usage < 0x08) - Notify((char*)pgm_read_word(&telTitles0[usage - 1])); - else if (usage > 0x1f && usage < 0x32) - Notify((char*)pgm_read_word(&telTitles1[usage - 0x1f])); - else if (usage > 0x4f && usage < 0x54) - Notify((char*)pgm_read_word(&telTitles2[usage - 0x4f])); - else if (usage > 0x6f && usage < 0x75) - Notify((char*)pgm_read_word(&telTitles3[usage - 0x6f])); - else if (usage > 0x8f && usage < 0x9f) - Notify((char*)pgm_read_word(&telTitles4[usage - 0x8f])); - else if (usage > 0xaf && usage < 0xc0) - Notify((char*)pgm_read_word(&telTitles5[usage - 0xaf])); - else - Notify(pstrUsagePageUndefined); -} - -void ReportDescParserBase::PrintConsumerPageUsage(uint16_t usage) -{ - Notify(pstrSpace); - - if (usage > 0x00 && usage < 0x07) - Notify((char*)pgm_read_word(&consTitles0[usage - 1])); - else if (usage > 0x1f && usage < 0x23) - Notify((char*)pgm_read_word(&consTitles1[usage - 0x1f])); - else if (usage > 0x2f && usage < 0x37) - Notify((char*)pgm_read_word(&consTitles2[usage - 0x2f])); - else if (usage > 0x3f && usage < 0x49) - Notify((char*)pgm_read_word(&consTitles3[usage - 0x3f])); - else if (usage > 0x5f && usage < 0x67) - Notify((char*)pgm_read_word(&consTitles4[usage - 0x5f])); - else if (usage > 0x7f && usage < 0xa5) - Notify((char*)pgm_read_word(&consTitles5[usage - 0x7f])); - else if (usage > 0xaf && usage < 0xcf) - Notify((char*)pgm_read_word(&consTitles6[usage - 0xaf])); - else if (usage > 0xdf && usage < 0xeb) - Notify((char*)pgm_read_word(&consTitles7[usage - 0xdf])); - else if (usage > 0xef && usage < 0xf6) - Notify((char*)pgm_read_word(&consTitles8[usage - 0xef])); - else if (usage > 0xff && usage < 0x10e) - Notify((char*)pgm_read_word(&consTitles9[usage - 0xff])); - else if (usage > 0x14f && usage < 0x156) - Notify((char*)pgm_read_word(&consTitlesA[usage - 0x14f])); - else if (usage > 0x15f && usage < 0x16b) - Notify((char*)pgm_read_word(&consTitlesB[usage - 0x15f])); - else if (usage > 0x16f && usage < 0x175) - Notify((char*)pgm_read_word(&consTitlesC[usage - 0x16f])); - else if (usage > 0x17f && usage < 0x1c8) - Notify((char*)pgm_read_word(&consTitlesD[usage - 0x17f])); - else if (usage > 0x1ff && usage < 0x29d) - Notify((char*)pgm_read_word(&consTitlesE[usage - 0x1ff])); - else - Notify(pstrUsagePageUndefined); -} - -void ReportDescParserBase::PrintDigitizerPageUsage(uint16_t usage) -{ - Notify(pstrSpace); - - if (usage > 0x00 && usage < 0x0e) - Notify((char*)pgm_read_word(&digitTitles0[usage - 1])); - else if (usage > 0x1f && usage < 0x23) - Notify((char*)pgm_read_word(&digitTitles1[usage - 0x1f])); - else if (usage > 0x2f && usage < 0x47) - Notify((char*)pgm_read_word(&digitTitles2[usage - 0x2f])); - else - Notify(pstrUsagePageUndefined); -} - -void ReportDescParserBase::PrintAlphanumDisplayPageUsage(uint16_t usage) -{ - Notify(pstrSpace); - - if (usage > 0x00 && usage < 0x03) - Notify((char*)pgm_read_word(&aplphanumTitles0[usage - 1])); - else if (usage > 0x1f && usage < 0x4e) - Notify((char*)pgm_read_word(&aplphanumTitles1[usage - 0x1f])); - else if (usage > 0x7f && usage < 0x96) - Notify((char*)pgm_read_word(&digitTitles2[usage - 0x80])); - else - Notify(pstrUsagePageUndefined); -} - -void ReportDescParserBase::PrintMedicalInstrumentPageUsage(uint16_t usage) -{ - Notify(pstrSpace); - - if (usage == 1) - Notify(pstrUsageMedicalUltrasound); - else if (usage > 0x1f && usage < 0x28) - Notify((char*)pgm_read_word(&medInstrTitles0[usage - 0x1f])); - else if (usage > 0x3f && usage < 0x45) - Notify((char*)pgm_read_word(&medInstrTitles1[usage - 0x40])); - else if (usage > 0x5f && usage < 0x62) - Notify((char*)pgm_read_word(&medInstrTitles2[usage - 0x60])); - else if (usage == 0x70) - Notify(pstrUsageDepthGainCompensation); - else if (usage > 0x7f && usage < 0x8a) - Notify((char*)pgm_read_word(&medInstrTitles3[usage - 0x80])); - else if (usage > 0x9f && usage < 0xa2) - Notify((char*)pgm_read_word(&medInstrTitles4[usage - 0xa0])); - else - Notify(pstrUsagePageUndefined); -} - - - - - -uint8_t ReportDescParser2::ParseItem(uint8_t **pp, uint16_t *pcntdn) -{ - uint8_t ret = enErrorSuccess; - - switch (itemParseState) - { - case 0: - if (**pp == HID_LONG_ITEM_PREFIX) - USBTRACE("\r\nLONG\r\n"); - else - { - uint8_t size = ((**pp) & DATA_SIZE_MASK); - itemPrefix = (**pp); - itemSize = 1 + ((size == DATA_SIZE_4) ? 4 : size); - } - (*pp) ++; - (*pcntdn) --; - itemSize --; - itemParseState = 1; - - if (!itemSize) - break; - - if (!pcntdn) - return enErrorIncomplete; - case 1: - theBuffer.valueSize = itemSize; - valParser.Initialize(&theBuffer); - itemParseState = 2; - case 2: - if (!valParser.Parse(pp, pcntdn)) - return enErrorIncomplete; - itemParseState = 3; - case 3: - { - uint8_t data = *((uint8_t*)varBuffer); - - switch (itemPrefix & (TYPE_MASK | TAG_MASK)) - { - case (TYPE_LOCAL | TAG_LOCAL_USAGE): - if (pfUsage) - if (theBuffer.valueSize > 1) - pfUsage(*((uint16_t*)varBuffer)); - else - pfUsage(data); - break; - case (TYPE_GLOBAL | TAG_GLOBAL_REPORTSIZE): - rptSize = data; - break; - case (TYPE_GLOBAL | TAG_GLOBAL_REPORTCOUNT): - rptCount = data; - break; - case (TYPE_GLOBAL | TAG_GLOBAL_REPORTID): - rptId = data; - break; - case (TYPE_LOCAL | TAG_LOCAL_USAGEMIN): - useMin = data; - break; - case (TYPE_LOCAL | TAG_LOCAL_USAGEMAX): - useMax = data; - break; - case (TYPE_GLOBAL | TAG_GLOBAL_USAGEPAGE): - SetUsagePage(data); - break; - case (TYPE_MAIN | TAG_MAIN_OUTPUT): - case (TYPE_MAIN | TAG_MAIN_FEATURE): - rptSize = 0; - rptCount = 0; - useMin = 0; - useMax = 0; - break; - case (TYPE_MAIN | TAG_MAIN_INPUT): - OnInputItem(data); - - totalSize += (uint16_t)rptSize * (uint16_t)rptCount; - - rptSize = 0; - rptCount = 0; - useMin = 0; - useMax = 0; - break; - } // switch (**pp & (TYPE_MASK | TAG_MASK)) - } - } // switch (itemParseState) - itemParseState = 0; - return enErrorSuccess; -} - -void ReportDescParser2::OnInputItem(uint8_t itm) -{ - uint8_t byte_offset = (totalSize >> 3); // calculate offset to the next unhandled byte i = (int)(totalCount / 8); - uint32_t tmp = (byte_offset << 3); - uint8_t bit_offset = totalSize - tmp; // number of bits in the current byte already handled - uint8_t *p = pBuf + byte_offset; // current byte pointer - - if (bit_offset) - *p >>= bit_offset; - - uint8_t usage = useMin; - - bool print_usemin_usemax = ( (useMin < useMax) && ((itm & 3) == 2) && pfUsage) ? true : false; - - uint8_t bits_of_byte = 8; - - // for each field in field array defined by rptCount - for (uint8_t field=0; field bits_of_byte) ? bits_of_byte : bits_left; - - result.dwResult <<= bits_to_copy; // Result buffer is shifted by the number of bits to be copied into it - - uint8_t val = *p; - - val >>= (8 - bits_of_byte); // Shift by the number of bits already processed - - mask = 0; - - for (uint8_t j=bits_to_copy; j; j--) - { - mask <<= 1; - mask |= 1; - } - - result.bResult[0] = (result.bResult[0] | (val & mask)); - - bits_of_byte -= bits_to_copy; - - if (bits_of_byte < 1) - { - bits_of_byte = 8; - p ++; - } - } - PrintByteValue(result.dwResult); - } - Serial.println(""); -} - -void UniversalReportParser::Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf) -{ - ReportDescParser2 prs(len, buf); - - uint8_t ret = hid->GetReportDescr(0, &prs); - - if (ret) - ErrorMessage(PSTR("GetReportDescr-2"), ret); +#include "hidescriptorparser.h" + +const char * const ReportDescParserBase::usagePageTitles0[] PROGMEM ={ + pstrUsagePageGenericDesktopControls, + pstrUsagePageSimulationControls, + pstrUsagePageVRControls, + pstrUsagePageSportControls, + pstrUsagePageGameControls, + pstrUsagePageGenericDeviceControls, + pstrUsagePageKeyboardKeypad, + pstrUsagePageLEDs, + pstrUsagePageButton, + pstrUsagePageOrdinal, + pstrUsagePageTelephone, + pstrUsagePageConsumer, + pstrUsagePageDigitizer, + pstrUsagePagePID, + pstrUsagePageUnicode +}; + +const char * const ReportDescParserBase::usagePageTitles1[] PROGMEM ={ + pstrUsagePageBarCodeScanner, + pstrUsagePageScale, + pstrUsagePageMSRDevices, + pstrUsagePagePointOfSale, + pstrUsagePageCameraControl, + pstrUsagePageArcade +}; +const char * const ReportDescParserBase::genDesktopTitles0[] PROGMEM ={ + pstrUsagePointer, + pstrUsageMouse, + pstrUsageJoystick, + pstrUsageGamePad, + pstrUsageKeyboard, + pstrUsageKeypad, + pstrUsageMultiAxisController, + pstrUsageTabletPCSystemControls + +}; +const char * const ReportDescParserBase::genDesktopTitles1[] PROGMEM ={ + pstrUsageX, + pstrUsageY, + pstrUsageZ, + pstrUsageRx, + pstrUsageRy, + pstrUsageRz, + pstrUsageSlider, + pstrUsageDial, + pstrUsageWheel, + pstrUsageHatSwitch, + pstrUsageCountedBuffer, + pstrUsageByteCount, + pstrUsageMotionWakeup, + pstrUsageStart, + pstrUsageSelect, + pstrUsagePageReserved, + pstrUsageVx, + pstrUsageVy, + pstrUsageVz, + pstrUsageVbrx, + pstrUsageVbry, + pstrUsageVbrz, + pstrUsageVno, + pstrUsageFeatureNotification, + pstrUsageResolutionMultiplier +}; +const char * const ReportDescParserBase::genDesktopTitles2[] PROGMEM ={ + pstrUsageSystemControl, + pstrUsageSystemPowerDown, + pstrUsageSystemSleep, + pstrUsageSystemWakeup, + pstrUsageSystemContextMenu, + pstrUsageSystemMainMenu, + pstrUsageSystemAppMenu, + pstrUsageSystemMenuHelp, + pstrUsageSystemMenuExit, + pstrUsageSystemMenuSelect, + pstrUsageSystemMenuRight, + pstrUsageSystemMenuLeft, + pstrUsageSystemMenuUp, + pstrUsageSystemMenuDown, + pstrUsageSystemColdRestart, + pstrUsageSystemWarmRestart, + pstrUsageDPadUp, + pstrUsageDPadDown, + pstrUsageDPadRight, + pstrUsageDPadLeft +}; +const char * const ReportDescParserBase::genDesktopTitles3[] PROGMEM ={ + pstrUsageSystemDock, + pstrUsageSystemUndock, + pstrUsageSystemSetup, + pstrUsageSystemBreak, + pstrUsageSystemDebuggerBreak, + pstrUsageApplicationBreak, + pstrUsageApplicationDebuggerBreak, + pstrUsageSystemSpeakerMute, + pstrUsageSystemHibernate +}; +const char * const ReportDescParserBase::genDesktopTitles4[] PROGMEM ={ + pstrUsageSystemDisplayInvert, + pstrUsageSystemDisplayInternal, + pstrUsageSystemDisplayExternal, + pstrUsageSystemDisplayBoth, + pstrUsageSystemDisplayDual, + pstrUsageSystemDisplayToggleIntExt, + pstrUsageSystemDisplaySwapPriSec, + pstrUsageSystemDisplayLCDAutoscale +}; +const char * const ReportDescParserBase::simuTitles0[] PROGMEM ={ + pstrUsageFlightSimulationDevice, + pstrUsageAutomobileSimulationDevice, + pstrUsageTankSimulationDevice, + pstrUsageSpaceshipSimulationDevice, + pstrUsageSubmarineSimulationDevice, + pstrUsageSailingSimulationDevice, + pstrUsageMotocicleSimulationDevice, + pstrUsageSportsSimulationDevice, + pstrUsageAirplaneSimulationDevice, + pstrUsageHelicopterSimulationDevice, + pstrUsageMagicCarpetSimulationDevice, + pstrUsageBicycleSimulationDevice +}; +const char * const ReportDescParserBase::simuTitles1[] PROGMEM ={ + pstrUsageFlightControlStick, + pstrUsageFlightStick, + pstrUsageCyclicControl, + pstrUsageCyclicTrim, + pstrUsageFlightYoke, + pstrUsageTrackControl +}; +const char * const ReportDescParserBase::simuTitles2[] PROGMEM ={ + pstrUsageAileron, + pstrUsageAileronTrim, + pstrUsageAntiTorqueControl, + pstrUsageAutopilotEnable, + pstrUsageChaffRelease, + pstrUsageCollectiveControl, + pstrUsageDiveBrake, + pstrUsageElectronicCountermeasures, + pstrUsageElevator, + pstrUsageElevatorTrim, + pstrUsageRudder, + pstrUsageThrottle, + pstrUsageFlightCommunications, + pstrUsageFlareRelease, + pstrUsageLandingGear, + pstrUsageToeBrake, + pstrUsageTrigger, + pstrUsageWeaponsArm, + pstrUsageWeaponsSelect, + pstrUsageWingFlaps, + pstrUsageAccelerator, + pstrUsageBrake, + pstrUsageClutch, + pstrUsageShifter, + pstrUsageSteering, + pstrUsageTurretDirection, + pstrUsageBarrelElevation, + pstrUsageDivePlane, + pstrUsageBallast, + pstrUsageBicycleCrank, + pstrUsageHandleBars, + pstrUsageFrontBrake, + pstrUsageRearBrake +}; +const char * const ReportDescParserBase::vrTitles0[] PROGMEM ={ + pstrUsageBelt, + pstrUsageBodySuit, + pstrUsageFlexor, + pstrUsageGlove, + pstrUsageHeadTracker, + pstrUsageHeadMountedDisplay, + pstrUsageHandTracker, + pstrUsageOculometer, + pstrUsageVest, + pstrUsageAnimatronicDevice +}; +const char * const ReportDescParserBase::vrTitles1[] PROGMEM ={ + pstrUsageStereoEnable, + pstrUsageDisplayEnable +}; +const char * const ReportDescParserBase::sportsCtrlTitles0[] PROGMEM ={ + pstrUsageBaseballBat, + pstrUsageGolfClub, + pstrUsageRowingMachine, + pstrUsageTreadmill +}; +const char * const ReportDescParserBase::sportsCtrlTitles1[] PROGMEM ={ + pstrUsageOar, + pstrUsageSlope, + pstrUsageRate, + pstrUsageStickSpeed, + pstrUsageStickFaceAngle, + pstrUsageStickHeelToe, + pstrUsageStickFollowThough, + pstrUsageStickTempo, + pstrUsageStickType, + pstrUsageStickHeight +}; +const char * const ReportDescParserBase::sportsCtrlTitles2[] PROGMEM ={ + pstrUsagePutter, + pstrUsage1Iron, + pstrUsage2Iron, + pstrUsage3Iron, + pstrUsage4Iron, + pstrUsage5Iron, + pstrUsage6Iron, + pstrUsage7Iron, + pstrUsage8Iron, + pstrUsage9Iron, + pstrUsage10Iron, + pstrUsage11Iron, + pstrUsageSandWedge, + pstrUsageLoftWedge, + pstrUsagePowerWedge, + pstrUsage1Wood, + pstrUsage3Wood, + pstrUsage5Wood, + pstrUsage7Wood, + pstrUsage9Wood +}; +const char * const ReportDescParserBase::gameTitles0[] PROGMEM ={ + pstrUsage3DGameController, + pstrUsagePinballDevice, + pstrUsageGunDevice +}; +const char * const ReportDescParserBase::gameTitles1[] PROGMEM ={ + pstrUsagePointOfView, + pstrUsageTurnRightLeft, + pstrUsagePitchForwardBackward, + pstrUsageRollRightLeft, + pstrUsageMoveRightLeft, + pstrUsageMoveForwardBackward, + pstrUsageMoveUpDown, + pstrUsageLeanRightLeft, + pstrUsageLeanForwardBackward, + pstrUsageHeightOfPOV, + pstrUsageFlipper, + pstrUsageSecondaryFlipper, + pstrUsageBump, + pstrUsageNewGame, + pstrUsageShootBall, + pstrUsagePlayer, + pstrUsageGunBolt, + pstrUsageGunClip, + pstrUsageGunSelector, + pstrUsageGunSingleShot, + pstrUsageGunBurst, + pstrUsageGunAutomatic, + pstrUsageGunSafety, + pstrUsageGamepadFireJump, + pstrUsageGamepadTrigger +}; +const char * const ReportDescParserBase::genDevCtrlTitles[] PROGMEM ={ + pstrUsageBatteryStrength, + pstrUsageWirelessChannel, + pstrUsageWirelessID, + pstrUsageDiscoverWirelessControl, + pstrUsageSecurityCodeCharEntered, + pstrUsageSecurityCodeCharErased, + pstrUsageSecurityCodeCleared +}; +const char * const ReportDescParserBase::ledTitles[] PROGMEM ={ + pstrUsageNumLock, + pstrUsageCapsLock, + pstrUsageScrollLock, + pstrUsageCompose, + pstrUsageKana, + pstrUsagePower, + pstrUsageShift, + pstrUsageDoNotDisturb, + pstrUsageMute, + pstrUsageToneEnable, + pstrUsageHighCutFilter, + pstrUsageLowCutFilter, + pstrUsageEqualizerEnable, + pstrUsageSoundFieldOn, + pstrUsageSurroundOn, + pstrUsageRepeat, + pstrUsageStereo, + pstrUsageSamplingRateDetect, + pstrUsageSpinning, + pstrUsageCAV, + pstrUsageCLV, + pstrUsageRecordingFormatDetect, + pstrUsageOffHook, + pstrUsageRing, + pstrUsageMessageWaiting, + pstrUsageDataMode, + pstrUsageBatteryOperation, + pstrUsageBatteryOK, + pstrUsageBatteryLow, + pstrUsageSpeaker, + pstrUsageHeadSet, + pstrUsageHold, + pstrUsageMicrophone, + pstrUsageCoverage, + pstrUsageNightMode, + pstrUsageSendCalls, + pstrUsageCallPickup, + pstrUsageConference, + pstrUsageStandBy, + pstrUsageCameraOn, + pstrUsageCameraOff, + pstrUsageOnLine, + pstrUsageOffLine, + pstrUsageBusy, + pstrUsageReady, + pstrUsagePaperOut, + pstrUsagePaperJam, + pstrUsageRemote, + pstrUsageForward, + pstrUsageReverse, + pstrUsageStop, + pstrUsageRewind, + pstrUsageFastForward, + pstrUsagePlay, + pstrUsagePause, + pstrUsageRecord, + pstrUsageError, + pstrUsageSelectedIndicator, + pstrUsageInUseIndicator, + pstrUsageMultiModeIndicator, + pstrUsageIndicatorOn, + pstrUsageIndicatorFlash, + pstrUsageIndicatorSlowBlink, + pstrUsageIndicatorFastBlink, + pstrUsageIndicatorOff, + pstrUsageFlashOnTime, + pstrUsageSlowBlinkOnTime, + pstrUsageSlowBlinkOffTime, + pstrUsageFastBlinkOnTime, + pstrUsageFastBlinkOffTime, + pstrUsageIndicatorColor, + pstrUsageIndicatorRed, + pstrUsageIndicatorGreen, + pstrUsageIndicatorAmber, + pstrUsageGenericIndicator, + pstrUsageSystemSuspend, + pstrUsageExternalPowerConnected +}; +const char * const ReportDescParserBase::telTitles0 [] PROGMEM ={ + pstrUsagePhone, + pstrUsageAnsweringMachine, + pstrUsageMessageControls, + pstrUsageHandset, + pstrUsageHeadset, + pstrUsageTelephonyKeyPad, + pstrUsageProgrammableButton +}; +const char * const ReportDescParserBase::telTitles1 [] PROGMEM ={ + pstrUsageHookSwitch, + pstrUsageFlash, + pstrUsageFeature, + pstrUsageHold, + pstrUsageRedial, + pstrUsageTransfer, + pstrUsageDrop, + pstrUsagePark, + pstrUsageForwardCalls, + pstrUsageAlternateFunction, + pstrUsageLine, + pstrUsageSpeakerPhone, + pstrUsageConference, + pstrUsageRingEnable, + pstrUsageRingSelect, + pstrUsagePhoneMute, + pstrUsageCallerID, + pstrUsageSend +}; +const char * const ReportDescParserBase::telTitles2 [] PROGMEM ={ + pstrUsageSpeedDial, + pstrUsageStoreNumber, + pstrUsageRecallNumber, + pstrUsagePhoneDirectory +}; +const char * const ReportDescParserBase::telTitles3 [] PROGMEM ={ + pstrUsageVoiceMail, + pstrUsageScreenCalls, + pstrUsageDoNotDisturb, + pstrUsageMessage, + pstrUsageAnswerOnOff +}; +const char * const ReportDescParserBase::telTitles4 [] PROGMEM ={ + pstrUsageInsideDialTone, + pstrUsageOutsideDialTone, + pstrUsageInsideRingTone, + pstrUsageOutsideRingTone, + pstrUsagePriorityRingTone, + pstrUsageInsideRingback, + pstrUsagePriorityRingback, + pstrUsageLineBusyTone, + pstrUsageReorderTone, + pstrUsageCallWaitingTone, + pstrUsageConfirmationTone1, + pstrUsageConfirmationTone2, + pstrUsageTonesOff, + pstrUsageOutsideRingback, + pstrUsageRinger +}; +const char * const ReportDescParserBase::telTitles5 [] PROGMEM ={ + pstrUsagePhoneKey0, + pstrUsagePhoneKey1, + pstrUsagePhoneKey2, + pstrUsagePhoneKey3, + pstrUsagePhoneKey4, + pstrUsagePhoneKey5, + pstrUsagePhoneKey6, + pstrUsagePhoneKey7, + pstrUsagePhoneKey8, + pstrUsagePhoneKey9, + pstrUsagePhoneKeyStar, + pstrUsagePhoneKeyPound, + pstrUsagePhoneKeyA, + pstrUsagePhoneKeyB, + pstrUsagePhoneKeyC, + pstrUsagePhoneKeyD +}; +const char * const ReportDescParserBase::consTitles0[] PROGMEM ={ + pstrUsageConsumerControl, + pstrUsageNumericKeyPad, + pstrUsageProgrammableButton, + pstrUsageMicrophone, + pstrUsageHeadphone, + pstrUsageGraphicEqualizer +}; +const char * const ReportDescParserBase::consTitles1[] PROGMEM ={ + pstrUsagePlus10, + pstrUsagePlus100, + pstrUsageAMPM +}; +const char * const ReportDescParserBase::consTitles2[] PROGMEM ={ + pstrUsagePower, + pstrUsageReset, + pstrUsageSleep, + pstrUsageSleepAfter, + pstrUsageSleepMode, + pstrUsageIllumination, + pstrUsageFunctionButtons + +}; +const char * const ReportDescParserBase::consTitles3[] PROGMEM ={ + pstrUsageMenu, + pstrUsageMenuPick, + pstrUsageMenuUp, + pstrUsageMenuDown, + pstrUsageMenuLeft, + pstrUsageMenuRight, + pstrUsageMenuEscape, + pstrUsageMenuValueIncrease, + pstrUsageMenuValueDecrease +}; +const char * const ReportDescParserBase::consTitles4[] PROGMEM ={ + pstrUsageDataOnScreen, + pstrUsageClosedCaption, + pstrUsageClosedCaptionSelect, + pstrUsageVCRTV, + pstrUsageBroadcastMode, + pstrUsageSnapshot, + pstrUsageStill +}; +const char * const ReportDescParserBase::consTitles5[] PROGMEM ={ + pstrUsageSelection, + pstrUsageAssignSelection, + pstrUsageModeStep, + pstrUsageRecallLast, + pstrUsageEnterChannel, + pstrUsageOrderMovie, + pstrUsageChannel, + pstrUsageMediaSelection, + pstrUsageMediaSelectComputer, + pstrUsageMediaSelectTV, + pstrUsageMediaSelectWWW, + pstrUsageMediaSelectDVD, + pstrUsageMediaSelectTelephone, + pstrUsageMediaSelectProgramGuide, + pstrUsageMediaSelectVideoPhone, + pstrUsageMediaSelectGames, + pstrUsageMediaSelectMessages, + pstrUsageMediaSelectCD, + pstrUsageMediaSelectVCR, + pstrUsageMediaSelectTuner, + pstrUsageQuit, + pstrUsageHelp, + pstrUsageMediaSelectTape, + pstrUsageMediaSelectCable, + pstrUsageMediaSelectSatellite, + pstrUsageMediaSelectSecurity, + pstrUsageMediaSelectHome, + pstrUsageMediaSelectCall, + pstrUsageChannelIncrement, + pstrUsageChannelDecrement, + pstrUsageMediaSelectSAP, + pstrUsagePageReserved, + pstrUsageVCRPlus, + pstrUsageOnce, + pstrUsageDaily, + pstrUsageWeekly, + pstrUsageMonthly +}; +const char * const ReportDescParserBase::consTitles6[] PROGMEM ={ + pstrUsagePlay, + pstrUsagePause, + pstrUsageRecord, + pstrUsageFastForward, + pstrUsageRewind, + pstrUsageScanNextTrack, + pstrUsageScanPreviousTrack, + pstrUsageStop, + pstrUsageEject, + pstrUsageRandomPlay, + pstrUsageSelectDisk, + pstrUsageEnterDisk, + pstrUsageRepeat, + pstrUsageTracking, + pstrUsageTrackNormal, + pstrUsageSlowTracking, + pstrUsageFrameForward, + pstrUsageFrameBackwards, + pstrUsageMark, + pstrUsageClearMark, + pstrUsageRepeatFromMark, + pstrUsageReturnToMark, + pstrUsageSearchMarkForward, + pstrUsageSearchMarkBackwards, + pstrUsageCounterReset, + pstrUsageShowCounter, + pstrUsageTrackingIncrement, + pstrUsageTrackingDecrement, + pstrUsageStopEject, + pstrUsagePlayPause, + pstrUsagePlaySkip +}; +const char * const ReportDescParserBase::consTitles7[] PROGMEM ={ + pstrUsageVolume, + pstrUsageBalance, + pstrUsageMute, + pstrUsageBass, + pstrUsageTreble, + pstrUsageBassBoost, + pstrUsageSurroundMode, + pstrUsageLoudness, + pstrUsageMPX, + pstrUsageVolumeIncrement, + pstrUsageVolumeDecrement +}; +const char * const ReportDescParserBase::consTitles8[] PROGMEM ={ + pstrUsageSpeedSelect, + pstrUsagePlaybackSpeed, + pstrUsageStandardPlay, + pstrUsageLongPlay, + pstrUsageExtendedPlay, + pstrUsageSlow +}; +const char * const ReportDescParserBase::consTitles9[] PROGMEM ={ + pstrUsageFanEnable, + pstrUsageFanSpeed, + pstrUsageLightEnable, + pstrUsageLightIlluminationLevel, + pstrUsageClimateControlEnable, + pstrUsageRoomTemperature, + pstrUsageSecurityEnable, + pstrUsageFireAlarm, + pstrUsagePoliceAlarm, + pstrUsageProximity, + pstrUsageMotion, + pstrUsageDuresAlarm, + pstrUsageHoldupAlarm, + pstrUsageMedicalAlarm +}; +const char * const ReportDescParserBase::consTitlesA[] PROGMEM ={ + pstrUsageBalanceRight, + pstrUsageBalanceLeft, + pstrUsageBassIncrement, + pstrUsageBassDecrement, + pstrUsageTrebleIncrement, + pstrUsageTrebleDecrement +}; +const char * const ReportDescParserBase::consTitlesB[] PROGMEM ={ + pstrUsageSpeakerSystem, + pstrUsageChannelLeft, + pstrUsageChannelRight, + pstrUsageChannelCenter, + pstrUsageChannelFront, + pstrUsageChannelCenterFront, + pstrUsageChannelSide, + pstrUsageChannelSurround, + pstrUsageChannelLowFreqEnhancement, + pstrUsageChannelTop, + pstrUsageChannelUnknown +}; +const char * const ReportDescParserBase::consTitlesC[] PROGMEM ={ + pstrUsageSubChannel, + pstrUsageSubChannelIncrement, + pstrUsageSubChannelDecrement, + pstrUsageAlternateAudioIncrement, + pstrUsageAlternateAudioDecrement +}; +const char * const ReportDescParserBase::consTitlesD[] PROGMEM ={ + pstrUsageApplicationLaunchButtons, + pstrUsageALLaunchButtonConfigTool, + pstrUsageALProgrammableButton, + pstrUsageALConsumerControlConfig, + pstrUsageALWordProcessor, + pstrUsageALTextEditor, + pstrUsageALSpreadsheet, + pstrUsageALGraphicsEditor, + pstrUsageALPresentationApp, + pstrUsageALDatabaseApp, + pstrUsageALEmailReader, + pstrUsageALNewsreader, + pstrUsageALVoicemail, + pstrUsageALContactsAddressBook, + pstrUsageALCalendarSchedule, + pstrUsageALTaskProjectManager, + pstrUsageALLogJournalTimecard, + pstrUsageALCheckbookFinance, + pstrUsageALCalculator, + pstrUsageALAVCapturePlayback, + pstrUsageALLocalMachineBrowser, + pstrUsageALLANWANBrow, + pstrUsageALInternetBrowser, + pstrUsageALRemoteNetISPConnect, + pstrUsageALNetworkConference, + pstrUsageALNetworkChat, + pstrUsageALTelephonyDialer, + pstrUsageALLogon, + pstrUsageALLogoff, + pstrUsageALLogonLogoff, + pstrUsageALTermLockScrSav, + pstrUsageALControlPannel, + pstrUsageALCommandLineProcessorRun, + pstrUsageALProcessTaskManager, + pstrUsageALSelectTaskApplication, + pstrUsageALNextTaskApplication, + pstrUsageALPreviousTaskApplication, + pstrUsageALPreemptiveHaltTaskApp, + pstrUsageALIntegratedHelpCenter, + pstrUsageALDocuments, + pstrUsageALThesaurus, + pstrUsageALDictionary, + pstrUsageALDesktop, + pstrUsageALSpellCheck, + pstrUsageALGrammarCheck, + pstrUsageALWirelessStatus, + pstrUsageALKeyboardLayout, + pstrUsageALVirusProtection, + pstrUsageALEncryption, + pstrUsageALScreenSaver, + pstrUsageALAlarms, + pstrUsageALClock, + pstrUsageALFileBrowser, + pstrUsageALPowerStatus, + pstrUsageALImageBrowser, + pstrUsageALAudioBrowser, + pstrUsageALMovieBrowser, + pstrUsageALDigitalRightsManager, + pstrUsageALDigitalWallet, + pstrUsagePageReserved, + pstrUsageALInstantMessaging, + pstrUsageALOEMFeaturesBrowser, + pstrUsageALOEMHelp, + pstrUsageALOnlineCommunity, + pstrUsageALEntertainmentContentBrow, + pstrUsageALOnlineShoppingBrowser, + pstrUsageALSmartCardInfoHelp, + pstrUsageALMarketMonitorFinBrowser, + pstrUsageALCustomCorpNewsBrowser, + pstrUsageALOnlineActivityBrowser, + pstrUsageALResearchSearchBrowser, + pstrUsageALAudioPlayer +}; +const char * const ReportDescParserBase::consTitlesE[] PROGMEM ={ + pstrUsageGenericGUIAppControls, + pstrUsageACNew, + pstrUsageACOpen, + pstrUsageACClose, + pstrUsageACExit, + pstrUsageACMaximize, + pstrUsageACMinimize, + pstrUsageACSave, + pstrUsageACPrint, + pstrUsageACProperties, + pstrUsageACUndo, + pstrUsageACCopy, + pstrUsageACCut, + pstrUsageACPaste, + pstrUsageACSelectAll, + pstrUsageACFind, + pstrUsageACFindAndReplace, + pstrUsageACSearch, + pstrUsageACGoto, + pstrUsageACHome, + pstrUsageACBack, + pstrUsageACForward, + pstrUsageACStop, + pstrUsageACRefresh, + pstrUsageACPreviousLink, + pstrUsageACNextLink, + pstrUsageACBookmarks, + pstrUsageACHistory, + pstrUsageACSubscriptions, + pstrUsageACZoomIn, + pstrUsageACZoomOut, + pstrUsageACZoom, + pstrUsageACFullScreenView, + pstrUsageACNormalView, + pstrUsageACViewToggle, + pstrUsageACScrollUp, + pstrUsageACScrollDown, + pstrUsageACScroll, + pstrUsageACPanLeft, + pstrUsageACPanRight, + pstrUsageACPan, + pstrUsageACNewWindow, + pstrUsageACTileHoriz, + pstrUsageACTileVert, + pstrUsageACFormat, + pstrUsageACEdit, + pstrUsageACBold, + pstrUsageACItalics, + pstrUsageACUnderline, + pstrUsageACStrikethrough, + pstrUsageACSubscript, + pstrUsageACSuperscript, + pstrUsageACAllCaps, + pstrUsageACRotate, + pstrUsageACResize, + pstrUsageACFlipHorizontal, + pstrUsageACFlipVertical, + pstrUsageACMirrorHorizontal, + pstrUsageACMirrorVertical, + pstrUsageACFontSelect, + pstrUsageACFontColor, + pstrUsageACFontSize, + pstrUsageACJustifyLeft, + pstrUsageACJustifyCenterH, + pstrUsageACJustifyRight, + pstrUsageACJustifyBlockH, + pstrUsageACJustifyTop, + pstrUsageACJustifyCenterV, + pstrUsageACJustifyBottom, + pstrUsageACJustifyBlockV, + pstrUsageACIndentDecrease, + pstrUsageACIndentIncrease, + pstrUsageACNumberedList, + pstrUsageACRestartNumbering, + pstrUsageACBulletedList, + pstrUsageACPromote, + pstrUsageACDemote, + pstrUsageACYes, + pstrUsageACNo, + pstrUsageACCancel, + pstrUsageACCatalog, + pstrUsageACBuyChkout, + pstrUsageACAddToCart, + pstrUsageACExpand, + pstrUsageACExpandAll, + pstrUsageACCollapse, + pstrUsageACCollapseAll, + pstrUsageACPrintPreview, + pstrUsageACPasteSpecial, + pstrUsageACInsertMode, + pstrUsageACDelete, + pstrUsageACLock, + pstrUsageACUnlock, + pstrUsageACProtect, + pstrUsageACUnprotect, + pstrUsageACAttachComment, + pstrUsageACDeleteComment, + pstrUsageACViewComment, + pstrUsageACSelectWord, + pstrUsageACSelectSentence, + pstrUsageACSelectParagraph, + pstrUsageACSelectColumn, + pstrUsageACSelectRow, + pstrUsageACSelectTable, + pstrUsageACSelectObject, + pstrUsageACRedoRepeat, + pstrUsageACSort, + pstrUsageACSortAscending, + pstrUsageACSortDescending, + pstrUsageACFilter, + pstrUsageACSetClock, + pstrUsageACViewClock, + pstrUsageACSelectTimeZone, + pstrUsageACEditTimeZone, + pstrUsageACSetAlarm, + pstrUsageACClearAlarm, + pstrUsageACSnoozeAlarm, + pstrUsageACResetAlarm, + pstrUsageACSyncronize, + pstrUsageACSendReceive, + pstrUsageACSendTo, + pstrUsageACReply, + pstrUsageACReplyAll, + pstrUsageACForwardMessage, + pstrUsageACSend, + pstrUsageACAttachFile, + pstrUsageACUpload, + pstrUsageACDownload, + pstrUsageACSetBorders, + pstrUsageACInsertRow, + pstrUsageACInsertColumn, + pstrUsageACInsertFile, + pstrUsageACInsertPicture, + pstrUsageACInsertObject, + pstrUsageACInsertSymbol, + pstrUsageACSaveAndClose, + pstrUsageACRename, + pstrUsageACMerge, + pstrUsageACSplit, + pstrUsageACDistributeHorizontaly, + pstrUsageACDistributeVerticaly +}; +const char * const ReportDescParserBase::digitTitles0[] PROGMEM ={ + pstrUsageDigitizer, + pstrUsagePen, + pstrUsageLightPen, + pstrUsageTouchScreen, + pstrUsageTouchPad, + pstrUsageWhiteBoard, + pstrUsageCoordinateMeasuringMachine, + pstrUsage3DDigitizer, + pstrUsageStereoPlotter, + pstrUsageArticulatedArm, + pstrUsageArmature, + pstrUsageMultiplePointDigitizer, + pstrUsageFreeSpaceWand +}; +const char * const ReportDescParserBase::digitTitles1[] PROGMEM ={ + pstrUsageStylus, + pstrUsagePuck, + pstrUsageFinger + +}; +const char * const ReportDescParserBase::digitTitles2[] PROGMEM ={ + pstrUsageTipPressure, + pstrUsageBarrelPressure, + pstrUsageInRange, + pstrUsageTouch, + pstrUsageUntouch, + pstrUsageTap, + pstrUsageQuality, + pstrUsageDataValid, + pstrUsageTransducerIndex, + pstrUsageTabletFunctionKeys, + pstrUsageProgramChangeKeys, + pstrUsageBatteryStrength, + pstrUsageInvert, + pstrUsageXTilt, + pstrUsageYTilt, + pstrUsageAzimuth, + pstrUsageAltitude, + pstrUsageTwist, + pstrUsageTipSwitch, + pstrUsageSecondaryTipSwitch, + pstrUsageBarrelSwitch, + pstrUsageEraser, + pstrUsageTabletPick +}; +const char * const ReportDescParserBase::aplphanumTitles0[] PROGMEM ={ + pstrUsageAlphanumericDisplay, + pstrUsageBitmappedDisplay +}; +const char * const ReportDescParserBase::aplphanumTitles1[] PROGMEM ={ + pstrUsageDisplayAttributesReport, + pstrUsageASCIICharacterSet, + pstrUsageDataReadBack, + pstrUsageFontReadBack, + pstrUsageDisplayControlReport, + pstrUsageClearDisplay, + pstrUsageDisplayEnable, + pstrUsageScreenSaverDelay, + pstrUsageScreenSaverEnable, + pstrUsageVerticalScroll, + pstrUsageHorizontalScroll, + pstrUsageCharacterReport, + pstrUsageDisplayData, + pstrUsageDisplayStatus, + pstrUsageStatusNotReady, + pstrUsageStatusReady, + pstrUsageErrorNotALoadableCharacter, + pstrUsageErrorFotDataCanNotBeRead, + pstrUsageCursorPositionReport, + pstrUsageRow, + pstrUsageColumn, + pstrUsageRows, + pstrUsageColumns, + pstrUsageCursorPixelPosition, + pstrUsageCursorMode, + pstrUsageCursorEnable, + pstrUsageCursorBlink, + pstrUsageFontReport, + pstrUsageFontData, + pstrUsageCharacterWidth, + pstrUsageCharacterHeight, + pstrUsageCharacterSpacingHorizontal, + pstrUsageCharacterSpacingVertical, + pstrUsageUnicodeCharset, + pstrUsageFont7Segment, + pstrUsage7SegmentDirectMap, + pstrUsageFont14Segment, + pstrUsage14SegmentDirectMap, + pstrUsageDisplayBrightness, + pstrUsageDisplayContrast, + pstrUsageCharacterAttribute, + pstrUsageAttributeReadback, + pstrUsageAttributeData, + pstrUsageCharAttributeEnhance, + pstrUsageCharAttributeUnderline, + pstrUsageCharAttributeBlink +}; +const char * const ReportDescParserBase::aplphanumTitles2[] PROGMEM ={ + pstrUsageBitmapSizeX, + pstrUsageBitmapSizeY, + pstrUsagePageReserved, + pstrUsageBitDepthFormat, + pstrUsageDisplayOrientation, + pstrUsagePaletteReport, + pstrUsagePaletteDataSize, + pstrUsagePaletteDataOffset, + pstrUsagePaletteData, + pstrUsageBlitReport, + pstrUsageBlitRectangleX1, + pstrUsageBlitRectangleY1, + pstrUsageBlitRectangleX2, + pstrUsageBlitRectangleY2, + pstrUsageBlitData, + pstrUsageSoftButton, + pstrUsageSoftButtonID, + pstrUsageSoftButtonSide, + pstrUsageSoftButtonOffset1, + pstrUsageSoftButtonOffset2, + pstrUsageSoftButtonReport +}; +const char * const ReportDescParserBase::medInstrTitles0[] PROGMEM ={ + pstrUsageVCRAcquisition, + pstrUsageFreezeThaw, + pstrUsageClipStore, + pstrUsageUpdate, + pstrUsageNext, + pstrUsageSave, + pstrUsagePrint, + pstrUsageMicrophoneEnable +}; +const char * const ReportDescParserBase::medInstrTitles1[] PROGMEM ={ + pstrUsageCine, + pstrUsageTransmitPower, + pstrUsageVolume, + pstrUsageFocus, + pstrUsageDepth +}; +const char * const ReportDescParserBase::medInstrTitles2[] PROGMEM ={ + pstrUsageSoftStepPrimary, + pstrUsageSoftStepSecondary +}; +const char * const ReportDescParserBase::medInstrTitles3[] PROGMEM ={ + pstrUsageZoomSelect, + pstrUsageZoomAdjust, + pstrUsageSpectralDopplerModeSelect, + pstrUsageSpectralDopplerModeAdjust, + pstrUsageColorDopplerModeSelect, + pstrUsageColorDopplerModeAdjust, + pstrUsageMotionModeSelect, + pstrUsageMotionModeAdjust, + pstrUsage2DModeSelect, + pstrUsage2DModeAdjust +}; +const char * const ReportDescParserBase::medInstrTitles4[] PROGMEM ={ + pstrUsageSoftControlSelect, + pstrUsageSoftControlAdjust +}; + +void ReportDescParserBase::Parse(const uint16_t len, const uint8_t *pbuf, const uint16_t &offset) { + uint16_t cntdn = (uint16_t) len; + uint8_t *p = (uint8_t*) pbuf; + + + totalSize = 0; + + while (cntdn) { + //Serial.println(""); + //PrintHex(offset + len - cntdn); + //Serial.print(":"); + + ParseItem(&p, &cntdn); + + //if (ParseItem(&p, &cntdn)) + // return; + } + //USBTRACE2("Total:", totalSize); +} + +void ReportDescParserBase::PrintValue(uint8_t *p, uint8_t len) { + Notify(PSTR("("), 0x80); + for (; len; p++, len--) + PrintHex (*p, 0x80); + Notify(PSTR(")"), 0x80); +} + +void ReportDescParserBase::PrintByteValue(uint8_t data) { + Notify(PSTR("("), 0x80); + PrintHex (data, 0x80); + Notify(PSTR(")"), 0x80); +} + +void ReportDescParserBase::PrintItemTitle(uint8_t prefix) { + switch (prefix & (TYPE_MASK | TAG_MASK)) { + case (TYPE_GLOBAL | TAG_GLOBAL_PUSH): + Notify(PSTR("\r\nPush"), 0x80); + break; + case (TYPE_GLOBAL | TAG_GLOBAL_POP): + Notify(PSTR("\r\nPop"), 0x80); + break; + case (TYPE_GLOBAL | TAG_GLOBAL_USAGEPAGE): + Notify(PSTR("\r\nUsage Page"), 0x80); + break; + case (TYPE_GLOBAL | TAG_GLOBAL_LOGICALMIN): + Notify(PSTR("\r\nLogical Min"), 0x80); + break; + case (TYPE_GLOBAL | TAG_GLOBAL_LOGICALMAX): + Notify(PSTR("\r\nLogical Max"), 0x80); + break; + case (TYPE_GLOBAL | TAG_GLOBAL_PHYSMIN): + Notify(PSTR("\r\nPhysical Min"), 0x80); + break; + case (TYPE_GLOBAL | TAG_GLOBAL_PHYSMAX): + Notify(PSTR("\r\nPhysical Max"), 0x80); + break; + case (TYPE_GLOBAL | TAG_GLOBAL_UNITEXP): + Notify(PSTR("\r\nUnit Exp"), 0x80); + break; + case (TYPE_GLOBAL | TAG_GLOBAL_UNIT): + Notify(PSTR("\r\nUnit"), 0x80); + break; + case (TYPE_GLOBAL | TAG_GLOBAL_REPORTSIZE): + Notify(PSTR("\r\nReport Size"), 0x80); + break; + case (TYPE_GLOBAL | TAG_GLOBAL_REPORTCOUNT): + Notify(PSTR("\r\nReport Count"), 0x80); + break; + case (TYPE_GLOBAL | TAG_GLOBAL_REPORTID): + Notify(PSTR("\r\nReport Id"), 0x80); + break; + case (TYPE_LOCAL | TAG_LOCAL_USAGE): + Notify(PSTR("\r\nUsage"), 0x80); + break; + case (TYPE_LOCAL | TAG_LOCAL_USAGEMIN): + Notify(PSTR("\r\nUsage Min"), 0x80); + break; + case (TYPE_LOCAL | TAG_LOCAL_USAGEMAX): + Notify(PSTR("\r\nUsage Max"), 0x80); + break; + case (TYPE_MAIN | TAG_MAIN_COLLECTION): + Notify(PSTR("\r\nCollection"), 0x80); + break; + case (TYPE_MAIN | TAG_MAIN_ENDCOLLECTION): + Notify(PSTR("\r\nEnd Collection"), 0x80); + break; + case (TYPE_MAIN | TAG_MAIN_INPUT): + Notify(PSTR("\r\nInput"), 0x80); + break; + case (TYPE_MAIN | TAG_MAIN_OUTPUT): + Notify(PSTR("\r\nOutput"), 0x80); + break; + case (TYPE_MAIN | TAG_MAIN_FEATURE): + Notify(PSTR("\r\nFeature"), 0x80); + break; + } // switch (**pp & (TYPE_MASK | TAG_MASK)) +} + +uint8_t ReportDescParserBase::ParseItem(uint8_t **pp, uint16_t *pcntdn) { + //uint8_t ret = enErrorSuccess; + + switch (itemParseState) { + case 0: + if (**pp == HID_LONG_ITEM_PREFIX) + USBTRACE("\r\nLONG\r\n"); + else { + uint8_t size = ((**pp) & DATA_SIZE_MASK); + + itemPrefix = (**pp); + itemSize = 1 + ((size == DATA_SIZE_4) ? 4 : size); + + PrintItemTitle(itemPrefix); + } + (*pp)++; + (*pcntdn)--; + itemSize--; + itemParseState = 1; + + if (!itemSize) + break; + + if (!pcntdn) + return enErrorIncomplete; + case 1: + //USBTRACE2("\r\niSz:",itemSize); + + theBuffer.valueSize = itemSize; + valParser.Initialize(&theBuffer); + itemParseState = 2; + case 2: + if (!valParser.Parse(pp, pcntdn)) + return enErrorIncomplete; + itemParseState = 3; + case 3: + { + uint8_t data = *((uint8_t*) varBuffer); + + switch (itemPrefix & (TYPE_MASK | TAG_MASK)) { + case (TYPE_LOCAL | TAG_LOCAL_USAGE): + if (pfUsage) { + if (theBuffer.valueSize > 1) + pfUsage(*((uint16_t*) varBuffer)); + else + pfUsage(data); + } + break; + case (TYPE_GLOBAL | TAG_GLOBAL_REPORTSIZE): + rptSize = data; + PrintByteValue(data); + break; + case (TYPE_GLOBAL | TAG_GLOBAL_REPORTCOUNT): + rptCount = data; + PrintByteValue(data); + break; + case (TYPE_GLOBAL | TAG_GLOBAL_LOGICALMIN): + case (TYPE_GLOBAL | TAG_GLOBAL_LOGICALMAX): + case (TYPE_GLOBAL | TAG_GLOBAL_PHYSMIN): + case (TYPE_GLOBAL | TAG_GLOBAL_PHYSMAX): + case (TYPE_GLOBAL | TAG_GLOBAL_REPORTID): + case (TYPE_LOCAL | TAG_LOCAL_USAGEMIN): + case (TYPE_LOCAL | TAG_LOCAL_USAGEMAX): + case (TYPE_GLOBAL | TAG_GLOBAL_UNITEXP): + case (TYPE_GLOBAL | TAG_GLOBAL_UNIT): + PrintValue(varBuffer, theBuffer.valueSize); + break; + case (TYPE_GLOBAL | TAG_GLOBAL_PUSH): + case (TYPE_GLOBAL | TAG_GLOBAL_POP): + break; + case (TYPE_GLOBAL | TAG_GLOBAL_USAGEPAGE): + SetUsagePage(data); + PrintUsagePage(data); + PrintByteValue(data); + break; + case (TYPE_MAIN | TAG_MAIN_COLLECTION): + case (TYPE_MAIN | TAG_MAIN_ENDCOLLECTION): + switch (data) { + case 0x00: + Notify(PSTR(" Physical"), 0x80); + break; + case 0x01: + Notify(PSTR(" Application"), 0x80); + break; + case 0x02: + Notify(PSTR(" Logical"), 0x80); + break; + case 0x03: + Notify(PSTR(" Report"), 0x80); + break; + case 0x04: + Notify(PSTR(" Named Array"), 0x80); + break; + case 0x05: + Notify(PSTR(" Usage Switch"), 0x80); + break; + case 0x06: + Notify(PSTR(" Usage Modifier"), 0x80); + break; + default: + Notify(PSTR(" Vendor Defined("), 0x80); + PrintHex (data, 0x80); + Notify(PSTR(")"), 0x80); + } + break; + case (TYPE_MAIN | TAG_MAIN_INPUT): + case (TYPE_MAIN | TAG_MAIN_OUTPUT): + case (TYPE_MAIN | TAG_MAIN_FEATURE): + totalSize += (uint16_t) rptSize * (uint16_t) rptCount; + rptSize = 0; + rptCount = 0; + Notify(PSTR("("), 0x80); + PrintBin (data, 0x80); + Notify(PSTR(")"), 0x80); + break; + } // switch (**pp & (TYPE_MASK | TAG_MASK)) + } + } // switch (itemParseState) + itemParseState = 0; + return enErrorSuccess; +} + +ReportDescParserBase::UsagePageFunc ReportDescParserBase::usagePageFunctions[] /*PROGMEM*/ ={ + &ReportDescParserBase::PrintGenericDesktopPageUsage, + &ReportDescParserBase::PrintSimulationControlsPageUsage, + &ReportDescParserBase::PrintVRControlsPageUsage, + &ReportDescParserBase::PrintSportsControlsPageUsage, + &ReportDescParserBase::PrintGameControlsPageUsage, + &ReportDescParserBase::PrintGenericDeviceControlsPageUsage, + NULL, // Keyboard/Keypad + &ReportDescParserBase::PrintLEDPageUsage, + &ReportDescParserBase::PrintButtonPageUsage, + &ReportDescParserBase::PrintOrdinalPageUsage, + &ReportDescParserBase::PrintTelephonyPageUsage, + &ReportDescParserBase::PrintConsumerPageUsage, + &ReportDescParserBase::PrintDigitizerPageUsage, + NULL, // Reserved + NULL, // PID + NULL // Unicode +}; + +void ReportDescParserBase::SetUsagePage(uint16_t page) { + pfUsage = NULL; + + if (page > 0x00 && page < 0x11) + pfUsage = /*(UsagePageFunc)pgm_read_word*/(usagePageFunctions[page - 1]); + //else if (page > 0x7f && page < 0x84) + // Notify(pstrUsagePageMonitor); + //else if (page > 0x83 && page < 0x8c) + // Notify(pstrUsagePagePower); + //else if (page > 0x8b && page < 0x92) + // Notify((char*)pgm_read_word(&usagePageTitles1[page - 0x8c])); + //else if (page > 0xfeff && page <= 0xffff) + // Notify(pstrUsagePageVendorDefined); + else + switch (page) { + case 0x14: + pfUsage = &ReportDescParserBase::PrintAlphanumDisplayPageUsage; + break; + case 0x40: + pfUsage = &ReportDescParserBase::PrintMedicalInstrumentPageUsage; + break; + } +} + +void ReportDescParserBase::PrintUsagePage(uint16_t page) { + Notify(pstrSpace, 0x80); + + if (page > 0x00 && page < 0x11) + Notify((char*) pgm_read_word(&usagePageTitles0[page - 1]), 0x80); + else if (page > 0x7f && page < 0x84) + Notify(pstrUsagePageMonitor, 0x80); + else if (page > 0x83 && page < 0x8c) + Notify(pstrUsagePagePower, 0x80); + else if (page > 0x8b && page < 0x92) + Notify((char*) pgm_read_word(&usagePageTitles1[page - 0x8c]), 0x80); + else if (page > 0xfeff && page <= 0xffff) + Notify(pstrUsagePageVendorDefined, 0x80); + else + switch (page) { + case 0x14: + Notify(pstrUsagePageAlphaNumericDisplay, 0x80); + break; + case 0x40: + Notify(pstrUsagePageMedicalInstruments, 0x80); + break; + default: + Notify(pstrUsagePageUndefined, 0x80); + } +} + +void ReportDescParserBase::PrintButtonPageUsage(uint16_t usage) { + Notify(pstrSpace, 0x80); + Notify(PSTR("Btn"), 0x80); + PrintHex (usage, 0x80); + Notify(PSTR("\r\n"), 0x80); + //Serial.print(usage, HEX); +} + +void ReportDescParserBase::PrintOrdinalPageUsage(uint16_t usage) { + Notify(pstrSpace, 0x80); + Notify(PSTR("Inst"), 0x80); + // Sorry, HEX for now... + PrintHex (usage, 0x80); + Notify(PSTR("\r\n"), 0x80); + //Serial.print(usage, DEC); +} + +void ReportDescParserBase::PrintGenericDesktopPageUsage(uint16_t usage) { + Notify(pstrSpace, 0x80); + + if (usage > 0x00 && usage < 0x0a) + Notify((char*) pgm_read_word(&genDesktopTitles0[usage - 1]), 0x80); + else if (usage > 0x2f && usage < 0x49) + Notify((char*) pgm_read_word(&genDesktopTitles1[usage - 0x30]), 0x80); + else if (usage > 0x7f && usage < 0x94) + Notify((char*) pgm_read_word(&genDesktopTitles2[usage - 0x80]), 0x80); + else if (usage > 0x9f && usage < 0xa9) + Notify((char*) pgm_read_word(&genDesktopTitles3[usage - 0xa0]), 0x80); + else if (usage > 0xaf && usage < 0xb8) + Notify((char*) pgm_read_word(&genDesktopTitles4[usage - 0xb0]), 0x80); + else + Notify(pstrUsagePageUndefined, 0x80); +} + +void ReportDescParserBase::PrintSimulationControlsPageUsage(uint16_t usage) { + Notify(pstrSpace, 0x80); + + if (usage > 0x00 && usage < 0x0d) + Notify((char*) pgm_read_word(&simuTitles0[usage - 1]), 0x80); + else if (usage > 0x1f && usage < 0x26) + Notify((char*) pgm_read_word(&simuTitles1[usage - 0x20]), 0x80); + else if (usage > 0xaf && usage < 0xd1) + Notify((char*) pgm_read_word(&simuTitles2[usage - 0xb0]), 0x80); + else + Notify(pstrUsagePageUndefined, 0x80); +} + +void ReportDescParserBase::PrintVRControlsPageUsage(uint16_t usage) { + Notify(pstrSpace, 0x80); + + if (usage > 0x00 && usage < 0x0b) + Notify((char*) pgm_read_word(&vrTitles0[usage - 1]), 0x80); + else if (usage > 0x1f && usage < 0x22) + Notify((char*) pgm_read_word(&vrTitles1[usage - 0x20]), 0x80); + else + Notify(pstrUsagePageUndefined, 0x80); +} + +void ReportDescParserBase::PrintSportsControlsPageUsage(uint16_t usage) { + Notify(pstrSpace, 0x80); + + if (usage > 0x00 && usage < 0x05) + Notify((char*) pgm_read_word(&sportsCtrlTitles0[usage - 1]), 0x80); + else if (usage > 0x2f && usage < 0x3a) + Notify((char*) pgm_read_word(&sportsCtrlTitles1[usage - 0x30]), 0x80); + else if (usage > 0x4f && usage < 0x64) + Notify((char*) pgm_read_word(&sportsCtrlTitles2[usage - 0x50]), 0x80); + else + Notify(pstrUsagePageUndefined, 0x80); +} + +void ReportDescParserBase::PrintGameControlsPageUsage(uint16_t usage) { + Notify(pstrSpace, 0x80); + + if (usage > 0x00 && usage < 0x04) + Notify((char*) pgm_read_word(&gameTitles0[usage - 1]), 0x80); + else if (usage > 0x1f && usage < 0x3a) + Notify((char*) pgm_read_word(&gameTitles1[usage - 0x20]), 0x80); + else + Notify(pstrUsagePageUndefined, 0x80); +} + +void ReportDescParserBase::PrintGenericDeviceControlsPageUsage(uint16_t usage) { + Notify(pstrSpace, 0x80); + + if (usage > 0x1f && usage < 0x27) + Notify((char*) pgm_read_word(&genDevCtrlTitles[usage - 0x20]), 0x80); + else + Notify(pstrUsagePageUndefined, 0x80); +} + +void ReportDescParserBase::PrintLEDPageUsage(uint16_t usage) { + Notify(pstrSpace, 0x80); + + if (usage > 0x00 && usage < 0x4e) + Notify((char*) pgm_read_word(&ledTitles[usage - 1]), 0x80); + else + Notify(pstrUsagePageUndefined, 0x80); +} + +void ReportDescParserBase::PrintTelephonyPageUsage(uint16_t usage) { + Notify(pstrSpace, 0x80); + + if (usage > 0x00 && usage < 0x08) + Notify((char*) pgm_read_word(&telTitles0[usage - 1]), 0x80); + else if (usage > 0x1f && usage < 0x32) + Notify((char*) pgm_read_word(&telTitles1[usage - 0x1f]), 0x80); + else if (usage > 0x4f && usage < 0x54) + Notify((char*) pgm_read_word(&telTitles2[usage - 0x4f]), 0x80); + else if (usage > 0x6f && usage < 0x75) + Notify((char*) pgm_read_word(&telTitles3[usage - 0x6f]), 0x80); + else if (usage > 0x8f && usage < 0x9f) + Notify((char*) pgm_read_word(&telTitles4[usage - 0x8f]), 0x80); + else if (usage > 0xaf && usage < 0xc0) + Notify((char*) pgm_read_word(&telTitles5[usage - 0xaf]), 0x80); + else + Notify(pstrUsagePageUndefined, 0x80); +} + +void ReportDescParserBase::PrintConsumerPageUsage(uint16_t usage) { + Notify(pstrSpace, 0x80); + + if (usage > 0x00 && usage < 0x07) + Notify((char*) pgm_read_word(&consTitles0[usage - 1]), 0x80); + else if (usage > 0x1f && usage < 0x23) + Notify((char*) pgm_read_word(&consTitles1[usage - 0x1f]), 0x80); + else if (usage > 0x2f && usage < 0x37) + Notify((char*) pgm_read_word(&consTitles2[usage - 0x2f]), 0x80); + else if (usage > 0x3f && usage < 0x49) + Notify((char*) pgm_read_word(&consTitles3[usage - 0x3f]), 0x80); + else if (usage > 0x5f && usage < 0x67) + Notify((char*) pgm_read_word(&consTitles4[usage - 0x5f]), 0x80); + else if (usage > 0x7f && usage < 0xa5) + Notify((char*) pgm_read_word(&consTitles5[usage - 0x7f]), 0x80); + else if (usage > 0xaf && usage < 0xcf) + Notify((char*) pgm_read_word(&consTitles6[usage - 0xaf]), 0x80); + else if (usage > 0xdf && usage < 0xeb) + Notify((char*) pgm_read_word(&consTitles7[usage - 0xdf]), 0x80); + else if (usage > 0xef && usage < 0xf6) + Notify((char*) pgm_read_word(&consTitles8[usage - 0xef]), 0x80); + else if (usage > 0xff && usage < 0x10e) + Notify((char*) pgm_read_word(&consTitles9[usage - 0xff]), 0x80); + else if (usage > 0x14f && usage < 0x156) + Notify((char*) pgm_read_word(&consTitlesA[usage - 0x14f]), 0x80); + else if (usage > 0x15f && usage < 0x16b) + Notify((char*) pgm_read_word(&consTitlesB[usage - 0x15f]), 0x80); + else if (usage > 0x16f && usage < 0x175) + Notify((char*) pgm_read_word(&consTitlesC[usage - 0x16f]), 0x80); + else if (usage > 0x17f && usage < 0x1c8) + Notify((char*) pgm_read_word(&consTitlesD[usage - 0x17f]), 0x80); + else if (usage > 0x1ff && usage < 0x29d) + Notify((char*) pgm_read_word(&consTitlesE[usage - 0x1ff]), 0x80); + else + Notify(pstrUsagePageUndefined, 0x80); +} + +void ReportDescParserBase::PrintDigitizerPageUsage(uint16_t usage) { + Notify(pstrSpace, 0x80); + + if (usage > 0x00 && usage < 0x0e) + Notify((char*) pgm_read_word(&digitTitles0[usage - 1]), 0x80); + else if (usage > 0x1f && usage < 0x23) + Notify((char*) pgm_read_word(&digitTitles1[usage - 0x1f]), 0x80); + else if (usage > 0x2f && usage < 0x47) + Notify((char*) pgm_read_word(&digitTitles2[usage - 0x2f]), 0x80); + else + Notify(pstrUsagePageUndefined, 0x80); +} + +void ReportDescParserBase::PrintAlphanumDisplayPageUsage(uint16_t usage) { + Notify(pstrSpace, 0x80); + + if (usage > 0x00 && usage < 0x03) + Notify((char*) pgm_read_word(&aplphanumTitles0[usage - 1]), 0x80); + else if (usage > 0x1f && usage < 0x4e) + Notify((char*) pgm_read_word(&aplphanumTitles1[usage - 0x1f]), 0x80); + else if (usage > 0x7f && usage < 0x96) + Notify((char*) pgm_read_word(&digitTitles2[usage - 0x80]), 0x80); + else + Notify(pstrUsagePageUndefined, 0x80); +} + +void ReportDescParserBase::PrintMedicalInstrumentPageUsage(uint16_t usage) { + Notify(pstrSpace, 0x80); + + if (usage == 1) + Notify(pstrUsageMedicalUltrasound, 0x80); + else if (usage > 0x1f && usage < 0x28) + Notify((char*) pgm_read_word(&medInstrTitles0[usage - 0x1f]), 0x80); + else if (usage > 0x3f && usage < 0x45) + Notify((char*) pgm_read_word(&medInstrTitles1[usage - 0x40]), 0x80); + else if (usage > 0x5f && usage < 0x62) + Notify((char*) pgm_read_word(&medInstrTitles2[usage - 0x60]), 0x80); + else if (usage == 0x70) + Notify(pstrUsageDepthGainCompensation, 0x80); + else if (usage > 0x7f && usage < 0x8a) + Notify((char*) pgm_read_word(&medInstrTitles3[usage - 0x80]), 0x80); + else if (usage > 0x9f && usage < 0xa2) + Notify((char*) pgm_read_word(&medInstrTitles4[usage - 0xa0]), 0x80); + else + Notify(pstrUsagePageUndefined, 0x80); +} + +uint8_t ReportDescParser2::ParseItem(uint8_t **pp, uint16_t *pcntdn) { + //uint8_t ret = enErrorSuccess; + + switch (itemParseState) { + case 0: + if (**pp == HID_LONG_ITEM_PREFIX) + USBTRACE("\r\nLONG\r\n"); + else { + uint8_t size = ((**pp) & DATA_SIZE_MASK); + itemPrefix = (**pp); + itemSize = 1 + ((size == DATA_SIZE_4) ? 4 : size); + } + (*pp)++; + (*pcntdn)--; + itemSize--; + itemParseState = 1; + + if (!itemSize) + break; + + if (!pcntdn) + return enErrorIncomplete; + case 1: + theBuffer.valueSize = itemSize; + valParser.Initialize(&theBuffer); + itemParseState = 2; + case 2: + if (!valParser.Parse(pp, pcntdn)) + return enErrorIncomplete; + itemParseState = 3; + case 3: + { + uint8_t data = *((uint8_t*) varBuffer); + + switch (itemPrefix & (TYPE_MASK | TAG_MASK)) { + case (TYPE_LOCAL | TAG_LOCAL_USAGE): + if (pfUsage) { + if (theBuffer.valueSize > 1) + pfUsage(*((uint16_t*) varBuffer)); + else + pfUsage(data); + } + break; + case (TYPE_GLOBAL | TAG_GLOBAL_REPORTSIZE): + rptSize = data; + break; + case (TYPE_GLOBAL | TAG_GLOBAL_REPORTCOUNT): + rptCount = data; + break; + case (TYPE_GLOBAL | TAG_GLOBAL_REPORTID): + rptId = data; + break; + case (TYPE_LOCAL | TAG_LOCAL_USAGEMIN): + useMin = data; + break; + case (TYPE_LOCAL | TAG_LOCAL_USAGEMAX): + useMax = data; + break; + case (TYPE_GLOBAL | TAG_GLOBAL_USAGEPAGE): + SetUsagePage(data); + break; + case (TYPE_MAIN | TAG_MAIN_OUTPUT): + case (TYPE_MAIN | TAG_MAIN_FEATURE): + rptSize = 0; + rptCount = 0; + useMin = 0; + useMax = 0; + break; + case (TYPE_MAIN | TAG_MAIN_INPUT): + OnInputItem(data); + + totalSize += (uint16_t) rptSize * (uint16_t) rptCount; + + rptSize = 0; + rptCount = 0; + useMin = 0; + useMax = 0; + break; + } // switch (**pp & (TYPE_MASK | TAG_MASK)) + } + } // switch (itemParseState) + itemParseState = 0; + return enErrorSuccess; +} + +void ReportDescParser2::OnInputItem(uint8_t itm) { + uint8_t byte_offset = (totalSize >> 3); // calculate offset to the next unhandled byte i = (int)(totalCount / 8); + uint32_t tmp = (byte_offset << 3); + uint8_t bit_offset = totalSize - tmp; // number of bits in the current byte already handled + uint8_t *p = pBuf + byte_offset; // current byte pointer + + if (bit_offset) + *p >>= bit_offset; + + uint8_t usage = useMin; + + bool print_usemin_usemax = ((useMin < useMax) && ((itm & 3) == 2) && pfUsage) ? true : false; + + uint8_t bits_of_byte = 8; + + // for each field in field array defined by rptCount + for (uint8_t field = 0; field < rptCount; field++, usage++) { + + union { + uint8_t bResult[4]; + uint16_t wResult[2]; + uint32_t dwResult; + } result; + + result.dwResult = 0; + uint8_t mask = 0; + + if (print_usemin_usemax) + pfUsage(usage); + + // bits_left - number of bits in the field(array of fields, depending on Report Count) left to process + // bits_of_byte - number of bits in current byte left to process + // bits_to_copy - number of bits to copy to result buffer + + // for each bit in a field + for (uint8_t bits_left = rptSize, bits_to_copy = 0; bits_left; + bits_left -= bits_to_copy) { + bits_to_copy = (bits_left > bits_of_byte) ? bits_of_byte : bits_left; + + result.dwResult <<= bits_to_copy; // Result buffer is shifted by the number of bits to be copied into it + + uint8_t val = *p; + + val >>= (8 - bits_of_byte); // Shift by the number of bits already processed + + mask = 0; + + for (uint8_t j = bits_to_copy; j; j--) { + mask <<= 1; + mask |= 1; + } + + result.bResult[0] = (result.bResult[0] | (val & mask)); + + bits_of_byte -= bits_to_copy; + + if (bits_of_byte < 1) { + bits_of_byte = 8; + p++; + } + } + PrintByteValue(result.dwResult); + } + Notify(PSTR("\r\n"), 0x80); +} + +void UniversalReportParser::Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf) { + ReportDescParser2 prs(len, buf); + + uint8_t ret = hid->GetReportDescr(0, &prs); + + if (ret) + ErrorMessage (PSTR("GetReportDescr-2"), ret); } \ No newline at end of file diff --git a/hidescriptorparser.h b/hidescriptorparser.h index 119a5a66..407f6c7e 100644 --- a/hidescriptorparser.h +++ b/hidescriptorparser.h @@ -1,195 +1,191 @@ -/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. - -This software may be distributed and modified under the terms of the GNU -General Public License version 2 (GPL2) as published by the Free Software -Foundation and appearing in the file GPL2.TXT included in the packaging of -this file. Please note that GPL2 Section 2[b] requires that all works based -on this software must also be made publicly available under the terms of -the GPL2 ("Copyleft"). - -Contact information -------------------- - -Circuits At Home, LTD -Web : http://www.circuitsathome.com -e-mail : support@circuitsathome.com -*/ -#if !defined(__HIDDESCRIPTORPARSER_H__) -#define __HIDDESCRIPTORPARSER_H__ - -#include -#include -#include "avrpins.h" -#include "max3421e.h" -#include "usbhost.h" -#include "usb_ch9.h" -#include "Usb.h" - -#if defined(ARDUINO) && ARDUINO >=100 -#include "Arduino.h" -#else -#include -#endif - -#include "printhex.h" -#include "hexdump.h" -#include "message.h" -#include "confdescparser.h" -#include "hid.h" - -class ReportDescParserBase : public USBReadParser -{ -public: - typedef void (*UsagePageFunc)(uint16_t usage); - - static void PrintGenericDesktopPageUsage(uint16_t usage); - static void PrintSimulationControlsPageUsage(uint16_t usage); - static void PrintVRControlsPageUsage(uint16_t usage); - static void PrintSportsControlsPageUsage(uint16_t usage); - static void PrintGameControlsPageUsage(uint16_t usage); - static void PrintGenericDeviceControlsPageUsage(uint16_t usage); - static void PrintLEDPageUsage(uint16_t usage); - static void PrintButtonPageUsage(uint16_t usage); - static void PrintOrdinalPageUsage(uint16_t usage); - static void PrintTelephonyPageUsage(uint16_t usage); - static void PrintConsumerPageUsage(uint16_t usage); - static void PrintDigitizerPageUsage(uint16_t usage); - static void PrintAlphanumDisplayPageUsage(uint16_t usage); - static void PrintMedicalInstrumentPageUsage(uint16_t usage); - - static void PrintValue(uint8_t *p, uint8_t len); - static void PrintByteValue(uint8_t data); - - static void PrintItemTitle(uint8_t prefix); - - static const char *usagePageTitles0[]; - static const char *usagePageTitles1[]; - static const char *genDesktopTitles0[]; - static const char *genDesktopTitles1[]; - static const char *genDesktopTitles2[]; - static const char *genDesktopTitles3[]; - static const char *genDesktopTitles4[]; - static const char *simuTitles0[]; - static const char *simuTitles1[]; - static const char *simuTitles2[]; - static const char *vrTitles0[]; - static const char *vrTitles1[]; - static const char *sportsCtrlTitles0[]; - static const char *sportsCtrlTitles1[]; - static const char *sportsCtrlTitles2[]; - static const char *gameTitles0[]; - static const char *gameTitles1[]; - static const char *genDevCtrlTitles[]; - static const char *ledTitles[]; - static const char *telTitles0[]; - static const char *telTitles1[]; - static const char *telTitles2[]; - static const char *telTitles3[]; - static const char *telTitles4[]; - static const char *telTitles5[]; - static const char *consTitles0[]; - static const char *consTitles1[]; - static const char *consTitles2[]; - static const char *consTitles3[]; - static const char *consTitles4[]; - static const char *consTitles5[]; - static const char *consTitles6[]; - static const char *consTitles7[]; - static const char *consTitles8[]; - static const char *consTitles9[]; - static const char *consTitlesA[]; - static const char *consTitlesB[]; - static const char *consTitlesC[]; - static const char *consTitlesD[]; - static const char *consTitlesE[]; - static const char *digitTitles0[]; - static const char *digitTitles1[]; - static const char *digitTitles2[]; - static const char *aplphanumTitles0[]; - static const char *aplphanumTitles1[]; - static const char *aplphanumTitles2[]; - static const char *medInstrTitles0[]; - static const char *medInstrTitles1[]; - static const char *medInstrTitles2[]; - static const char *medInstrTitles3[]; - static const char *medInstrTitles4[]; - -protected: - static UsagePageFunc usagePageFunctions[]; - - MultiValueBuffer theBuffer; - MultiByteValueParser valParser; - ByteSkipper theSkipper; - uint8_t varBuffer[sizeof(USB_CONFIGURATION_DESCRIPTOR)]; - - uint8_t itemParseState; // Item parser state variable - uint8_t itemSize; // Item size - uint8_t itemPrefix; // Item prefix (first byte) - uint8_t rptSize; // Report Size - uint8_t rptCount; // Report Count - - uint16_t totalSize; // Report size in bits - - virtual uint8_t ParseItem(uint8_t **pp, uint16_t *pcntdn); - - UsagePageFunc pfUsage; - - static void PrintUsagePage(uint16_t page); - void SetUsagePage(uint16_t page); - -public: - ReportDescParserBase() : - itemParseState(0), - itemSize(0), - itemPrefix(0), - rptSize(0), - rptCount(0), - pfUsage(NULL) - { - theBuffer.pValue = varBuffer; - valParser.Initialize(&theBuffer); - theSkipper.Initialize(&theBuffer); - }; - - virtual void Parse(const uint16_t len, const uint8_t *pbuf, const uint16_t &offset); - - enum - { - enErrorSuccess = 0 - , enErrorIncomplete // value or record is partialy read in buffer - , enErrorBufferTooSmall - }; -}; - -class ReportDescParser : public ReportDescParserBase -{ -}; - -class ReportDescParser2 : public ReportDescParserBase -{ - uint8_t rptId; // Report ID - uint8_t useMin; // Usage Minimum - uint8_t useMax; // Usage Maximum - uint8_t fieldCount; // Number of field being currently processed - - void OnInputItem(uint8_t itm); // Method which is called every time Input item is found - - uint8_t *pBuf; // Report buffer pointer - uint8_t bLen; // Report length - -protected: - virtual uint8_t ParseItem(uint8_t **pp, uint16_t *pcntdn); - -public: - ReportDescParser2(uint16_t len, uint8_t *pbuf) : - ReportDescParserBase(), bLen(len), pBuf(pbuf), rptId(0), useMin(0), useMax(0), fieldCount(0) - {}; -}; - -class UniversalReportParser : public HIDReportParser -{ -public: - virtual void Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf); -}; - +/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. + +This software may be distributed and modified under the terms of the GNU +General Public License version 2 (GPL2) as published by the Free Software +Foundation and appearing in the file GPL2.TXT included in the packaging of +this file. Please note that GPL2 Section 2[b] requires that all works based +on this software must also be made publicly available under the terms of +the GPL2 ("Copyleft"). + +Contact information +------------------- + +Circuits At Home, LTD +Web : http://www.circuitsathome.com +e-mail : support@circuitsathome.com + */ +#if !defined(__HIDDESCRIPTORPARSER_H__) +#define __HIDDESCRIPTORPARSER_H__ + +#include +#include +#include "avrpins.h" +#include "max3421e.h" +#include "usbhost.h" +#include "usb_ch9.h" +#include "Usb.h" + +#if defined(ARDUINO) && ARDUINO >=100 +#include "Arduino.h" +#else +#include +#endif + +#include "printhex.h" +#include "hexdump.h" +#include "message.h" +#include "confdescparser.h" +#include "hid.h" + +class ReportDescParserBase : public USBReadParser { +public: + typedef void (*UsagePageFunc)(uint16_t usage); + + static void PrintGenericDesktopPageUsage(uint16_t usage); + static void PrintSimulationControlsPageUsage(uint16_t usage); + static void PrintVRControlsPageUsage(uint16_t usage); + static void PrintSportsControlsPageUsage(uint16_t usage); + static void PrintGameControlsPageUsage(uint16_t usage); + static void PrintGenericDeviceControlsPageUsage(uint16_t usage); + static void PrintLEDPageUsage(uint16_t usage); + static void PrintButtonPageUsage(uint16_t usage); + static void PrintOrdinalPageUsage(uint16_t usage); + static void PrintTelephonyPageUsage(uint16_t usage); + static void PrintConsumerPageUsage(uint16_t usage); + static void PrintDigitizerPageUsage(uint16_t usage); + static void PrintAlphanumDisplayPageUsage(uint16_t usage); + static void PrintMedicalInstrumentPageUsage(uint16_t usage); + + static void PrintValue(uint8_t *p, uint8_t len); + static void PrintByteValue(uint8_t data); + + static void PrintItemTitle(uint8_t prefix); + + static const char * const usagePageTitles0[]; + static const char * const usagePageTitles1[]; + static const char * const genDesktopTitles0[]; + static const char * const genDesktopTitles1[]; + static const char * const genDesktopTitles2[]; + static const char * const genDesktopTitles3[]; + static const char * const genDesktopTitles4[]; + static const char * const simuTitles0[]; + static const char * const simuTitles1[]; + static const char * const simuTitles2[]; + static const char * const vrTitles0[]; + static const char * const vrTitles1[]; + static const char * const sportsCtrlTitles0[]; + static const char * const sportsCtrlTitles1[]; + static const char * const sportsCtrlTitles2[]; + static const char * const gameTitles0[]; + static const char * const gameTitles1[]; + static const char * const genDevCtrlTitles[]; + static const char * const ledTitles[]; + static const char * const telTitles0[]; + static const char * const telTitles1[]; + static const char * const telTitles2[]; + static const char * const telTitles3[]; + static const char * const telTitles4[]; + static const char * const telTitles5[]; + static const char * const consTitles0[]; + static const char * const consTitles1[]; + static const char * const consTitles2[]; + static const char * const consTitles3[]; + static const char * const consTitles4[]; + static const char * const consTitles5[]; + static const char * const consTitles6[]; + static const char * const consTitles7[]; + static const char * const consTitles8[]; + static const char * const consTitles9[]; + static const char * const consTitlesA[]; + static const char * const consTitlesB[]; + static const char * const consTitlesC[]; + static const char * const consTitlesD[]; + static const char * const consTitlesE[]; + static const char * const digitTitles0[]; + static const char * const digitTitles1[]; + static const char * const digitTitles2[]; + static const char * const aplphanumTitles0[]; + static const char * const aplphanumTitles1[]; + static const char * const aplphanumTitles2[]; + static const char * const medInstrTitles0[]; + static const char * const medInstrTitles1[]; + static const char * const medInstrTitles2[]; + static const char * const medInstrTitles3[]; + static const char * const medInstrTitles4[]; + +protected: + static UsagePageFunc usagePageFunctions[]; + + MultiValueBuffer theBuffer; + MultiByteValueParser valParser; + ByteSkipper theSkipper; + uint8_t varBuffer[sizeof (USB_CONFIGURATION_DESCRIPTOR)]; + + uint8_t itemParseState; // Item parser state variable + uint8_t itemSize; // Item size + uint8_t itemPrefix; // Item prefix (first byte) + uint8_t rptSize; // Report Size + uint8_t rptCount; // Report Count + + uint16_t totalSize; // Report size in bits + + virtual uint8_t ParseItem(uint8_t **pp, uint16_t *pcntdn); + + UsagePageFunc pfUsage; + + static void PrintUsagePage(uint16_t page); + void SetUsagePage(uint16_t page); + +public: + + ReportDescParserBase() : + itemParseState(0), + itemSize(0), + itemPrefix(0), + rptSize(0), + rptCount(0), + pfUsage(NULL) { + theBuffer.pValue = varBuffer; + valParser.Initialize(&theBuffer); + theSkipper.Initialize(&theBuffer); + }; + + virtual void Parse(const uint16_t len, const uint8_t *pbuf, const uint16_t &offset); + + enum { + enErrorSuccess = 0 + , enErrorIncomplete // value or record is partialy read in buffer + , enErrorBufferTooSmall + }; +}; + +class ReportDescParser : public ReportDescParserBase { +}; + +class ReportDescParser2 : public ReportDescParserBase { + uint8_t rptId; // Report ID + uint8_t useMin; // Usage Minimum + uint8_t useMax; // Usage Maximum + uint8_t fieldCount; // Number of field being currently processed + + void OnInputItem(uint8_t itm); // Method which is called every time Input item is found + + uint8_t *pBuf; // Report buffer pointer + uint8_t bLen; // Report length + +protected: + virtual uint8_t ParseItem(uint8_t **pp, uint16_t *pcntdn); + +public: + + ReportDescParser2(uint16_t len, uint8_t *pbuf) : + ReportDescParserBase(), rptId(0), useMin(0), useMax(0), fieldCount(0), pBuf(pbuf), bLen(len) { + }; +}; + +class UniversalReportParser : public HIDReportParser { +public: + virtual void Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf); +}; + #endif // __HIDDESCRIPTORPARSER_H__ \ No newline at end of file diff --git a/hiduniversal.cpp b/hiduniversal.cpp index 9bffe3b7..9cdb8f66 100644 --- a/hiduniversal.cpp +++ b/hiduniversal.cpp @@ -1,418 +1,378 @@ -#include "hiduniversal.h" - -HIDUniversal::HIDUniversal(USB *p) : - HID(p), - qNextPollTime(0), - bPollEnable(false), - bHasReportId(false) -{ - Initialize(); - - if (pUsb) - pUsb->RegisterDeviceClass(this); -} - -uint16_t HIDUniversal::GetHidClassDescrLen(uint8_t type, uint8_t num) -{ - for (uint8_t i=0, n=0; iGetAddressPool(); - - USBTRACE("HU Init\r\n"); - - if (bAddress) - return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE; - - // Get pointer to pseudo device with address 0 assigned - p = addrPool.GetUsbDevicePtr(0); - - if (!p) - return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; - - if (!p->epinfo) - { - USBTRACE("epinfo\r\n"); - return USB_ERROR_EPINFO_IS_NULL; - } - - // Save old pointer to EP_RECORD of address 0 - oldep_ptr = p->epinfo; - - // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence - p->epinfo = epInfo; - - p->lowspeed = lowspeed; - - //delay(200); - - // Get device descriptor - rcode = pUsb->getDevDescr( 0, 0, 8, (uint8_t*)buf ); - - if (!rcode) - len = (buf[0] > constBufSize) ? constBufSize : buf[0]; - - if( rcode ) - { - // Restore p->epinfo - p->epinfo = oldep_ptr; - - goto FailGetDevDescr; - } - - // Restore p->epinfo - p->epinfo = oldep_ptr; - - // Allocate new address according to device class - bAddress = addrPool.AllocAddress(parent, false, port); - - if (!bAddress) - return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; - - // Extract Max Packet Size from the device descriptor - epInfo[0].maxPktSize = (uint8_t)((USB_DEVICE_DESCRIPTOR*)buf)->bMaxPacketSize0; - - // Assign new address to the device - rcode = pUsb->setAddr( 0, 0, bAddress ); - - if (rcode) - { - p->lowspeed = false; - addrPool.FreeAddress(bAddress); - bAddress = 0; - USBTRACE2("setAddr:",rcode); - return rcode; - } - - USBTRACE2("Addr:", bAddress); - - p->lowspeed = false; - - p = addrPool.GetUsbDevicePtr(bAddress); - - if (!p) - return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; - - p->lowspeed = lowspeed; - - delay(500); - - if (len) - rcode = pUsb->getDevDescr( bAddress, 0, len, (uint8_t*)buf ); - - if(rcode) - goto FailGetDevDescr; - - num_of_conf = ((USB_DEVICE_DESCRIPTOR*)buf)->bNumConfigurations; - - // Assign epInfo to epinfo pointer - rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); - - if (rcode) - goto FailSetDevTblEntry; - - USBTRACE2("NC:", num_of_conf); - - for (uint8_t i=0; i HexDump; - ConfigDescParser confDescrParser(this); - - //rcode = pUsb->getConfDescr(bAddress, 0, i, &HexDump); - rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser); - - if (bNumEP > 1) - break; - } // for - - if (bNumEP < 2) - return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; - - // Assign epInfo to epinfo pointer - rcode = pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo); - - USBTRACE2("\r\nCnf:", bConfNum); - - // Set Configuration Value - rcode = pUsb->setConf(bAddress, 0, bConfNum); - - if (rcode) - goto FailSetConfDescr; - - for (uint8_t i=0; i 1 && conf != bConfNum) - return; - - //ErrorMessage(PSTR("\r\nConf.Val"), conf); - //ErrorMessage(PSTR("Iface Num"), iface); - //ErrorMessage(PSTR("Alt.Set"), alt); - - bConfNum = conf; - - uint8_t index = 0; - HIDInterface *piface = FindInterface(iface, alt, proto); - - // Fill in interface structure in case of new interface - if (!piface) - { - piface = hidInterfaces + bNumIface; - piface->bmInterface = iface; - piface->bmAltSet = alt; - piface->bmProtocol = proto; - bNumIface ++; - } - - if ((pep->bmAttributes & 0x03) == 3 && (pep->bEndpointAddress & 0x80) == 0x80) - index = epInterruptInIndex; - else - index = epInterruptOutIndex; - - if (index) - { - // Fill in the endpoint info structure - epInfo[bNumEP].epAddr = (pep->bEndpointAddress & 0x0F); - epInfo[bNumEP].maxPktSize = (uint8_t)pep->wMaxPacketSize; - epInfo[bNumEP].epAttribs = 0; - epInfo[bNumEP].bmNakPower = USB_NAK_NOWAIT; - - // Fill in the endpoint index list - piface->epIndex[index] = bNumEP; //(pep->bEndpointAddress & 0x0F); - - bNumEP ++; - } - //PrintEndpointDescriptor(pep); -} - - -uint8_t HIDUniversal::Release() -{ - pUsb->GetAddressPool().FreeAddress(bAddress); - - bNumEP = 1; - bAddress = 0; - qNextPollTime = 0; - bPollEnable = false; - return 0; -} - -bool HIDUniversal::BuffersIdentical(uint8_t len, uint8_t *buf1, uint8_t *buf2) -{ - for (uint8_t i=0; iinTransfer(bAddress, epInfo[index].epAddr, &read, buf); - - if (rcode) - { - if (rcode != hrNAK) - USBTRACE2("Poll:", rcode); - return rcode; - } - - if (read > constBuffLen) - read = constBuffLen; - - bool identical = BuffersIdentical(read, buf, prevBuf); - - SaveBuffer(read, buf, prevBuf); - - if (identical) - return 0; - - Serial.print("\r\nBuf: "); - - for (uint8_t i=0; i(buf[i]); - - Serial.println(""); - - HIDReportParser *prs = GetReportParser( ((bHasReportId) ? *buf : 0) ); - - if (prs) - prs->Parse(this, bHasReportId, (uint8_t)read, buf); - } - } - return rcode; -} +#include "hiduniversal.h" + +HIDUniversal::HIDUniversal(USB *p) : +HID(p), +qNextPollTime(0), +bPollEnable(false), +bHasReportId(false) { + Initialize(); + + if (pUsb) + pUsb->RegisterDeviceClass(this); +} + +uint16_t HIDUniversal::GetHidClassDescrLen(uint8_t type, uint8_t num) { + for (uint8_t i = 0, n = 0; i < HID_MAX_HID_CLASS_DESCRIPTORS; i++) { + if (descrInfo[i].bDescrType == type) { + if (n == num) + return descrInfo[i].wDescriptorLength; + n++; + } + } + return 0; +} + +void HIDUniversal::Initialize() { + for (uint8_t i = 0; i < MAX_REPORT_PARSERS; i++) { + rptParsers[i].rptId = 0; + rptParsers[i].rptParser = NULL; + } + for (uint8_t i = 0; i < HID_MAX_HID_CLASS_DESCRIPTORS; i++) { + descrInfo[i].bDescrType = 0; + descrInfo[i].wDescriptorLength = 0; + } + for (uint8_t i = 0; i < maxHidInterfaces; i++) { + hidInterfaces[i].bmInterface = 0; + hidInterfaces[i].bmProtocol = 0; + + for (uint8_t j = 0; j < maxEpPerInterface; j++) + hidInterfaces[i].epIndex[j] = 0; + } + for (uint8_t i = 0; i < totalEndpoints; i++) { + epInfo[i].epAddr = 0; + epInfo[i].maxPktSize = (i) ? 0 : 8; + epInfo[i].epAttribs = 0; + epInfo[i].bmNakPower = (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER; + } + bNumEP = 1; + bNumIface = 0; + bConfNum = 0; + + ZeroMemory(constBuffLen, prevBuf); +} + +bool HIDUniversal::SetReportParser(uint8_t id, HIDReportParser *prs) { + for (uint8_t i = 0; i < MAX_REPORT_PARSERS; i++) { + if (rptParsers[i].rptId == 0 && rptParsers[i].rptParser == NULL) { + rptParsers[i].rptId = id; + rptParsers[i].rptParser = prs; + return true; + } + } + return false; +} + +HIDReportParser* HIDUniversal::GetReportParser(uint8_t id) { + if (!bHasReportId) + return ((rptParsers[0].rptParser) ? rptParsers[0].rptParser : NULL); + + for (uint8_t i = 0; i < MAX_REPORT_PARSERS; i++) { + if (rptParsers[i].rptId == id) + return rptParsers[i].rptParser; + } + return NULL; +} + +uint8_t HIDUniversal::Init(uint8_t parent, uint8_t port, bool lowspeed) { + const uint8_t constBufSize = sizeof (USB_DEVICE_DESCRIPTOR); + + uint8_t buf[constBufSize]; + uint8_t rcode; + UsbDevice *p = NULL; + EpInfo *oldep_ptr = NULL; + uint8_t len = 0; + + uint8_t num_of_conf; // number of configurations + //uint8_t num_of_intf; // number of interfaces + + AddressPool &addrPool = pUsb->GetAddressPool(); + + USBTRACE("HU Init\r\n"); + + if (bAddress) + return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE; + + // Get pointer to pseudo device with address 0 assigned + p = addrPool.GetUsbDevicePtr(0); + + if (!p) + return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; + + if (!p->epinfo) { + USBTRACE("epinfo\r\n"); + return USB_ERROR_EPINFO_IS_NULL; + } + + // Save old pointer to EP_RECORD of address 0 + oldep_ptr = p->epinfo; + + // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence + p->epinfo = epInfo; + + p->lowspeed = lowspeed; + + // Get device descriptor + rcode = pUsb->getDevDescr(0, 0, 8, (uint8_t*) buf); + + if (!rcode) + len = (buf[0] > constBufSize) ? constBufSize : buf[0]; + + if (rcode) { + // Restore p->epinfo + p->epinfo = oldep_ptr; + + goto FailGetDevDescr; + } + + // Restore p->epinfo + p->epinfo = oldep_ptr; + + // Allocate new address according to device class + bAddress = addrPool.AllocAddress(parent, false, port); + + if (!bAddress) + return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; + + // Extract Max Packet Size from the device descriptor + epInfo[0].maxPktSize = (uint8_t) ((USB_DEVICE_DESCRIPTOR*) buf)->bMaxPacketSize0; + + // Assign new address to the device + rcode = pUsb->setAddr(0, 0, bAddress); + + if (rcode) { + p->lowspeed = false; + addrPool.FreeAddress(bAddress); + bAddress = 0; + USBTRACE2("setAddr:", rcode); + return rcode; + } + + USBTRACE2("Addr:", bAddress); + + p->lowspeed = false; + + p = addrPool.GetUsbDevicePtr(bAddress); + + if (!p) + return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; + + p->lowspeed = lowspeed; + + if (len) + rcode = pUsb->getDevDescr(bAddress, 0, len, (uint8_t*) buf); + + if (rcode) + goto FailGetDevDescr; + + num_of_conf = ((USB_DEVICE_DESCRIPTOR*) buf)->bNumConfigurations; + + // Assign epInfo to epinfo pointer + rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); + + if (rcode) + goto FailSetDevTblEntry; + + USBTRACE2("NC:", num_of_conf); + + for (uint8_t i = 0; i < num_of_conf; i++) { + //HexDumper HexDump; + ConfigDescParser confDescrParser(this); + + //rcode = pUsb->getConfDescr(bAddress, 0, i, &HexDump); + rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser); + + if (rcode) + goto FailGetConfDescr; + + if (bNumEP > 1) + break; + } // for + + if (bNumEP < 2) + return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; + + // Assign epInfo to epinfo pointer + rcode = pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo); + + USBTRACE2("\r\nCnf:", bConfNum); + + // Set Configuration Value + rcode = pUsb->setConf(bAddress, 0, bConfNum); + + if (rcode) + goto FailSetConfDescr; + + for (uint8_t i = 0; i < bNumIface; i++) { + if (hidInterfaces[i].epIndex[epInterruptInIndex] == 0) + continue; + + rcode = SetIdle(hidInterfaces[i].bmInterface, 0, 0); + + if (rcode && rcode != hrSTALL) + goto FailSetIdle; + } + + USBTRACE("HU configured\r\n"); + + OnInitSuccessful(); + + bPollEnable = true; + return 0; + +FailGetDevDescr: + USBTRACE("getDevDescr:"); + goto Fail; + +FailSetDevTblEntry: + USBTRACE("setDevTblEn:"); + goto Fail; + +FailGetConfDescr: + USBTRACE("getConf:"); + goto Fail; + +FailSetConfDescr: + USBTRACE("setConf:"); + goto Fail; + +FailSetIdle: + USBTRACE("SetIdle:"); + goto Fail; + +Fail: + PrintHex (rcode, 0x80); + Notify(PSTR("\r\n"), 0x80); + //Serial.println(rcode, HEX); + Release(); + return rcode; +} + +HIDUniversal::HIDInterface* HIDUniversal::FindInterface(uint8_t iface, uint8_t alt, uint8_t proto) { + for (uint8_t i = 0; i < bNumIface && i < maxHidInterfaces; i++) + if (hidInterfaces[i].bmInterface == iface && hidInterfaces[i].bmAltSet == alt + && hidInterfaces[i].bmProtocol == proto) + return hidInterfaces + i; + return NULL; +} + +void HIDUniversal::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *pep) { + // If the first configuration satisfies, the others are not concidered. + if (bNumEP > 1 && conf != bConfNum) + return; + + //ErrorMessage(PSTR("\r\nConf.Val"), conf); + //ErrorMessage(PSTR("Iface Num"), iface); + //ErrorMessage(PSTR("Alt.Set"), alt); + + bConfNum = conf; + + uint8_t index = 0; + HIDInterface *piface = FindInterface(iface, alt, proto); + + // Fill in interface structure in case of new interface + if (!piface) { + piface = hidInterfaces + bNumIface; + piface->bmInterface = iface; + piface->bmAltSet = alt; + piface->bmProtocol = proto; + bNumIface++; + } + + if ((pep->bmAttributes & 0x03) == 3 && (pep->bEndpointAddress & 0x80) == 0x80) + index = epInterruptInIndex; + else + index = epInterruptOutIndex; + + if (index) { + // Fill in the endpoint info structure + epInfo[bNumEP].epAddr = (pep->bEndpointAddress & 0x0F); + epInfo[bNumEP].maxPktSize = (uint8_t) pep->wMaxPacketSize; + epInfo[bNumEP].epAttribs = 0; + epInfo[bNumEP].bmNakPower = USB_NAK_NOWAIT; + + // Fill in the endpoint index list + piface->epIndex[index] = bNumEP; //(pep->bEndpointAddress & 0x0F); + + bNumEP++; + } + //PrintEndpointDescriptor(pep); +} + +uint8_t HIDUniversal::Release() { + pUsb->GetAddressPool().FreeAddress(bAddress); + + bNumEP = 1; + bAddress = 0; + qNextPollTime = 0; + bPollEnable = false; + return 0; +} + +bool HIDUniversal::BuffersIdentical(uint8_t len, uint8_t *buf1, uint8_t *buf2) { + for (uint8_t i = 0; i < len; i++) + if (buf1[i] != buf2[i]) + return false; + return true; +} + +void HIDUniversal::ZeroMemory(uint8_t len, uint8_t *buf) { + for (uint8_t i = 0; i < len; i++) + buf[i] = 0; +} + +void HIDUniversal::SaveBuffer(uint8_t len, uint8_t *src, uint8_t *dest) { + for (uint8_t i = 0; i < len; i++) + dest[i] = src[i]; +} + +uint8_t HIDUniversal::Poll() { + uint8_t rcode = 0; + + if (!bPollEnable) + return 0; + + if (qNextPollTime <= millis()) { + qNextPollTime = millis() + 50; + + uint8_t buf[constBuffLen]; + + for (uint8_t i = 0; i < bNumIface; i++) { + uint8_t index = hidInterfaces[i].epIndex[epInterruptInIndex]; + uint16_t read = (uint16_t) epInfo[index].maxPktSize; + + ZeroMemory(constBuffLen, buf); + + uint8_t rcode = pUsb->inTransfer(bAddress, epInfo[index].epAddr, &read, buf); + + if (rcode) { + if (rcode != hrNAK) + USBTRACE2("Poll:", rcode); + return rcode; + } + + if (read > constBuffLen) + read = constBuffLen; + + bool identical = BuffersIdentical(read, buf, prevBuf); + + SaveBuffer(read, buf, prevBuf); + + if (identical) + return 0; + + Notify(PSTR("\r\nBuf: "), 0x80); + + for (uint8_t i = 0; i < read; i++) + PrintHex (buf[i], 0x80); + + Notify(PSTR("\r\n"), 0x80); + + HIDReportParser *prs = GetReportParser(((bHasReportId) ? *buf : 0)); + + if (prs) + prs->Parse(this, bHasReportId, (uint8_t) read, buf); + } + } + return rcode; +} diff --git a/hiduniversal.h b/hiduniversal.h index 9b64af37..e1ea26c4 100644 --- a/hiduniversal.h +++ b/hiduniversal.h @@ -1,75 +1,79 @@ -#if !defined(__HIDUNIVERSAL_H__) -#define __HIDUNIVERSAL_H__ - -#include "hid.h" -//#include "hidescriptorparser.h" - -class HIDUniversal : public HID -{ - struct ReportParser - { - uint8_t rptId; - HIDReportParser *rptParser; - } rptParsers[MAX_REPORT_PARSERS]; - - // HID class specific descriptor type and length info obtained from HID descriptor - HID_CLASS_DESCRIPTOR_LEN_AND_TYPE descrInfo[HID_MAX_HID_CLASS_DESCRIPTORS]; - - // Returns HID class specific descriptor length by its type and order number - uint16_t GetHidClassDescrLen(uint8_t type, uint8_t num); - - EpInfo epInfo[totalEndpoints]; - - struct HIDInterface - { - struct - { - uint8_t bmInterface : 3; - uint8_t bmAltSet : 3; - uint8_t bmProtocol : 2; - }; - uint8_t epIndex[maxEpPerInterface]; - }; - - HIDInterface hidInterfaces[maxHidInterfaces]; - - uint8_t bConfNum; // configuration number - uint8_t bNumIface; // number of interfaces in the configuration - uint8_t bNumEP; // total number of EP in the configuration - uint32_t qNextPollTime; // next poll time - bool bPollEnable; // poll enable flag - - static const uint16_t constBuffLen = 64; // event buffer length - uint8_t prevBuf[constBuffLen]; // previous event buffer - - void Initialize(); - HIDInterface* FindInterface(uint8_t iface, uint8_t alt, uint8_t proto); - - void ZeroMemory(uint8_t len, uint8_t *buf); - bool BuffersIdentical(uint8_t len, uint8_t *buf1, uint8_t *buf2); - void SaveBuffer(uint8_t len, uint8_t *src, uint8_t *dest); - -protected: - bool bHasReportId; - - // HID implementation - virtual HIDReportParser* GetReportParser(uint8_t id); - virtual uint8_t OnInitSuccessful() { return 0; }; - -public: - HIDUniversal(USB *p); - - // HID implementation - virtual bool SetReportParser(uint8_t id, HIDReportParser *prs); - - // USBDeviceConfig implementation - virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed); - virtual uint8_t Release(); - virtual uint8_t Poll(); - virtual uint8_t GetAddress() { return bAddress; }; - - // UsbConfigXtracter implementation - virtual void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep); -}; - +#if !defined(__HIDUNIVERSAL_H__) +#define __HIDUNIVERSAL_H__ + +#include "hid.h" +//#include "hidescriptorparser.h" + +class HIDUniversal : public HID { + + struct ReportParser { + uint8_t rptId; + HIDReportParser *rptParser; + } rptParsers[MAX_REPORT_PARSERS]; + + // HID class specific descriptor type and length info obtained from HID descriptor + HID_CLASS_DESCRIPTOR_LEN_AND_TYPE descrInfo[HID_MAX_HID_CLASS_DESCRIPTORS]; + + // Returns HID class specific descriptor length by its type and order number + uint16_t GetHidClassDescrLen(uint8_t type, uint8_t num); + + EpInfo epInfo[totalEndpoints]; + + struct HIDInterface { + + struct { + uint8_t bmInterface : 3; + uint8_t bmAltSet : 3; + uint8_t bmProtocol : 2; + }; + uint8_t epIndex[maxEpPerInterface]; + }; + + HIDInterface hidInterfaces[maxHidInterfaces]; + + uint8_t bConfNum; // configuration number + uint8_t bNumIface; // number of interfaces in the configuration + uint8_t bNumEP; // total number of EP in the configuration + uint32_t qNextPollTime; // next poll time + bool bPollEnable; // poll enable flag + + static const uint16_t constBuffLen = 64; // event buffer length + uint8_t prevBuf[constBuffLen]; // previous event buffer + + void Initialize(); + HIDInterface* FindInterface(uint8_t iface, uint8_t alt, uint8_t proto); + + void ZeroMemory(uint8_t len, uint8_t *buf); + bool BuffersIdentical(uint8_t len, uint8_t *buf1, uint8_t *buf2); + void SaveBuffer(uint8_t len, uint8_t *src, uint8_t *dest); + +protected: + bool bHasReportId; + + // HID implementation + virtual HIDReportParser* GetReportParser(uint8_t id); + + virtual uint8_t OnInitSuccessful() { + return 0; + }; + +public: + HIDUniversal(USB *p); + + // HID implementation + virtual bool SetReportParser(uint8_t id, HIDReportParser *prs); + + // USBDeviceConfig implementation + virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed); + virtual uint8_t Release(); + virtual uint8_t Poll(); + + virtual uint8_t GetAddress() { + return bAddress; + }; + + // UsbConfigXtracter implementation + virtual void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep); +}; + #endif // __HIDUNIVERSAL_H__ \ No newline at end of file diff --git a/hidusagestr.h b/hidusagestr.h index b150f26a..6c137e02 100644 --- a/hidusagestr.h +++ b/hidusagestr.h @@ -1,977 +1,977 @@ -/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. - -This software may be distributed and modified under the terms of the GNU -General Public License version 2 (GPL2) as published by the Free Software -Foundation and appearing in the file GPL2.TXT included in the packaging of -this file. Please note that GPL2 Section 2[b] requires that all works based -on this software must also be made publicly available under the terms of -the GPL2 ("Copyleft"). - -Contact information -------------------- - -Circuits At Home, LTD -Web : http://www.circuitsathome.com -e-mail : support@circuitsathome.com -*/ -#if !defined( __HIDUSAGESTR_H__) -#define __HIDUSAGESTR_H__ - -#include - -const char pstrSpace [] PROGMEM = " "; -const char pstrCRLF [] PROGMEM = "\r\n"; -const char pstrSingleTab [] PROGMEM = "\t"; -const char pstrDoubleTab [] PROGMEM = "\t\t"; -const char pstrTripleTab [] PROGMEM = "\t\t\t"; - -// Usage Page String Titles -const char pstrUsagePageUndefined [] PROGMEM = "Undef"; -const char pstrUsagePageGenericDesktopControls [] PROGMEM = "Gen Desktop Ctrls"; -const char pstrUsagePageSimulationControls [] PROGMEM = "Simu Ctrls"; -const char pstrUsagePageVRControls [] PROGMEM = "VR Ctrls"; -const char pstrUsagePageSportControls [] PROGMEM = "Sport Ctrls"; -const char pstrUsagePageGameControls [] PROGMEM = "Game Ctrls"; -const char pstrUsagePageGenericDeviceControls [] PROGMEM = "Gen Dev Ctrls"; -const char pstrUsagePageKeyboardKeypad [] PROGMEM = "Kbrd/Keypad"; -const char pstrUsagePageLEDs [] PROGMEM = "LEDs"; -const char pstrUsagePageButton [] PROGMEM = "Button"; -const char pstrUsagePageOrdinal [] PROGMEM = "Ordinal"; -const char pstrUsagePageTelephone [] PROGMEM = "Tel"; -const char pstrUsagePageConsumer [] PROGMEM = "Consumer"; -const char pstrUsagePageDigitizer [] PROGMEM = "Digitizer"; -const char pstrUsagePagePID [] PROGMEM = "PID"; -const char pstrUsagePageUnicode [] PROGMEM = "Unicode"; -const char pstrUsagePageAlphaNumericDisplay [] PROGMEM = "Alpha Num Disp"; -const char pstrUsagePageMedicalInstruments [] PROGMEM = "Medical Instr"; -const char pstrUsagePageMonitor [] PROGMEM = "Monitor"; -const char pstrUsagePagePower [] PROGMEM = "Power"; -const char pstrUsagePageBarCodeScanner [] PROGMEM = "Bar Code Scan"; -const char pstrUsagePageScale [] PROGMEM = "Scale"; -const char pstrUsagePageMSRDevices [] PROGMEM = "Magn Stripe Read Dev"; -const char pstrUsagePagePointOfSale [] PROGMEM = "POS"; -const char pstrUsagePageCameraControl [] PROGMEM = "Cam Ctrl"; -const char pstrUsagePageArcade [] PROGMEM = "Arcade"; -const char pstrUsagePageReserved [] PROGMEM = "Reserved"; -const char pstrUsagePageVendorDefined [] PROGMEM = "Vendor Def"; - -// Generic Desktop Controls Page -const char pstrUsagePointer [] PROGMEM = "Pointer"; -const char pstrUsageMouse [] PROGMEM = "Mouse"; -const char pstrUsageJoystick [] PROGMEM = "Joystick"; -const char pstrUsageGamePad [] PROGMEM = "Game Pad"; -const char pstrUsageKeyboard [] PROGMEM = "Kbrd"; -const char pstrUsageKeypad [] PROGMEM = "Keypad"; -const char pstrUsageMultiAxisController [] PROGMEM = "Multi-axis Ctrl"; -const char pstrUsageTabletPCSystemControls [] PROGMEM = "Tablet PC Sys Ctrls"; -const char pstrUsageX [] PROGMEM = "X"; -const char pstrUsageY [] PROGMEM = "Y"; -const char pstrUsageZ [] PROGMEM = "Z"; -const char pstrUsageRx [] PROGMEM = "Rx"; -const char pstrUsageRy [] PROGMEM = "Ry"; -const char pstrUsageRz [] PROGMEM = "Rz"; -const char pstrUsageSlider [] PROGMEM = "Slider"; -const char pstrUsageDial [] PROGMEM = "Dial"; -const char pstrUsageWheel [] PROGMEM = "Wheel"; -const char pstrUsageHatSwitch [] PROGMEM = "Hat Switch"; -const char pstrUsageCountedBuffer [] PROGMEM = "Counted Buf"; -const char pstrUsageByteCount [] PROGMEM = "Byte Count"; -const char pstrUsageMotionWakeup [] PROGMEM = "Motion Wakeup"; -const char pstrUsageStart [] PROGMEM = "Start"; -const char pstrUsageSelect [] PROGMEM = "Sel"; -const char pstrUsageVx [] PROGMEM = "Vx"; -const char pstrUsageVy [] PROGMEM = "Vy"; -const char pstrUsageVz [] PROGMEM = "Vz"; -const char pstrUsageVbrx [] PROGMEM = "Vbrx"; -const char pstrUsageVbry [] PROGMEM = "Vbry"; -const char pstrUsageVbrz [] PROGMEM = "Vbrz"; -const char pstrUsageVno [] PROGMEM = "Vno"; -const char pstrUsageFeatureNotification [] PROGMEM = "Feature Notif"; -const char pstrUsageResolutionMultiplier [] PROGMEM = "Res Mult"; -const char pstrUsageSystemControl [] PROGMEM = "Sys Ctrl"; -const char pstrUsageSystemPowerDown [] PROGMEM = "Sys Pwr Down"; -const char pstrUsageSystemSleep [] PROGMEM = "Sys Sleep"; -const char pstrUsageSystemWakeup [] PROGMEM = "Sys Wakeup"; -const char pstrUsageSystemContextMenu [] PROGMEM = "Sys Context Menu"; -const char pstrUsageSystemMainMenu [] PROGMEM = "Sys Main Menu"; -const char pstrUsageSystemAppMenu [] PROGMEM = "Sys App Menu"; -const char pstrUsageSystemMenuHelp [] PROGMEM = "Sys Menu Help"; -const char pstrUsageSystemMenuExit [] PROGMEM = "Sys Menu Exit"; -const char pstrUsageSystemMenuSelect [] PROGMEM = "Sys Menu Select"; -const char pstrUsageSystemMenuRight [] PROGMEM = "Sys Menu Right"; -const char pstrUsageSystemMenuLeft [] PROGMEM = "Sys Menu Left"; -const char pstrUsageSystemMenuUp [] PROGMEM = "Sys Menu Up"; -const char pstrUsageSystemMenuDown [] PROGMEM = "Sys Menu Down"; -const char pstrUsageSystemColdRestart [] PROGMEM = "Sys Cold Restart"; -const char pstrUsageSystemWarmRestart [] PROGMEM = "Sys Warm Restart"; -const char pstrUsageDPadUp [] PROGMEM = "D-pad Up"; -const char pstrUsageDPadDown [] PROGMEM = "D-pad Down"; -const char pstrUsageDPadRight [] PROGMEM = "D-pad Right"; -const char pstrUsageDPadLeft [] PROGMEM = "D-pad Left"; -const char pstrUsageSystemDock [] PROGMEM = "Sys Dock"; -const char pstrUsageSystemUndock [] PROGMEM = "Sys Undock"; -const char pstrUsageSystemSetup [] PROGMEM = "Sys Setup"; -const char pstrUsageSystemBreak [] PROGMEM = "Sys Break"; -const char pstrUsageSystemDebuggerBreak [] PROGMEM = "Sys Dbg Brk"; -const char pstrUsageApplicationBreak [] PROGMEM = "App Break"; -const char pstrUsageApplicationDebuggerBreak [] PROGMEM = "App Dbg Brk"; -const char pstrUsageSystemSpeakerMute [] PROGMEM = "Sys Spk Mute"; -const char pstrUsageSystemHibernate [] PROGMEM = "Sys Hiber"; -const char pstrUsageSystemDisplayInvert [] PROGMEM = "Sys Disp Inv"; -const char pstrUsageSystemDisplayInternal [] PROGMEM = "Sys Disp Int"; -const char pstrUsageSystemDisplayExternal [] PROGMEM = "Sys Disp Ext"; -const char pstrUsageSystemDisplayBoth [] PROGMEM = "Sys Disp Both"; -const char pstrUsageSystemDisplayDual [] PROGMEM = "Sys Disp Dual"; -const char pstrUsageSystemDisplayToggleIntExt [] PROGMEM = "Sys Disp Tgl Int/Ext"; -const char pstrUsageSystemDisplaySwapPriSec [] PROGMEM = "Sys Disp Swap Pri/Sec"; -const char pstrUsageSystemDisplayLCDAutoscale [] PROGMEM = "Sys Disp LCD Autoscale"; - -// Simulation Controls Page -const char pstrUsageFlightSimulationDevice [] PROGMEM = "Flight Simu Dev"; -const char pstrUsageAutomobileSimulationDevice [] PROGMEM = "Auto Simu Dev"; -const char pstrUsageTankSimulationDevice [] PROGMEM = "Tank Simu Dev"; -const char pstrUsageSpaceshipSimulationDevice [] PROGMEM = "Space Simu Dev"; -const char pstrUsageSubmarineSimulationDevice [] PROGMEM = "Subm Simu Dev"; -const char pstrUsageSailingSimulationDevice [] PROGMEM = "Sail Simu Dev"; -const char pstrUsageMotocicleSimulationDevice [] PROGMEM = "Moto Simu Dev"; -const char pstrUsageSportsSimulationDevice [] PROGMEM = "Sport Simu Dev"; -const char pstrUsageAirplaneSimulationDevice [] PROGMEM = "Airp Simu Dev"; -const char pstrUsageHelicopterSimulationDevice [] PROGMEM = "Heli Simu Dev"; -const char pstrUsageMagicCarpetSimulationDevice [] PROGMEM = "Magic Carpet Simu Dev"; -const char pstrUsageBicycleSimulationDevice [] PROGMEM = "Bike Simu Dev"; -const char pstrUsageFlightControlStick [] PROGMEM = "Flight Ctrl Stick"; -const char pstrUsageFlightStick [] PROGMEM = "Flight Stick"; -const char pstrUsageCyclicControl [] PROGMEM = "Cyclic Ctrl"; -const char pstrUsageCyclicTrim [] PROGMEM = "Cyclic Trim"; -const char pstrUsageFlightYoke [] PROGMEM = "Flight Yoke"; -const char pstrUsageTrackControl [] PROGMEM = "Track Ctrl"; -const char pstrUsageAileron [] PROGMEM = "Aileron"; -const char pstrUsageAileronTrim [] PROGMEM = "Aileron Trim"; -const char pstrUsageAntiTorqueControl [] PROGMEM = "Anti-Torque Ctrl"; -const char pstrUsageAutopilotEnable [] PROGMEM = "Autopilot Enable"; -const char pstrUsageChaffRelease [] PROGMEM = "Chaff Release"; -const char pstrUsageCollectiveControl [] PROGMEM = "Collective Ctrl"; -const char pstrUsageDiveBrake [] PROGMEM = "Dive Brake"; -const char pstrUsageElectronicCountermeasures [] PROGMEM = "El Countermeasures"; -const char pstrUsageElevator [] PROGMEM = "Elevator"; -const char pstrUsageElevatorTrim [] PROGMEM = "Elevator Trim"; -const char pstrUsageRudder [] PROGMEM = "Rudder"; -const char pstrUsageThrottle [] PROGMEM = "Throttle"; -const char pstrUsageFlightCommunications [] PROGMEM = "Flight Comm"; -const char pstrUsageFlareRelease [] PROGMEM = "Flare Release"; -const char pstrUsageLandingGear [] PROGMEM = "Landing Gear"; -const char pstrUsageToeBrake [] PROGMEM = "Toe Brake"; -const char pstrUsageTrigger [] PROGMEM = "Trigger"; -const char pstrUsageWeaponsArm [] PROGMEM = "Weapons Arm"; -const char pstrUsageWeaponsSelect [] PROGMEM = "Weapons Sel"; -const char pstrUsageWingFlaps [] PROGMEM = "Wing Flaps"; -const char pstrUsageAccelerator [] PROGMEM = "Accel"; -const char pstrUsageBrake [] PROGMEM = "Brake"; -const char pstrUsageClutch [] PROGMEM = "Clutch"; -const char pstrUsageShifter [] PROGMEM = "Shifter"; -const char pstrUsageSteering [] PROGMEM = "Steering"; -const char pstrUsageTurretDirection [] PROGMEM = "Turret Dir"; -const char pstrUsageBarrelElevation [] PROGMEM = "Barrel Ele"; -const char pstrUsageDivePlane [] PROGMEM = "Dive Plane"; -const char pstrUsageBallast [] PROGMEM = "Ballast"; -const char pstrUsageBicycleCrank [] PROGMEM = "Bicycle Crank"; -const char pstrUsageHandleBars [] PROGMEM = "Handle Bars"; -const char pstrUsageFrontBrake [] PROGMEM = "Front Brake"; -const char pstrUsageRearBrake [] PROGMEM = "Rear Brake"; - -// VR Controls Page -const char pstrUsageBelt [] PROGMEM = "Belt"; -const char pstrUsageBodySuit [] PROGMEM = "Body Suit"; -const char pstrUsageFlexor [] PROGMEM = "Flexor"; -const char pstrUsageGlove [] PROGMEM = "Glove"; -const char pstrUsageHeadTracker [] PROGMEM = "Head Track"; -const char pstrUsageHeadMountedDisplay [] PROGMEM = "Head Disp"; -const char pstrUsageHandTracker [] PROGMEM = "Hand Track"; -const char pstrUsageOculometer [] PROGMEM = "Oculometer"; -const char pstrUsageVest [] PROGMEM = "Vest"; -const char pstrUsageAnimatronicDevice [] PROGMEM = "Animat Dev"; -const char pstrUsageStereoEnable [] PROGMEM = "Stereo Enbl"; -const char pstrUsageDisplayEnable [] PROGMEM = "Display Enbl"; - -// Sport Controls Page -const char pstrUsageBaseballBat [] PROGMEM = "Baseball Bat"; -const char pstrUsageGolfClub [] PROGMEM = "Golf Club"; -const char pstrUsageRowingMachine [] PROGMEM = "Rowing Mach"; -const char pstrUsageTreadmill [] PROGMEM = "Treadmill"; -const char pstrUsageOar [] PROGMEM = "Oar"; -const char pstrUsageSlope [] PROGMEM = "Slope"; -const char pstrUsageRate [] PROGMEM = "Rate"; -const char pstrUsageStickSpeed [] PROGMEM = "Stick Speed"; -const char pstrUsageStickFaceAngle [] PROGMEM = "Stick Face Ang"; -const char pstrUsageStickHeelToe [] PROGMEM = "Stick Heel/Toe"; -const char pstrUsageStickFollowThough [] PROGMEM = "Stick Flw Thru"; -const char pstrUsageStickTempo [] PROGMEM = "Stick Tempo"; -const char pstrUsageStickType [] PROGMEM = "Stick Type"; -const char pstrUsageStickHeight [] PROGMEM = "Stick Hght"; -const char pstrUsagePutter [] PROGMEM = "Putter"; -const char pstrUsage1Iron [] PROGMEM = "1 Iron"; -const char pstrUsage2Iron [] PROGMEM = "2 Iron"; -const char pstrUsage3Iron [] PROGMEM = "3 Iron"; -const char pstrUsage4Iron [] PROGMEM = "4 Iron"; -const char pstrUsage5Iron [] PROGMEM = "5 Iron"; -const char pstrUsage6Iron [] PROGMEM = "6 Iron"; -const char pstrUsage7Iron [] PROGMEM = "7 Iron"; -const char pstrUsage8Iron [] PROGMEM = "8 Iron"; -const char pstrUsage9Iron [] PROGMEM = "9 Iron"; -const char pstrUsage10Iron [] PROGMEM = "10 Iron"; -const char pstrUsage11Iron [] PROGMEM = "11 Iron"; -const char pstrUsageSandWedge [] PROGMEM = "Sand Wedge"; -const char pstrUsageLoftWedge [] PROGMEM = "Loft Wedge"; -const char pstrUsagePowerWedge [] PROGMEM = "Pwr Wedge"; -const char pstrUsage1Wood [] PROGMEM = "1 Wood"; -const char pstrUsage3Wood [] PROGMEM = "3 Wood"; -const char pstrUsage5Wood [] PROGMEM = "5 Wood"; -const char pstrUsage7Wood [] PROGMEM = "7 Wood"; -const char pstrUsage9Wood [] PROGMEM = "9 Wood"; - -// Game Controls Page -const char pstrUsage3DGameController [] PROGMEM = "3D Game Ctrl"; -const char pstrUsagePinballDevice [] PROGMEM = "Pinball Dev"; -const char pstrUsageGunDevice [] PROGMEM = "Gun Dev"; -const char pstrUsagePointOfView [] PROGMEM = "POV"; -const char pstrUsageTurnRightLeft [] PROGMEM = "Turn Right Left"; -const char pstrUsagePitchForwardBackward [] PROGMEM = "Pitch Fwd/Back"; -const char pstrUsageRollRightLeft [] PROGMEM = "Roll Right/Left"; -const char pstrUsageMoveRightLeft [] PROGMEM = "Move Right/Left"; -const char pstrUsageMoveForwardBackward [] PROGMEM = "Move Fwd/Back"; -const char pstrUsageMoveUpDown [] PROGMEM = "Move Up/Down"; -const char pstrUsageLeanRightLeft [] PROGMEM = "Lean Right/Left"; -const char pstrUsageLeanForwardBackward [] PROGMEM = "Lean Fwd/Back"; -const char pstrUsageHeightOfPOV [] PROGMEM = "Height of POV"; -const char pstrUsageFlipper [] PROGMEM = "Flipper"; -const char pstrUsageSecondaryFlipper [] PROGMEM = "Second Flipper"; -const char pstrUsageBump [] PROGMEM = "Bump"; -const char pstrUsageNewGame [] PROGMEM = "New Game"; -const char pstrUsageShootBall [] PROGMEM = "Shoot Ball"; -const char pstrUsagePlayer [] PROGMEM = "Player"; -const char pstrUsageGunBolt [] PROGMEM = "Gun Bolt"; -const char pstrUsageGunClip [] PROGMEM = "Gun Clip"; -const char pstrUsageGunSelector [] PROGMEM = "Gun Sel"; -const char pstrUsageGunSingleShot [] PROGMEM = "Gun Sngl Shot"; -const char pstrUsageGunBurst [] PROGMEM = "Gun Burst"; -const char pstrUsageGunAutomatic [] PROGMEM = "Gun Auto"; -const char pstrUsageGunSafety [] PROGMEM = "Gun Safety"; -const char pstrUsageGamepadFireJump [] PROGMEM = "Gamepad Fire/Jump"; -const char pstrUsageGamepadTrigger [] PROGMEM = "Gamepad Trig"; - -// Generic Device Controls Page -const char pstrUsageBatteryStrength [] PROGMEM = "Bat Strength"; -const char pstrUsageWirelessChannel [] PROGMEM = "Wireless Ch"; -const char pstrUsageWirelessID [] PROGMEM = "Wireless ID"; -const char pstrUsageDiscoverWirelessControl [] PROGMEM = "Discover Wireless Ctrl"; -const char pstrUsageSecurityCodeCharEntered [] PROGMEM = "Sec Code Char Entrd"; -const char pstrUsageSecurityCodeCharErased [] PROGMEM = "Sec Code Char Erased"; -const char pstrUsageSecurityCodeCleared [] PROGMEM = "Sec Code Cleared"; - -// LED Page -const char pstrUsageNumLock [] PROGMEM = "Num Lock"; -const char pstrUsageCapsLock [] PROGMEM = "Caps Lock"; -const char pstrUsageScrollLock [] PROGMEM = "Scroll Lock"; -const char pstrUsageCompose [] PROGMEM = "Compose"; -const char pstrUsageKana [] PROGMEM = "Kana"; -const char pstrUsagePower [] PROGMEM = "Pwr"; -const char pstrUsageShift [] PROGMEM = "Shift"; -const char pstrUsageDoNotDisturb [] PROGMEM = "DND"; -const char pstrUsageMute [] PROGMEM = "Mute"; -const char pstrUsageToneEnable [] PROGMEM = "Tone Enbl"; -const char pstrUsageHighCutFilter [] PROGMEM = "High Cut Fltr"; -const char pstrUsageLowCutFilter [] PROGMEM = "Low Cut Fltr"; -const char pstrUsageEqualizerEnable [] PROGMEM = "Eq Enbl"; -const char pstrUsageSoundFieldOn [] PROGMEM = "Sound Field On"; -const char pstrUsageSurroundOn [] PROGMEM = "Surround On"; -const char pstrUsageRepeat [] PROGMEM = "Repeat"; -const char pstrUsageStereo [] PROGMEM = "Stereo"; -const char pstrUsageSamplingRateDetect [] PROGMEM = "Smpl Rate Detect"; -const char pstrUsageSpinning [] PROGMEM = "Spinning"; -const char pstrUsageCAV [] PROGMEM = "CAV"; -const char pstrUsageCLV [] PROGMEM = "CLV"; -const char pstrUsageRecordingFormatDetect [] PROGMEM = "Rec Format Detect"; -const char pstrUsageOffHook [] PROGMEM = "Off Hook"; -const char pstrUsageRing [] PROGMEM = "Ring"; -const char pstrUsageMessageWaiting [] PROGMEM = "Msg Wait"; -const char pstrUsageDataMode [] PROGMEM = "Data Mode"; -const char pstrUsageBatteryOperation [] PROGMEM = "Bat Op"; -const char pstrUsageBatteryOK [] PROGMEM = "Bat OK"; -const char pstrUsageBatteryLow [] PROGMEM = "Bat Low"; -const char pstrUsageSpeaker [] PROGMEM = "Speaker"; -const char pstrUsageHeadSet [] PROGMEM = "Head Set"; -const char pstrUsageHold [] PROGMEM = "Hold"; -const char pstrUsageMicrophone [] PROGMEM = "Mic"; -const char pstrUsageCoverage [] PROGMEM = "Coverage"; -const char pstrUsageNightMode [] PROGMEM = "Night Mode"; -const char pstrUsageSendCalls [] PROGMEM = "Send Calls"; -const char pstrUsageCallPickup [] PROGMEM = "Call Pickup"; -const char pstrUsageConference [] PROGMEM = "Conf"; -const char pstrUsageStandBy [] PROGMEM = "Stand-by"; -const char pstrUsageCameraOn [] PROGMEM = "Cam On"; -const char pstrUsageCameraOff [] PROGMEM = "Cam Off"; -const char pstrUsageOnLine [] PROGMEM = "On-Line"; -const char pstrUsageOffLine [] PROGMEM = "Off-Line"; -const char pstrUsageBusy [] PROGMEM = "Busy"; -const char pstrUsageReady [] PROGMEM = "Ready"; -const char pstrUsagePaperOut [] PROGMEM = "Paper Out"; -const char pstrUsagePaperJam [] PROGMEM = "Paper Jam"; -const char pstrUsageRemote [] PROGMEM = "Remote"; -const char pstrUsageForward [] PROGMEM = "Fwd"; -const char pstrUsageReverse [] PROGMEM = "Rev"; -const char pstrUsageStop [] PROGMEM = "Stop"; -const char pstrUsageRewind [] PROGMEM = "Rewind"; -const char pstrUsageFastForward [] PROGMEM = "Fast Fwd"; -const char pstrUsagePlay [] PROGMEM = "Play"; -const char pstrUsagePause [] PROGMEM = "Pause"; -const char pstrUsageRecord [] PROGMEM = "Rec"; -const char pstrUsageError [] PROGMEM = "Error"; -const char pstrUsageSelectedIndicator [] PROGMEM = "Usage Sel Ind"; -const char pstrUsageInUseIndicator [] PROGMEM = "Usage In Use Ind"; -const char pstrUsageMultiModeIndicator [] PROGMEM = "Usage Multi Mode Ind"; -const char pstrUsageIndicatorOn [] PROGMEM = "Ind On"; -const char pstrUsageIndicatorFlash [] PROGMEM = "Ind Flash"; -const char pstrUsageIndicatorSlowBlink [] PROGMEM = "Ind Slow Blk"; -const char pstrUsageIndicatorFastBlink [] PROGMEM = "Ind Fast Blk"; -const char pstrUsageIndicatorOff [] PROGMEM = "Ind Off"; -const char pstrUsageFlashOnTime [] PROGMEM = "Flash On Time"; -const char pstrUsageSlowBlinkOnTime [] PROGMEM = "Slow Blk On Time"; -const char pstrUsageSlowBlinkOffTime [] PROGMEM = "Slow Blk Off Time"; -const char pstrUsageFastBlinkOnTime [] PROGMEM = "Fast Blk On Time"; -const char pstrUsageFastBlinkOffTime [] PROGMEM = "Fast Blk Off Time"; -const char pstrUsageIndicatorColor [] PROGMEM = "Usage Ind Color"; -const char pstrUsageIndicatorRed [] PROGMEM = "Ind Red"; -const char pstrUsageIndicatorGreen [] PROGMEM = "Ind Green"; -const char pstrUsageIndicatorAmber [] PROGMEM = "Ind Amber"; -const char pstrUsageGenericIndicator [] PROGMEM = "Gen Ind"; -const char pstrUsageSystemSuspend [] PROGMEM = "Sys Suspend"; -const char pstrUsageExternalPowerConnected [] PROGMEM = "Ext Pwr Conn"; - -// Telephony Usage Page -const char pstrUsagePhone [] PROGMEM = "Phone"; -const char pstrUsageAnsweringMachine [] PROGMEM = "Answ Mach"; -const char pstrUsageMessageControls [] PROGMEM = "Msg Ctrls"; -const char pstrUsageHandset [] PROGMEM = "Handset"; -const char pstrUsageHeadset [] PROGMEM = "Headset"; -const char pstrUsageTelephonyKeyPad [] PROGMEM = "Tel Key Pad"; -const char pstrUsageProgrammableButton [] PROGMEM = "Prog Button"; -const char pstrUsageHookSwitch [] PROGMEM = "Hook Sw"; -const char pstrUsageFlash [] PROGMEM = "Flash"; -const char pstrUsageFeature [] PROGMEM = "Feature"; -//const char pstrUsageHold [] PROGMEM = "Hold"; -const char pstrUsageRedial [] PROGMEM = "Redial"; -const char pstrUsageTransfer [] PROGMEM = "Transfer"; -const char pstrUsageDrop [] PROGMEM = "Drop"; -const char pstrUsagePark [] PROGMEM = "Park"; -const char pstrUsageForwardCalls [] PROGMEM = "Fwd Calls"; -const char pstrUsageAlternateFunction [] PROGMEM = "Alt Func"; -const char pstrUsageLine [] PROGMEM = "Line"; -const char pstrUsageSpeakerPhone [] PROGMEM = "Spk Phone"; -//const char pstrUsageConference [] PROGMEM = "Conference"; -const char pstrUsageRingEnable [] PROGMEM = "Ring Enbl"; -const char pstrUsageRingSelect [] PROGMEM = "Ring Sel"; -const char pstrUsagePhoneMute [] PROGMEM = "Phone Mute"; -const char pstrUsageCallerID [] PROGMEM = "Caller ID"; -const char pstrUsageSend [] PROGMEM = "Send"; -const char pstrUsageSpeedDial [] PROGMEM = "Speed Dial"; -const char pstrUsageStoreNumber [] PROGMEM = "Store Num"; -const char pstrUsageRecallNumber [] PROGMEM = "Recall Num"; -const char pstrUsagePhoneDirectory [] PROGMEM = "Phone Dir"; -const char pstrUsageVoiceMail [] PROGMEM = "Voice Mail"; -const char pstrUsageScreenCalls [] PROGMEM = "Screen Calls"; -//const char pstrUsageDoNotDisturb [] PROGMEM = "Do Not Disturb"; -const char pstrUsageMessage [] PROGMEM = "Msg"; -const char pstrUsageAnswerOnOff [] PROGMEM = "Answer On/Off"; -const char pstrUsageInsideDialTone [] PROGMEM = "Inside Dial Tone"; -const char pstrUsageOutsideDialTone [] PROGMEM = "Outside Dial Tone"; -const char pstrUsageInsideRingTone [] PROGMEM = "Inside Ring Tone"; -const char pstrUsageOutsideRingTone [] PROGMEM = "Outside Ring Tone"; -const char pstrUsagePriorityRingTone [] PROGMEM = "Prior Ring Tone"; -const char pstrUsageInsideRingback [] PROGMEM = "Inside Ringback"; -const char pstrUsagePriorityRingback [] PROGMEM = "Priority Ringback"; -const char pstrUsageLineBusyTone [] PROGMEM = "Ln Busy Tone"; -const char pstrUsageReorderTone [] PROGMEM = "Reorder Tone"; -const char pstrUsageCallWaitingTone [] PROGMEM = "Call Wait Tone"; -const char pstrUsageConfirmationTone1 [] PROGMEM = "Cnfrm Tone1"; -const char pstrUsageConfirmationTone2 [] PROGMEM = "Cnfrm Tone2"; -const char pstrUsageTonesOff [] PROGMEM = "Tones Off"; -const char pstrUsageOutsideRingback [] PROGMEM = "Outside Ringback"; -const char pstrUsageRinger [] PROGMEM = "Ringer"; -const char pstrUsagePhoneKey0 [] PROGMEM = "0"; -const char pstrUsagePhoneKey1 [] PROGMEM = "1"; -const char pstrUsagePhoneKey2 [] PROGMEM = "2"; -const char pstrUsagePhoneKey3 [] PROGMEM = "3"; -const char pstrUsagePhoneKey4 [] PROGMEM = "4"; -const char pstrUsagePhoneKey5 [] PROGMEM = "5"; -const char pstrUsagePhoneKey6 [] PROGMEM = "6"; -const char pstrUsagePhoneKey7 [] PROGMEM = "7"; -const char pstrUsagePhoneKey8 [] PROGMEM = "8"; -const char pstrUsagePhoneKey9 [] PROGMEM = "9"; -const char pstrUsagePhoneKeyStar [] PROGMEM = "*"; -const char pstrUsagePhoneKeyPound [] PROGMEM = "#"; -const char pstrUsagePhoneKeyA [] PROGMEM = "A"; -const char pstrUsagePhoneKeyB [] PROGMEM = "B"; -const char pstrUsagePhoneKeyC [] PROGMEM = "C"; -const char pstrUsagePhoneKeyD [] PROGMEM = "D"; - -// Consumer Usage Page -const char pstrUsageConsumerControl [] PROGMEM = "Consumer Ctrl"; -const char pstrUsageNumericKeyPad [] PROGMEM = "Num Key Pad"; -//const char pstrUsageProgrammableButton [] PROGMEM = "Prog Btn"; -//const char pstrUsageMicrophone [] PROGMEM = "Mic"; -const char pstrUsageHeadphone [] PROGMEM = "Headphone"; -const char pstrUsageGraphicEqualizer [] PROGMEM = "Graph Eq"; -const char pstrUsagePlus10 [] PROGMEM = "+10"; -const char pstrUsagePlus100 [] PROGMEM = "+100"; -const char pstrUsageAMPM [] PROGMEM = "AM/PM"; -//const char pstrUsagePower [] PROGMEM = "Pwr"; -const char pstrUsageReset [] PROGMEM = "Reset"; -const char pstrUsageSleep [] PROGMEM = "Sleep"; -const char pstrUsageSleepAfter [] PROGMEM = "Sleep After"; -const char pstrUsageSleepMode [] PROGMEM = "Sleep Mode"; -const char pstrUsageIllumination [] PROGMEM = "Illumin"; -const char pstrUsageFunctionButtons [] PROGMEM = "Func Btns"; -const char pstrUsageMenu [] PROGMEM = "Menu"; -const char pstrUsageMenuPick [] PROGMEM = "Menu Pick"; -const char pstrUsageMenuUp [] PROGMEM = "Menu Up"; -const char pstrUsageMenuDown [] PROGMEM = "Menu Down"; -const char pstrUsageMenuLeft [] PROGMEM = "Menu Left"; -const char pstrUsageMenuRight [] PROGMEM = "Menu Right"; -const char pstrUsageMenuEscape [] PROGMEM = "Menu Esc"; -const char pstrUsageMenuValueIncrease [] PROGMEM = "Menu Val Inc"; -const char pstrUsageMenuValueDecrease [] PROGMEM = "Menu Val Dec"; -const char pstrUsageDataOnScreen [] PROGMEM = "Data On Scr"; -const char pstrUsageClosedCaption [] PROGMEM = "Closed Cptn"; -const char pstrUsageClosedCaptionSelect [] PROGMEM = "Closed Cptn Sel"; -const char pstrUsageVCRTV [] PROGMEM = "VCR/TV"; -const char pstrUsageBroadcastMode [] PROGMEM = "Brdcast Mode"; -const char pstrUsageSnapshot [] PROGMEM = "Snapshot"; -const char pstrUsageStill [] PROGMEM = "Still"; -const char pstrUsageSelection [] PROGMEM = "Sel"; -const char pstrUsageAssignSelection [] PROGMEM = "Assign Sel"; -const char pstrUsageModeStep [] PROGMEM = "Mode Step"; -const char pstrUsageRecallLast [] PROGMEM = "Recall Last"; -const char pstrUsageEnterChannel [] PROGMEM = "Entr Channel"; -const char pstrUsageOrderMovie [] PROGMEM = "Ord Movie"; -const char pstrUsageChannel [] PROGMEM = "Channel"; -const char pstrUsageMediaSelection [] PROGMEM = "Med Sel"; -const char pstrUsageMediaSelectComputer [] PROGMEM = "Med Sel Comp"; -const char pstrUsageMediaSelectTV [] PROGMEM = "Med Sel TV"; -const char pstrUsageMediaSelectWWW [] PROGMEM = "Med Sel WWW"; -const char pstrUsageMediaSelectDVD [] PROGMEM = "Med Sel DVD"; -const char pstrUsageMediaSelectTelephone [] PROGMEM = "Med Sel Tel"; -const char pstrUsageMediaSelectProgramGuide [] PROGMEM = "Med Sel PG"; -const char pstrUsageMediaSelectVideoPhone [] PROGMEM = "Med Sel Vid"; -const char pstrUsageMediaSelectGames [] PROGMEM = "Med Sel Games"; -const char pstrUsageMediaSelectMessages [] PROGMEM = "Med Sel Msg"; -const char pstrUsageMediaSelectCD [] PROGMEM = "Med Sel CD"; -const char pstrUsageMediaSelectVCR [] PROGMEM = "Med Sel VCR"; -const char pstrUsageMediaSelectTuner [] PROGMEM = "Med Sel Tuner"; -const char pstrUsageQuit [] PROGMEM = "Quit"; -const char pstrUsageHelp [] PROGMEM = "Help"; -const char pstrUsageMediaSelectTape [] PROGMEM = "Med Sel Tape"; -const char pstrUsageMediaSelectCable [] PROGMEM = "Med Sel Cbl"; -const char pstrUsageMediaSelectSatellite [] PROGMEM = "Med Sel Sat"; -const char pstrUsageMediaSelectSecurity [] PROGMEM = "Med Sel Secur"; -const char pstrUsageMediaSelectHome [] PROGMEM = "Med Sel Home"; -const char pstrUsageMediaSelectCall [] PROGMEM = "Med Sel Call"; -const char pstrUsageChannelIncrement [] PROGMEM = "Ch Inc"; -const char pstrUsageChannelDecrement [] PROGMEM = "Ch Dec"; -const char pstrUsageMediaSelectSAP [] PROGMEM = "Med Sel SAP"; -const char pstrUsageVCRPlus [] PROGMEM = "VCR+"; -const char pstrUsageOnce [] PROGMEM = "Once"; -const char pstrUsageDaily [] PROGMEM = "Daily"; -const char pstrUsageWeekly [] PROGMEM = "Weekly"; -const char pstrUsageMonthly [] PROGMEM = "Monthly"; -//const char pstrUsagePlay [] PROGMEM = "Play"; -//const char pstrUsagePause [] PROGMEM = "Pause"; -//const char pstrUsageRecord [] PROGMEM = "Rec"; -//const char pstrUsageFastForward [] PROGMEM = "FF"; -//const char pstrUsageRewind [] PROGMEM = "Rewind"; -const char pstrUsageScanNextTrack [] PROGMEM = "Next Track"; -const char pstrUsageScanPreviousTrack [] PROGMEM = "Prev Track"; -//const char pstrUsageStop [] PROGMEM = "Stop"; -const char pstrUsageEject [] PROGMEM = "Eject"; -const char pstrUsageRandomPlay [] PROGMEM = "Random"; -const char pstrUsageSelectDisk [] PROGMEM = "Sel Disk"; -const char pstrUsageEnterDisk [] PROGMEM = "Ent Disk"; -//const char pstrUsageRepeat [] PROGMEM = "Repeat"; -const char pstrUsageTracking [] PROGMEM = "Tracking"; -const char pstrUsageTrackNormal [] PROGMEM = "Trk Norm"; -const char pstrUsageSlowTracking [] PROGMEM = "Slow Trk"; -const char pstrUsageFrameForward [] PROGMEM = "Frm Fwd"; -const char pstrUsageFrameBackwards [] PROGMEM = "Frm Back"; -const char pstrUsageMark [] PROGMEM = "Mark"; -const char pstrUsageClearMark [] PROGMEM = "Clr Mark"; -const char pstrUsageRepeatFromMark [] PROGMEM = "Rpt Mark"; -const char pstrUsageReturnToMark [] PROGMEM = "Ret to Mark"; -const char pstrUsageSearchMarkForward [] PROGMEM = "Search Mark Fwd"; -const char pstrUsageSearchMarkBackwards [] PROGMEM = "Search Mark Back"; -const char pstrUsageCounterReset [] PROGMEM = "Counter Reset"; -const char pstrUsageShowCounter [] PROGMEM = "Show Counter"; -const char pstrUsageTrackingIncrement [] PROGMEM = "Track Inc"; -const char pstrUsageTrackingDecrement [] PROGMEM = "Track Dec"; -const char pstrUsageStopEject [] PROGMEM = "Stop/Eject"; -const char pstrUsagePlayPause [] PROGMEM = "Play/Pause"; -const char pstrUsagePlaySkip [] PROGMEM = "Play/Skip"; -const char pstrUsageVolume [] PROGMEM = "Vol"; -const char pstrUsageBalance [] PROGMEM = "Balance"; -//const char pstrUsageMute [] PROGMEM = "Mute"; -const char pstrUsageBass [] PROGMEM = "Bass"; -const char pstrUsageTreble [] PROGMEM = "Treble"; -const char pstrUsageBassBoost [] PROGMEM = "Bass Boost"; -const char pstrUsageSurroundMode [] PROGMEM = "Surround"; -const char pstrUsageLoudness [] PROGMEM = "Loud"; -const char pstrUsageMPX [] PROGMEM = "MPX"; -const char pstrUsageVolumeIncrement [] PROGMEM = "Vol Inc"; -const char pstrUsageVolumeDecrement [] PROGMEM = "Vol Dec"; -const char pstrUsageSpeedSelect [] PROGMEM = "Speed"; -const char pstrUsagePlaybackSpeed [] PROGMEM = "Play Speed"; -const char pstrUsageStandardPlay [] PROGMEM = "Std Play"; -const char pstrUsageLongPlay [] PROGMEM = "Long Play"; -const char pstrUsageExtendedPlay [] PROGMEM = "Ext Play"; -const char pstrUsageSlow [] PROGMEM = "Slow"; -const char pstrUsageFanEnable [] PROGMEM = "Fan Enbl"; -const char pstrUsageFanSpeed [] PROGMEM = "Fan Speed"; -const char pstrUsageLightEnable [] PROGMEM = "Light Enbl"; -const char pstrUsageLightIlluminationLevel [] PROGMEM = "Light Illum Lev"; -const char pstrUsageClimateControlEnable [] PROGMEM = "Climate Enbl"; -const char pstrUsageRoomTemperature [] PROGMEM = "Room Temp"; -const char pstrUsageSecurityEnable [] PROGMEM = "Secur Enbl"; -const char pstrUsageFireAlarm [] PROGMEM = "Fire Alm"; -const char pstrUsagePoliceAlarm [] PROGMEM = "Police Alm"; -const char pstrUsageProximity [] PROGMEM = "Prox"; -const char pstrUsageMotion [] PROGMEM = "Motion"; -const char pstrUsageDuresAlarm [] PROGMEM = "Dures Alm"; -const char pstrUsageHoldupAlarm [] PROGMEM = "Holdup Alm"; -const char pstrUsageMedicalAlarm [] PROGMEM = "Med Alm"; -const char pstrUsageBalanceRight [] PROGMEM = "Balance Right"; -const char pstrUsageBalanceLeft [] PROGMEM = "Balance Left"; -const char pstrUsageBassIncrement [] PROGMEM = "Bass Inc"; -const char pstrUsageBassDecrement [] PROGMEM = "Bass Dec"; -const char pstrUsageTrebleIncrement [] PROGMEM = "Treble Inc"; -const char pstrUsageTrebleDecrement [] PROGMEM = "Treble Dec"; -const char pstrUsageSpeakerSystem [] PROGMEM = "Spk Sys"; -const char pstrUsageChannelLeft [] PROGMEM = "Ch Left"; -const char pstrUsageChannelRight [] PROGMEM = "Ch Right"; -const char pstrUsageChannelCenter [] PROGMEM = "Ch Center"; -const char pstrUsageChannelFront [] PROGMEM = "Ch Front"; -const char pstrUsageChannelCenterFront [] PROGMEM = "Ch Cntr Front"; -const char pstrUsageChannelSide [] PROGMEM = "Ch Side"; -const char pstrUsageChannelSurround [] PROGMEM = "Ch Surround"; -const char pstrUsageChannelLowFreqEnhancement [] PROGMEM = "Ch Low Freq Enh"; -const char pstrUsageChannelTop [] PROGMEM = "Ch Top"; -const char pstrUsageChannelUnknown [] PROGMEM = "Ch Unk"; -const char pstrUsageSubChannel [] PROGMEM = "Sub-ch"; -const char pstrUsageSubChannelIncrement [] PROGMEM = "Sub-ch Inc"; -const char pstrUsageSubChannelDecrement [] PROGMEM = "Sub-ch Dec"; -const char pstrUsageAlternateAudioIncrement [] PROGMEM = "Alt Aud Inc"; -const char pstrUsageAlternateAudioDecrement [] PROGMEM = "Alt Aud Dec"; -const char pstrUsageApplicationLaunchButtons [] PROGMEM = "App Launch Btns"; -const char pstrUsageALLaunchButtonConfigTool [] PROGMEM = "AL Launch Conf Tl"; -const char pstrUsageALProgrammableButton [] PROGMEM = "AL Pgm Btn"; -const char pstrUsageALConsumerControlConfig [] PROGMEM = "AL Cons Ctrl Cfg"; -const char pstrUsageALWordProcessor [] PROGMEM = "AL Word Proc"; -const char pstrUsageALTextEditor [] PROGMEM = "AL Txt Edtr"; -const char pstrUsageALSpreadsheet [] PROGMEM = "AL Sprdsheet"; -const char pstrUsageALGraphicsEditor [] PROGMEM = "AL Graph Edtr"; -const char pstrUsageALPresentationApp [] PROGMEM = "AL Present App"; -const char pstrUsageALDatabaseApp [] PROGMEM = "AL DB App"; -const char pstrUsageALEmailReader [] PROGMEM = "AL E-mail Rdr"; -const char pstrUsageALNewsreader [] PROGMEM = "AL Newsrdr"; -const char pstrUsageALVoicemail [] PROGMEM = "AL Voicemail"; -const char pstrUsageALContactsAddressBook [] PROGMEM = "AL Addr Book"; -const char pstrUsageALCalendarSchedule [] PROGMEM = "AL Clndr/Schdlr"; -const char pstrUsageALTaskProjectManager [] PROGMEM = "AL Task/Prj Mgr"; -const char pstrUsageALLogJournalTimecard [] PROGMEM = "AL Log/Jrnl/Tmcrd"; -const char pstrUsageALCheckbookFinance [] PROGMEM = "AL Chckbook/Fin"; -const char pstrUsageALCalculator [] PROGMEM = "AL Calc"; -const char pstrUsageALAVCapturePlayback [] PROGMEM = "AL A/V Capt/Play"; -const char pstrUsageALLocalMachineBrowser [] PROGMEM = "AL Loc Mach Brow"; -const char pstrUsageALLANWANBrow [] PROGMEM = "AL LAN/WAN Brow"; -const char pstrUsageALInternetBrowser [] PROGMEM = "AL I-net Brow"; -const char pstrUsageALRemoteNetISPConnect [] PROGMEM = "AL Rem Net Con"; -const char pstrUsageALNetworkConference [] PROGMEM = "AL Net Conf"; -const char pstrUsageALNetworkChat [] PROGMEM = "AL Net Chat"; -const char pstrUsageALTelephonyDialer [] PROGMEM = "AL Tel/Dial"; -const char pstrUsageALLogon [] PROGMEM = "AL Logon"; -const char pstrUsageALLogoff [] PROGMEM = "AL Logoff"; -const char pstrUsageALLogonLogoff [] PROGMEM = "AL Logon/Logoff"; -const char pstrUsageALTermLockScrSav [] PROGMEM = "AL Term Lock/Scr Sav"; -const char pstrUsageALControlPannel [] PROGMEM = "AL Ctrl Pan"; -const char pstrUsageALCommandLineProcessorRun [] PROGMEM = "AL Cmd/Run"; -const char pstrUsageALProcessTaskManager [] PROGMEM = "AL Task Mgr"; -const char pstrUsageALSelectTaskApplication [] PROGMEM = "AL Sel App"; -const char pstrUsageALNextTaskApplication [] PROGMEM = "AL Next App"; -const char pstrUsageALPreviousTaskApplication [] PROGMEM = "AL Prev App"; -const char pstrUsageALPreemptiveHaltTaskApp [] PROGMEM = "AL Prmpt Halt App"; -const char pstrUsageALIntegratedHelpCenter [] PROGMEM = "AL Hlp Cntr"; -const char pstrUsageALDocuments [] PROGMEM = "AL Docs"; -const char pstrUsageALThesaurus [] PROGMEM = "AL Thsrs"; -const char pstrUsageALDictionary [] PROGMEM = "AL Dict"; -const char pstrUsageALDesktop [] PROGMEM = "AL Desktop"; -const char pstrUsageALSpellCheck [] PROGMEM = "AL Spell Chk"; -const char pstrUsageALGrammarCheck [] PROGMEM = "AL Gram Chk"; -const char pstrUsageALWirelessStatus [] PROGMEM = "AL Wireless Sts"; -const char pstrUsageALKeyboardLayout [] PROGMEM = "AL Kbd Layout"; -const char pstrUsageALVirusProtection [] PROGMEM = "AL Vir Protect"; -const char pstrUsageALEncryption [] PROGMEM = "AL Encrypt"; -const char pstrUsageALScreenSaver [] PROGMEM = "AL Scr Sav"; -const char pstrUsageALAlarms [] PROGMEM = "AL Alarms"; -const char pstrUsageALClock [] PROGMEM = "AL Clock"; -const char pstrUsageALFileBrowser [] PROGMEM = "AL File Brow"; -const char pstrUsageALPowerStatus [] PROGMEM = "AL Pwr Sts"; -const char pstrUsageALImageBrowser [] PROGMEM = "AL Img Brow"; -const char pstrUsageALAudioBrowser [] PROGMEM = "AL Aud Brow"; -const char pstrUsageALMovieBrowser [] PROGMEM = "AL Mov Brow"; -const char pstrUsageALDigitalRightsManager [] PROGMEM = "AL Dig Rights Mgr"; -const char pstrUsageALDigitalWallet [] PROGMEM = "AL Dig Wallet"; -const char pstrUsageALInstantMessaging [] PROGMEM = "AL Inst Msg"; -const char pstrUsageALOEMFeaturesBrowser [] PROGMEM = "AL OEM Tips Brow"; -const char pstrUsageALOEMHelp [] PROGMEM = "AL OEM Hlp"; -const char pstrUsageALOnlineCommunity [] PROGMEM = "AL Online Com"; -const char pstrUsageALEntertainmentContentBrow [] PROGMEM = "AL Ent Cont Brow"; -const char pstrUsageALOnlineShoppingBrowser [] PROGMEM = "AL Online Shop Brow"; -const char pstrUsageALSmartCardInfoHelp [] PROGMEM = "AL SmartCard Inf"; -const char pstrUsageALMarketMonitorFinBrowser [] PROGMEM = "AL Market Brow"; -const char pstrUsageALCustomCorpNewsBrowser [] PROGMEM = "AL Cust Corp News Brow"; -const char pstrUsageALOnlineActivityBrowser [] PROGMEM = "AL Online Act Brow"; -const char pstrUsageALResearchSearchBrowser [] PROGMEM = "AL Search Brow"; -const char pstrUsageALAudioPlayer [] PROGMEM = "AL Aud Player"; -const char pstrUsageGenericGUIAppControls [] PROGMEM = "Gen GUI App Ctrl"; -const char pstrUsageACNew [] PROGMEM = "AC New"; -const char pstrUsageACOpen [] PROGMEM = "AC Open"; -const char pstrUsageACClose [] PROGMEM = "AC Close"; -const char pstrUsageACExit [] PROGMEM = "AC Exit"; -const char pstrUsageACMaximize [] PROGMEM = "AC Max"; -const char pstrUsageACMinimize [] PROGMEM = "AC Min"; -const char pstrUsageACSave [] PROGMEM = "AC Save"; -const char pstrUsageACPrint [] PROGMEM = "AC Print"; -const char pstrUsageACProperties [] PROGMEM = "AC Prop"; -const char pstrUsageACUndo [] PROGMEM = "AC Undo"; -const char pstrUsageACCopy [] PROGMEM = "AC Copy"; -const char pstrUsageACCut [] PROGMEM = "AC Cut"; -const char pstrUsageACPaste [] PROGMEM = "AC Paste"; -const char pstrUsageACSelectAll [] PROGMEM = "AC Sel All"; -const char pstrUsageACFind [] PROGMEM = "AC Find"; -const char pstrUsageACFindAndReplace [] PROGMEM = "AC Find/Replace"; -const char pstrUsageACSearch [] PROGMEM = "AC Search"; -const char pstrUsageACGoto [] PROGMEM = "AC Goto"; -const char pstrUsageACHome [] PROGMEM = "AC Home"; -const char pstrUsageACBack [] PROGMEM = "AC Back"; -const char pstrUsageACForward [] PROGMEM = "AC Fwd"; -const char pstrUsageACStop [] PROGMEM = "AC Stop"; -const char pstrUsageACRefresh [] PROGMEM = "AC Refresh"; -const char pstrUsageACPreviousLink [] PROGMEM = "AC Prev Link"; -const char pstrUsageACNextLink [] PROGMEM = "AC Next Link"; -const char pstrUsageACBookmarks [] PROGMEM = "AC Bkmarks"; -const char pstrUsageACHistory [] PROGMEM = "AC Hist"; -const char pstrUsageACSubscriptions [] PROGMEM = "AC Subscr"; -const char pstrUsageACZoomIn [] PROGMEM = "AC Zoom In"; -const char pstrUsageACZoomOut [] PROGMEM = "AC Zoom Out"; -const char pstrUsageACZoom [] PROGMEM = "AC Zoom"; -const char pstrUsageACFullScreenView [] PROGMEM = "AC Full Scr"; -const char pstrUsageACNormalView [] PROGMEM = "AC Norm View"; -const char pstrUsageACViewToggle [] PROGMEM = "AC View Tgl"; -const char pstrUsageACScrollUp [] PROGMEM = "AC Scroll Up"; -const char pstrUsageACScrollDown [] PROGMEM = "AC Scroll Down"; -const char pstrUsageACScroll [] PROGMEM = "AC Scroll"; -const char pstrUsageACPanLeft [] PROGMEM = "AC Pan Left"; -const char pstrUsageACPanRight [] PROGMEM = "AC Pan Right"; -const char pstrUsageACPan [] PROGMEM = "AC Pan"; -const char pstrUsageACNewWindow [] PROGMEM = "AC New Wnd"; -const char pstrUsageACTileHoriz [] PROGMEM = "AC Tile Horiz"; -const char pstrUsageACTileVert [] PROGMEM = "AC Tile Vert"; -const char pstrUsageACFormat [] PROGMEM = "AC Frmt"; -const char pstrUsageACEdit [] PROGMEM = "AC Edit"; -const char pstrUsageACBold [] PROGMEM = "AC Bold"; -const char pstrUsageACItalics [] PROGMEM = "AC Ital"; -const char pstrUsageACUnderline [] PROGMEM = "AC Under"; -const char pstrUsageACStrikethrough [] PROGMEM = "AC Strike"; -const char pstrUsageACSubscript [] PROGMEM = "AC Sub"; -const char pstrUsageACSuperscript [] PROGMEM = "AC Super"; -const char pstrUsageACAllCaps [] PROGMEM = "AC All Caps"; -const char pstrUsageACRotate [] PROGMEM = "AC Rotate"; -const char pstrUsageACResize [] PROGMEM = "AC Resize"; -const char pstrUsageACFlipHorizontal [] PROGMEM = "AC Flp H"; -const char pstrUsageACFlipVertical [] PROGMEM = "AC Flp V"; -const char pstrUsageACMirrorHorizontal [] PROGMEM = "AC Mir H"; -const char pstrUsageACMirrorVertical [] PROGMEM = "AC Mir V"; -const char pstrUsageACFontSelect [] PROGMEM = "AC Fnt Sel"; -const char pstrUsageACFontColor [] PROGMEM = "AC Fnt Clr"; -const char pstrUsageACFontSize [] PROGMEM = "AC Fnt Size"; -const char pstrUsageACJustifyLeft [] PROGMEM = "AC Just Left"; -const char pstrUsageACJustifyCenterH [] PROGMEM = "AC Just Cent H"; -const char pstrUsageACJustifyRight [] PROGMEM = "AC Just Right"; -const char pstrUsageACJustifyBlockH [] PROGMEM = "AC Just Block H"; -const char pstrUsageACJustifyTop [] PROGMEM = "AC Just Top"; -const char pstrUsageACJustifyCenterV [] PROGMEM = "AC Just Cent V"; -const char pstrUsageACJustifyBottom [] PROGMEM = "AC Just Bot"; -const char pstrUsageACJustifyBlockV [] PROGMEM = "AC Just Block V"; -const char pstrUsageACIndentDecrease [] PROGMEM = "AC Indent Dec"; -const char pstrUsageACIndentIncrease [] PROGMEM = "AC Indent Inc"; -const char pstrUsageACNumberedList [] PROGMEM = "AC Num List"; -const char pstrUsageACRestartNumbering [] PROGMEM = "AC Res Num"; -const char pstrUsageACBulletedList [] PROGMEM = "AC Blt List"; -const char pstrUsageACPromote [] PROGMEM = "AC Promote"; -const char pstrUsageACDemote [] PROGMEM = "AC Demote"; -const char pstrUsageACYes [] PROGMEM = "AC Yes"; -const char pstrUsageACNo [] PROGMEM = "AC No"; -const char pstrUsageACCancel [] PROGMEM = "AC Cancel"; -const char pstrUsageACCatalog [] PROGMEM = "AC Ctlg"; -const char pstrUsageACBuyChkout [] PROGMEM = "AC Buy"; -const char pstrUsageACAddToCart [] PROGMEM = "AC Add2Cart"; -const char pstrUsageACExpand [] PROGMEM = "AC Xpnd"; -const char pstrUsageACExpandAll [] PROGMEM = "AC Xpand All"; -const char pstrUsageACCollapse [] PROGMEM = "AC Collapse"; -const char pstrUsageACCollapseAll [] PROGMEM = "AC Collapse All"; -const char pstrUsageACPrintPreview [] PROGMEM = "AC Prn Prevw"; -const char pstrUsageACPasteSpecial [] PROGMEM = "AC Paste Spec"; -const char pstrUsageACInsertMode [] PROGMEM = "AC Ins Mode"; -const char pstrUsageACDelete [] PROGMEM = "AC Del"; -const char pstrUsageACLock [] PROGMEM = "AC Lock"; -const char pstrUsageACUnlock [] PROGMEM = "AC Unlock"; -const char pstrUsageACProtect [] PROGMEM = "AC Prot"; -const char pstrUsageACUnprotect [] PROGMEM = "AC Unprot"; -const char pstrUsageACAttachComment [] PROGMEM = "AC Attach Cmnt"; -const char pstrUsageACDeleteComment [] PROGMEM = "AC Del Cmnt"; -const char pstrUsageACViewComment [] PROGMEM = "AC View Cmnt"; -const char pstrUsageACSelectWord [] PROGMEM = "AC Sel Word"; -const char pstrUsageACSelectSentence [] PROGMEM = "AC Sel Sntc"; -const char pstrUsageACSelectParagraph [] PROGMEM = "AC Sel Para"; -const char pstrUsageACSelectColumn [] PROGMEM = "AC Sel Col"; -const char pstrUsageACSelectRow [] PROGMEM = "AC Sel Row"; -const char pstrUsageACSelectTable [] PROGMEM = "AC Sel Tbl"; -const char pstrUsageACSelectObject [] PROGMEM = "AC Sel Obj"; -const char pstrUsageACRedoRepeat [] PROGMEM = "AC Redo"; -const char pstrUsageACSort [] PROGMEM = "AC Sort"; -const char pstrUsageACSortAscending [] PROGMEM = "AC Sort Asc"; -const char pstrUsageACSortDescending [] PROGMEM = "AC Sort Desc"; -const char pstrUsageACFilter [] PROGMEM = "AC Filt"; -const char pstrUsageACSetClock [] PROGMEM = "AC Set Clk"; -const char pstrUsageACViewClock [] PROGMEM = "AC View Clk"; -const char pstrUsageACSelectTimeZone [] PROGMEM = "AC Sel Time Z"; -const char pstrUsageACEditTimeZone [] PROGMEM = "AC Edt Time Z"; -const char pstrUsageACSetAlarm [] PROGMEM = "AC Set Alm"; -const char pstrUsageACClearAlarm [] PROGMEM = "AC Clr Alm"; -const char pstrUsageACSnoozeAlarm [] PROGMEM = "AC Snz Alm"; -const char pstrUsageACResetAlarm [] PROGMEM = "AC Rst Alm"; -const char pstrUsageACSyncronize [] PROGMEM = "AC Sync"; -const char pstrUsageACSendReceive [] PROGMEM = "AC Snd/Rcv"; -const char pstrUsageACSendTo [] PROGMEM = "AC Snd To"; -const char pstrUsageACReply [] PROGMEM = "AC Reply"; -const char pstrUsageACReplyAll [] PROGMEM = "AC Reply All"; -const char pstrUsageACForwardMessage [] PROGMEM = "AC Fwd Msg"; -const char pstrUsageACSend [] PROGMEM = "AC Snd"; -const char pstrUsageACAttachFile [] PROGMEM = "AC Att File"; -const char pstrUsageACUpload [] PROGMEM = "AC Upld"; -const char pstrUsageACDownload [] PROGMEM = "AC Dnld"; -const char pstrUsageACSetBorders [] PROGMEM = "AC Set Brd"; -const char pstrUsageACInsertRow [] PROGMEM = "AC Ins Row"; -const char pstrUsageACInsertColumn [] PROGMEM = "AC Ins Col"; -const char pstrUsageACInsertFile [] PROGMEM = "AC Ins File"; -const char pstrUsageACInsertPicture [] PROGMEM = "AC Ins Pic"; -const char pstrUsageACInsertObject [] PROGMEM = "AC Ins Obj"; -const char pstrUsageACInsertSymbol [] PROGMEM = "AC Ins Sym"; -const char pstrUsageACSaveAndClose [] PROGMEM = "AC Sav&Cls"; -const char pstrUsageACRename [] PROGMEM = "AC Rename"; -const char pstrUsageACMerge [] PROGMEM = "AC Merge"; -const char pstrUsageACSplit [] PROGMEM = "AC Split"; -const char pstrUsageACDistributeHorizontaly [] PROGMEM = "AC Dist Hor"; -const char pstrUsageACDistributeVerticaly [] PROGMEM = "AC Dist Ver"; - -// Digitaizers -const char pstrUsageDigitizer [] PROGMEM = "Digitizer"; -const char pstrUsagePen [] PROGMEM = "Pen"; -const char pstrUsageLightPen [] PROGMEM = "Light Pen"; -const char pstrUsageTouchScreen [] PROGMEM = "Touch Scr"; -const char pstrUsageTouchPad [] PROGMEM = "Touch Pad"; -const char pstrUsageWhiteBoard [] PROGMEM = "White Brd"; -const char pstrUsageCoordinateMeasuringMachine [] PROGMEM = "Coord Meas Mach"; -const char pstrUsage3DDigitizer [] PROGMEM = "3D Dgtz"; -const char pstrUsageStereoPlotter [] PROGMEM = "Stereo Plot"; -const char pstrUsageArticulatedArm [] PROGMEM = "Art Arm"; -const char pstrUsageArmature [] PROGMEM = "Armature"; -const char pstrUsageMultiplePointDigitizer [] PROGMEM = "Multi Point Dgtz"; -const char pstrUsageFreeSpaceWand [] PROGMEM = "Free Space Wand"; -const char pstrUsageStylus [] PROGMEM = "Stylus"; -const char pstrUsagePuck [] PROGMEM = "Puck"; -const char pstrUsageFinger [] PROGMEM = "Finger"; -const char pstrUsageTipPressure [] PROGMEM = "Tip Press"; -const char pstrUsageBarrelPressure [] PROGMEM = "Brl Press"; -const char pstrUsageInRange [] PROGMEM = "In Range"; -const char pstrUsageTouch [] PROGMEM = "Touch"; -const char pstrUsageUntouch [] PROGMEM = "Untouch"; -const char pstrUsageTap [] PROGMEM = "Tap"; -const char pstrUsageQuality [] PROGMEM = "Qlty"; -const char pstrUsageDataValid [] PROGMEM = "Data Valid"; -const char pstrUsageTransducerIndex [] PROGMEM = "Transducer Ind"; -const char pstrUsageTabletFunctionKeys [] PROGMEM = "Tabl Func Keys"; -const char pstrUsageProgramChangeKeys [] PROGMEM = "Pgm Chng Keys"; -//const char pstrUsageBatteryStrength [] PROGMEM = "Bat Strength"; -const char pstrUsageInvert [] PROGMEM = "Invert"; -const char pstrUsageXTilt [] PROGMEM = "X Tilt"; -const char pstrUsageYTilt [] PROGMEM = "Y Tilt"; -const char pstrUsageAzimuth [] PROGMEM = "Azimuth"; -const char pstrUsageAltitude [] PROGMEM = "Altitude"; -const char pstrUsageTwist [] PROGMEM = "Twist"; -const char pstrUsageTipSwitch [] PROGMEM = "Tip Sw"; -const char pstrUsageSecondaryTipSwitch [] PROGMEM = "Scnd Tip Sw"; -const char pstrUsageBarrelSwitch [] PROGMEM = "Brl Sw"; -const char pstrUsageEraser [] PROGMEM = "Eraser"; -const char pstrUsageTabletPick [] PROGMEM = "Tbl Pick"; - -// Alphanumeric Display Page -const char pstrUsageAlphanumericDisplay [] PROGMEM = "Alphanum Disp"; -const char pstrUsageBitmappedDisplay [] PROGMEM = "Bmp Disp"; -const char pstrUsageDisplayAttributesReport [] PROGMEM = "Disp Attr Rpt"; -const char pstrUsageASCIICharacterSet [] PROGMEM = "ASCII chset"; -const char pstrUsageDataReadBack [] PROGMEM = "Data Rd Back"; -const char pstrUsageFontReadBack [] PROGMEM = "Fnt Rd Back"; -const char pstrUsageDisplayControlReport [] PROGMEM = "Disp Ctrl Rpt"; -const char pstrUsageClearDisplay [] PROGMEM = "Clr Disp"; -//const char pstrUsageDisplayEnable [] PROGMEM = "Disp Enbl"; -const char pstrUsageScreenSaverDelay [] PROGMEM = "Scr Sav Delay"; -const char pstrUsageScreenSaverEnable [] PROGMEM = "Scr Sav Enbl"; -const char pstrUsageVerticalScroll [] PROGMEM = "V Scroll"; -const char pstrUsageHorizontalScroll [] PROGMEM = "H Scroll"; -const char pstrUsageCharacterReport [] PROGMEM = "Char Rpt"; -const char pstrUsageDisplayData [] PROGMEM = "Disp Data"; -const char pstrUsageDisplayStatus [] PROGMEM = "Disp Stat"; -const char pstrUsageStatusNotReady [] PROGMEM = "Stat !Ready"; -const char pstrUsageStatusReady [] PROGMEM = "Stat Ready"; -const char pstrUsageErrorNotALoadableCharacter [] PROGMEM = "Err Not Ld Char"; -const char pstrUsageErrorFotDataCanNotBeRead [] PROGMEM = "Fnt Data Rd Err"; -const char pstrUsageCursorPositionReport [] PROGMEM = "Cur Pos Rpt"; -const char pstrUsageRow [] PROGMEM = "Row"; -const char pstrUsageColumn [] PROGMEM = "Col"; -const char pstrUsageRows [] PROGMEM = "Rows"; -const char pstrUsageColumns [] PROGMEM = "Cols"; -const char pstrUsageCursorPixelPosition [] PROGMEM = "Cur Pix Pos"; -const char pstrUsageCursorMode [] PROGMEM = "Cur Mode"; -const char pstrUsageCursorEnable [] PROGMEM = "Cur Enbl"; -const char pstrUsageCursorBlink [] PROGMEM = "Cur Blnk"; -const char pstrUsageFontReport [] PROGMEM = "Fnt Rpt"; -const char pstrUsageFontData [] PROGMEM = "Fnt Data"; -const char pstrUsageCharacterWidth [] PROGMEM = "Char Wdth"; -const char pstrUsageCharacterHeight [] PROGMEM = "Char Hght"; -const char pstrUsageCharacterSpacingHorizontal [] PROGMEM = "Char Space H"; -const char pstrUsageCharacterSpacingVertical [] PROGMEM = "Char Space V"; -const char pstrUsageUnicodeCharset [] PROGMEM = "Unicode Char"; -const char pstrUsageFont7Segment [] PROGMEM = "Fnt 7-seg"; -const char pstrUsage7SegmentDirectMap [] PROGMEM = "7-seg map"; -const char pstrUsageFont14Segment [] PROGMEM = "Fnt 14-seg"; -const char pstrUsage14SegmentDirectMap [] PROGMEM = "14-seg map"; -const char pstrUsageDisplayBrightness [] PROGMEM = "Disp Bright"; -const char pstrUsageDisplayContrast [] PROGMEM = "Disp Cntrst"; -const char pstrUsageCharacterAttribute [] PROGMEM = "Char Attr"; -const char pstrUsageAttributeReadback [] PROGMEM = "Attr Readbk"; -const char pstrUsageAttributeData [] PROGMEM = "Attr Data"; -const char pstrUsageCharAttributeEnhance [] PROGMEM = "Char Attr Enh"; -const char pstrUsageCharAttributeUnderline [] PROGMEM = "Char Attr Undl"; -const char pstrUsageCharAttributeBlink [] PROGMEM = "Char Attr Blnk"; -const char pstrUsageBitmapSizeX [] PROGMEM = "Bmp Size X"; -const char pstrUsageBitmapSizeY [] PROGMEM = "Bmp Size Y"; -const char pstrUsageBitDepthFormat [] PROGMEM = "Bit Dpth Fmt"; -const char pstrUsageDisplayOrientation [] PROGMEM = "Disp Ornt"; -const char pstrUsagePaletteReport [] PROGMEM = "Pal Rpt"; -const char pstrUsagePaletteDataSize [] PROGMEM = "Pal Data Size"; -const char pstrUsagePaletteDataOffset [] PROGMEM = "Pal Data Off"; -const char pstrUsagePaletteData [] PROGMEM = "Pal Data"; -const char pstrUsageBlitReport [] PROGMEM = "Blit Rpt"; -const char pstrUsageBlitRectangleX1 [] PROGMEM = "Blit Rect X1"; -const char pstrUsageBlitRectangleY1 [] PROGMEM = "Blit Rect Y1"; -const char pstrUsageBlitRectangleX2 [] PROGMEM = "Blit Rect X2"; -const char pstrUsageBlitRectangleY2 [] PROGMEM = "Blit Rect Y2"; -const char pstrUsageBlitData [] PROGMEM = "Blit Data"; -const char pstrUsageSoftButton [] PROGMEM = "Soft Btn"; -const char pstrUsageSoftButtonID [] PROGMEM = "Soft Btn ID"; -const char pstrUsageSoftButtonSide [] PROGMEM = "Soft Btn Side"; -const char pstrUsageSoftButtonOffset1 [] PROGMEM = "Soft Btn Off1"; -const char pstrUsageSoftButtonOffset2 [] PROGMEM = "Soft Btn Off2"; -const char pstrUsageSoftButtonReport [] PROGMEM = "Soft Btn Rpt"; - -// Medical Instrument Page -const char pstrUsageMedicalUltrasound [] PROGMEM = "Med Ultrasnd"; -const char pstrUsageVCRAcquisition [] PROGMEM = "VCR/Acq"; -const char pstrUsageFreezeThaw [] PROGMEM = "Freeze"; -const char pstrUsageClipStore [] PROGMEM = "Clip Store"; -const char pstrUsageUpdate [] PROGMEM = "Update"; -const char pstrUsageNext [] PROGMEM = "Next"; -const char pstrUsageSave [] PROGMEM = "Save"; -const char pstrUsagePrint [] PROGMEM = "Print"; -const char pstrUsageMicrophoneEnable [] PROGMEM = "Mic Enbl"; -const char pstrUsageCine [] PROGMEM = "Cine"; -const char pstrUsageTransmitPower [] PROGMEM = "Trans Pwr"; -//const char pstrUsageVolume [] PROGMEM = "Vol"; -const char pstrUsageFocus [] PROGMEM = "Focus"; -const char pstrUsageDepth [] PROGMEM = "Depth"; -const char pstrUsageSoftStepPrimary [] PROGMEM = "Soft Stp-Pri"; -const char pstrUsageSoftStepSecondary [] PROGMEM = "Soft Stp-Sec"; -const char pstrUsageDepthGainCompensation [] PROGMEM = "Dpth Gain Comp"; -const char pstrUsageZoomSelect [] PROGMEM = "Zoom Sel"; -const char pstrUsageZoomAdjust [] PROGMEM = "Zoom Adj"; -const char pstrUsageSpectralDopplerModeSelect [] PROGMEM = "Spec Dop Mode Sel"; -const char pstrUsageSpectralDopplerModeAdjust [] PROGMEM = "Spec Dop Mode Adj"; -const char pstrUsageColorDopplerModeSelect [] PROGMEM = "Color Dop Mode Sel"; -const char pstrUsageColorDopplerModeAdjust [] PROGMEM = "Color Dop Mode Adj"; -const char pstrUsageMotionModeSelect [] PROGMEM = "Motion Mode Sel"; -const char pstrUsageMotionModeAdjust [] PROGMEM = "Motion Mode Adj"; -const char pstrUsage2DModeSelect [] PROGMEM = "2D Mode Sel"; -const char pstrUsage2DModeAdjust [] PROGMEM = "2D Mode Adj"; -const char pstrUsageSoftControlSelect [] PROGMEM = "Soft Ctrl Sel"; -const char pstrUsageSoftControlAdjust [] PROGMEM = "Soft Ctrl Adj"; - -//extern const char *usagePageTitles0[15]; -//const char *usagePageTitles1[]; -//const char *genDesktopTitles0[]; -//const char *genDesktopTitles1[]; -//const char *genDesktopTitles2[]; -//const char *genDesktopTitles3[]; -//const char *genDesktopTitles4[]; -//const char *simuTitles0[]; -//const char *simuTitles1[]; -//const char *simuTitles2[]; -//const char *vrTitles0[]; -//const char *vrTitles1[]; -//const char *sportsCtrlTitles0[]; -//const char *sportsCtrlTitles1[]; -//const char *sportsCtrlTitles2[]; -//const char *gameTitles0[]; -//const char *gameTitles1[]; -//const char *genDevCtrlTitles[]; -//const char *ledTitles[]; -//const char *telTitles0[]; -//const char *telTitles1[]; -//const char *telTitles2[]; -//const char *telTitles3[]; -//const char *telTitles4[]; -//const char *telTitles5[]; -//const char *consTitles0[]; -//const char *consTitles1[]; -//const char *consTitles2[]; -//const char *consTitles3[]; -//const char *consTitles4[]; -//const char *consTitles5[]; -//const char *consTitles6[]; -//const char *consTitles7[]; -//const char *consTitles8[]; -//const char *consTitles9[]; -//const char *consTitlesA[]; -//const char *consTitlesB[]; -//const char *consTitlesC[]; -//const char *consTitlesD[]; -//const char *consTitlesE[]; -//const char *digitTitles0[]; -//const char *digitTitles1[]; -//const char *digitTitles2[]; -//const char *aplphanumTitles0[]; -//const char *aplphanumTitles1[]; -//const char *aplphanumTitles2[]; -//const char *medInstrTitles0[]; -//const char *medInstrTitles1[]; -//const char *medInstrTitles2[]; -//const char *medInstrTitles3[]; -//const char *medInstrTitles4[]; - +/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. + +This software may be distributed and modified under the terms of the GNU +General Public License version 2 (GPL2) as published by the Free Software +Foundation and appearing in the file GPL2.TXT included in the packaging of +this file. Please note that GPL2 Section 2[b] requires that all works based +on this software must also be made publicly available under the terms of +the GPL2 ("Copyleft"). + +Contact information +------------------- + +Circuits At Home, LTD +Web : http://www.circuitsathome.com +e-mail : support@circuitsathome.com + */ +#if !defined( __HIDUSAGESTR_H__) +#define __HIDUSAGESTR_H__ + +#include + +const char pstrSpace [] PROGMEM = " "; +const char pstrCRLF [] PROGMEM = "\r\n"; +const char pstrSingleTab [] PROGMEM = "\t"; +const char pstrDoubleTab [] PROGMEM = "\t\t"; +const char pstrTripleTab [] PROGMEM = "\t\t\t"; + +// Usage Page String Titles +const char pstrUsagePageUndefined [] PROGMEM = "Undef"; +const char pstrUsagePageGenericDesktopControls [] PROGMEM = "Gen Desktop Ctrls"; +const char pstrUsagePageSimulationControls [] PROGMEM = "Simu Ctrls"; +const char pstrUsagePageVRControls [] PROGMEM = "VR Ctrls"; +const char pstrUsagePageSportControls [] PROGMEM = "Sport Ctrls"; +const char pstrUsagePageGameControls [] PROGMEM = "Game Ctrls"; +const char pstrUsagePageGenericDeviceControls [] PROGMEM = "Gen Dev Ctrls"; +const char pstrUsagePageKeyboardKeypad [] PROGMEM = "Kbrd/Keypad"; +const char pstrUsagePageLEDs [] PROGMEM = "LEDs"; +const char pstrUsagePageButton [] PROGMEM = "Button"; +const char pstrUsagePageOrdinal [] PROGMEM = "Ordinal"; +const char pstrUsagePageTelephone [] PROGMEM = "Tel"; +const char pstrUsagePageConsumer [] PROGMEM = "Consumer"; +const char pstrUsagePageDigitizer [] PROGMEM = "Digitizer"; +const char pstrUsagePagePID [] PROGMEM = "PID"; +const char pstrUsagePageUnicode [] PROGMEM = "Unicode"; +const char pstrUsagePageAlphaNumericDisplay [] PROGMEM = "Alpha Num Disp"; +const char pstrUsagePageMedicalInstruments [] PROGMEM = "Medical Instr"; +const char pstrUsagePageMonitor [] PROGMEM = "Monitor"; +const char pstrUsagePagePower [] PROGMEM = "Power"; +const char pstrUsagePageBarCodeScanner [] PROGMEM = "Bar Code Scan"; +const char pstrUsagePageScale [] PROGMEM = "Scale"; +const char pstrUsagePageMSRDevices [] PROGMEM = "Magn Stripe Read Dev"; +const char pstrUsagePagePointOfSale [] PROGMEM = "POS"; +const char pstrUsagePageCameraControl [] PROGMEM = "Cam Ctrl"; +const char pstrUsagePageArcade [] PROGMEM = "Arcade"; +const char pstrUsagePageReserved [] PROGMEM = "Reserved"; +const char pstrUsagePageVendorDefined [] PROGMEM = "Vendor Def"; + +// Generic Desktop Controls Page +const char pstrUsagePointer [] PROGMEM = "Pointer"; +const char pstrUsageMouse [] PROGMEM = "Mouse"; +const char pstrUsageJoystick [] PROGMEM = "Joystick"; +const char pstrUsageGamePad [] PROGMEM = "Game Pad"; +const char pstrUsageKeyboard [] PROGMEM = "Kbrd"; +const char pstrUsageKeypad [] PROGMEM = "Keypad"; +const char pstrUsageMultiAxisController [] PROGMEM = "Multi-axis Ctrl"; +const char pstrUsageTabletPCSystemControls [] PROGMEM = "Tablet PC Sys Ctrls"; +const char pstrUsageX [] PROGMEM = "X"; +const char pstrUsageY [] PROGMEM = "Y"; +const char pstrUsageZ [] PROGMEM = "Z"; +const char pstrUsageRx [] PROGMEM = "Rx"; +const char pstrUsageRy [] PROGMEM = "Ry"; +const char pstrUsageRz [] PROGMEM = "Rz"; +const char pstrUsageSlider [] PROGMEM = "Slider"; +const char pstrUsageDial [] PROGMEM = "Dial"; +const char pstrUsageWheel [] PROGMEM = "Wheel"; +const char pstrUsageHatSwitch [] PROGMEM = "Hat Switch"; +const char pstrUsageCountedBuffer [] PROGMEM = "Counted Buf"; +const char pstrUsageByteCount [] PROGMEM = "Byte Count"; +const char pstrUsageMotionWakeup [] PROGMEM = "Motion Wakeup"; +const char pstrUsageStart [] PROGMEM = "Start"; +const char pstrUsageSelect [] PROGMEM = "Sel"; +const char pstrUsageVx [] PROGMEM = "Vx"; +const char pstrUsageVy [] PROGMEM = "Vy"; +const char pstrUsageVz [] PROGMEM = "Vz"; +const char pstrUsageVbrx [] PROGMEM = "Vbrx"; +const char pstrUsageVbry [] PROGMEM = "Vbry"; +const char pstrUsageVbrz [] PROGMEM = "Vbrz"; +const char pstrUsageVno [] PROGMEM = "Vno"; +const char pstrUsageFeatureNotification [] PROGMEM = "Feature Notif"; +const char pstrUsageResolutionMultiplier [] PROGMEM = "Res Mult"; +const char pstrUsageSystemControl [] PROGMEM = "Sys Ctrl"; +const char pstrUsageSystemPowerDown [] PROGMEM = "Sys Pwr Down"; +const char pstrUsageSystemSleep [] PROGMEM = "Sys Sleep"; +const char pstrUsageSystemWakeup [] PROGMEM = "Sys Wakeup"; +const char pstrUsageSystemContextMenu [] PROGMEM = "Sys Context Menu"; +const char pstrUsageSystemMainMenu [] PROGMEM = "Sys Main Menu"; +const char pstrUsageSystemAppMenu [] PROGMEM = "Sys App Menu"; +const char pstrUsageSystemMenuHelp [] PROGMEM = "Sys Menu Help"; +const char pstrUsageSystemMenuExit [] PROGMEM = "Sys Menu Exit"; +const char pstrUsageSystemMenuSelect [] PROGMEM = "Sys Menu Select"; +const char pstrUsageSystemMenuRight [] PROGMEM = "Sys Menu Right"; +const char pstrUsageSystemMenuLeft [] PROGMEM = "Sys Menu Left"; +const char pstrUsageSystemMenuUp [] PROGMEM = "Sys Menu Up"; +const char pstrUsageSystemMenuDown [] PROGMEM = "Sys Menu Down"; +const char pstrUsageSystemColdRestart [] PROGMEM = "Sys Cold Restart"; +const char pstrUsageSystemWarmRestart [] PROGMEM = "Sys Warm Restart"; +const char pstrUsageDPadUp [] PROGMEM = "D-pad Up"; +const char pstrUsageDPadDown [] PROGMEM = "D-pad Down"; +const char pstrUsageDPadRight [] PROGMEM = "D-pad Right"; +const char pstrUsageDPadLeft [] PROGMEM = "D-pad Left"; +const char pstrUsageSystemDock [] PROGMEM = "Sys Dock"; +const char pstrUsageSystemUndock [] PROGMEM = "Sys Undock"; +const char pstrUsageSystemSetup [] PROGMEM = "Sys Setup"; +const char pstrUsageSystemBreak [] PROGMEM = "Sys Break"; +const char pstrUsageSystemDebuggerBreak [] PROGMEM = "Sys Dbg Brk"; +const char pstrUsageApplicationBreak [] PROGMEM = "App Break"; +const char pstrUsageApplicationDebuggerBreak [] PROGMEM = "App Dbg Brk"; +const char pstrUsageSystemSpeakerMute [] PROGMEM = "Sys Spk Mute"; +const char pstrUsageSystemHibernate [] PROGMEM = "Sys Hiber"; +const char pstrUsageSystemDisplayInvert [] PROGMEM = "Sys Disp Inv"; +const char pstrUsageSystemDisplayInternal [] PROGMEM = "Sys Disp Int"; +const char pstrUsageSystemDisplayExternal [] PROGMEM = "Sys Disp Ext"; +const char pstrUsageSystemDisplayBoth [] PROGMEM = "Sys Disp Both"; +const char pstrUsageSystemDisplayDual [] PROGMEM = "Sys Disp Dual"; +const char pstrUsageSystemDisplayToggleIntExt [] PROGMEM = "Sys Disp Tgl Int/Ext"; +const char pstrUsageSystemDisplaySwapPriSec [] PROGMEM = "Sys Disp Swap Pri/Sec"; +const char pstrUsageSystemDisplayLCDAutoscale [] PROGMEM = "Sys Disp LCD Autoscale"; + +// Simulation Controls Page +const char pstrUsageFlightSimulationDevice [] PROGMEM = "Flight Simu Dev"; +const char pstrUsageAutomobileSimulationDevice [] PROGMEM = "Auto Simu Dev"; +const char pstrUsageTankSimulationDevice [] PROGMEM = "Tank Simu Dev"; +const char pstrUsageSpaceshipSimulationDevice [] PROGMEM = "Space Simu Dev"; +const char pstrUsageSubmarineSimulationDevice [] PROGMEM = "Subm Simu Dev"; +const char pstrUsageSailingSimulationDevice [] PROGMEM = "Sail Simu Dev"; +const char pstrUsageMotocicleSimulationDevice [] PROGMEM = "Moto Simu Dev"; +const char pstrUsageSportsSimulationDevice [] PROGMEM = "Sport Simu Dev"; +const char pstrUsageAirplaneSimulationDevice [] PROGMEM = "Airp Simu Dev"; +const char pstrUsageHelicopterSimulationDevice [] PROGMEM = "Heli Simu Dev"; +const char pstrUsageMagicCarpetSimulationDevice [] PROGMEM = "Magic Carpet Simu Dev"; +const char pstrUsageBicycleSimulationDevice [] PROGMEM = "Bike Simu Dev"; +const char pstrUsageFlightControlStick [] PROGMEM = "Flight Ctrl Stick"; +const char pstrUsageFlightStick [] PROGMEM = "Flight Stick"; +const char pstrUsageCyclicControl [] PROGMEM = "Cyclic Ctrl"; +const char pstrUsageCyclicTrim [] PROGMEM = "Cyclic Trim"; +const char pstrUsageFlightYoke [] PROGMEM = "Flight Yoke"; +const char pstrUsageTrackControl [] PROGMEM = "Track Ctrl"; +const char pstrUsageAileron [] PROGMEM = "Aileron"; +const char pstrUsageAileronTrim [] PROGMEM = "Aileron Trim"; +const char pstrUsageAntiTorqueControl [] PROGMEM = "Anti-Torque Ctrl"; +const char pstrUsageAutopilotEnable [] PROGMEM = "Autopilot Enable"; +const char pstrUsageChaffRelease [] PROGMEM = "Chaff Release"; +const char pstrUsageCollectiveControl [] PROGMEM = "Collective Ctrl"; +const char pstrUsageDiveBrake [] PROGMEM = "Dive Brake"; +const char pstrUsageElectronicCountermeasures [] PROGMEM = "El Countermeasures"; +const char pstrUsageElevator [] PROGMEM = "Elevator"; +const char pstrUsageElevatorTrim [] PROGMEM = "Elevator Trim"; +const char pstrUsageRudder [] PROGMEM = "Rudder"; +const char pstrUsageThrottle [] PROGMEM = "Throttle"; +const char pstrUsageFlightCommunications [] PROGMEM = "Flight Comm"; +const char pstrUsageFlareRelease [] PROGMEM = "Flare Release"; +const char pstrUsageLandingGear [] PROGMEM = "Landing Gear"; +const char pstrUsageToeBrake [] PROGMEM = "Toe Brake"; +const char pstrUsageTrigger [] PROGMEM = "Trigger"; +const char pstrUsageWeaponsArm [] PROGMEM = "Weapons Arm"; +const char pstrUsageWeaponsSelect [] PROGMEM = "Weapons Sel"; +const char pstrUsageWingFlaps [] PROGMEM = "Wing Flaps"; +const char pstrUsageAccelerator [] PROGMEM = "Accel"; +const char pstrUsageBrake [] PROGMEM = "Brake"; +const char pstrUsageClutch [] PROGMEM = "Clutch"; +const char pstrUsageShifter [] PROGMEM = "Shifter"; +const char pstrUsageSteering [] PROGMEM = "Steering"; +const char pstrUsageTurretDirection [] PROGMEM = "Turret Dir"; +const char pstrUsageBarrelElevation [] PROGMEM = "Barrel Ele"; +const char pstrUsageDivePlane [] PROGMEM = "Dive Plane"; +const char pstrUsageBallast [] PROGMEM = "Ballast"; +const char pstrUsageBicycleCrank [] PROGMEM = "Bicycle Crank"; +const char pstrUsageHandleBars [] PROGMEM = "Handle Bars"; +const char pstrUsageFrontBrake [] PROGMEM = "Front Brake"; +const char pstrUsageRearBrake [] PROGMEM = "Rear Brake"; + +// VR Controls Page +const char pstrUsageBelt [] PROGMEM = "Belt"; +const char pstrUsageBodySuit [] PROGMEM = "Body Suit"; +const char pstrUsageFlexor [] PROGMEM = "Flexor"; +const char pstrUsageGlove [] PROGMEM = "Glove"; +const char pstrUsageHeadTracker [] PROGMEM = "Head Track"; +const char pstrUsageHeadMountedDisplay [] PROGMEM = "Head Disp"; +const char pstrUsageHandTracker [] PROGMEM = "Hand Track"; +const char pstrUsageOculometer [] PROGMEM = "Oculometer"; +const char pstrUsageVest [] PROGMEM = "Vest"; +const char pstrUsageAnimatronicDevice [] PROGMEM = "Animat Dev"; +const char pstrUsageStereoEnable [] PROGMEM = "Stereo Enbl"; +const char pstrUsageDisplayEnable [] PROGMEM = "Display Enbl"; + +// Sport Controls Page +const char pstrUsageBaseballBat [] PROGMEM = "Baseball Bat"; +const char pstrUsageGolfClub [] PROGMEM = "Golf Club"; +const char pstrUsageRowingMachine [] PROGMEM = "Rowing Mach"; +const char pstrUsageTreadmill [] PROGMEM = "Treadmill"; +const char pstrUsageOar [] PROGMEM = "Oar"; +const char pstrUsageSlope [] PROGMEM = "Slope"; +const char pstrUsageRate [] PROGMEM = "Rate"; +const char pstrUsageStickSpeed [] PROGMEM = "Stick Speed"; +const char pstrUsageStickFaceAngle [] PROGMEM = "Stick Face Ang"; +const char pstrUsageStickHeelToe [] PROGMEM = "Stick Heel/Toe"; +const char pstrUsageStickFollowThough [] PROGMEM = "Stick Flw Thru"; +const char pstrUsageStickTempo [] PROGMEM = "Stick Tempo"; +const char pstrUsageStickType [] PROGMEM = "Stick Type"; +const char pstrUsageStickHeight [] PROGMEM = "Stick Hght"; +const char pstrUsagePutter [] PROGMEM = "Putter"; +const char pstrUsage1Iron [] PROGMEM = "1 Iron"; +const char pstrUsage2Iron [] PROGMEM = "2 Iron"; +const char pstrUsage3Iron [] PROGMEM = "3 Iron"; +const char pstrUsage4Iron [] PROGMEM = "4 Iron"; +const char pstrUsage5Iron [] PROGMEM = "5 Iron"; +const char pstrUsage6Iron [] PROGMEM = "6 Iron"; +const char pstrUsage7Iron [] PROGMEM = "7 Iron"; +const char pstrUsage8Iron [] PROGMEM = "8 Iron"; +const char pstrUsage9Iron [] PROGMEM = "9 Iron"; +const char pstrUsage10Iron [] PROGMEM = "10 Iron"; +const char pstrUsage11Iron [] PROGMEM = "11 Iron"; +const char pstrUsageSandWedge [] PROGMEM = "Sand Wedge"; +const char pstrUsageLoftWedge [] PROGMEM = "Loft Wedge"; +const char pstrUsagePowerWedge [] PROGMEM = "Pwr Wedge"; +const char pstrUsage1Wood [] PROGMEM = "1 Wood"; +const char pstrUsage3Wood [] PROGMEM = "3 Wood"; +const char pstrUsage5Wood [] PROGMEM = "5 Wood"; +const char pstrUsage7Wood [] PROGMEM = "7 Wood"; +const char pstrUsage9Wood [] PROGMEM = "9 Wood"; + +// Game Controls Page +const char pstrUsage3DGameController [] PROGMEM = "3D Game Ctrl"; +const char pstrUsagePinballDevice [] PROGMEM = "Pinball Dev"; +const char pstrUsageGunDevice [] PROGMEM = "Gun Dev"; +const char pstrUsagePointOfView [] PROGMEM = "POV"; +const char pstrUsageTurnRightLeft [] PROGMEM = "Turn Right Left"; +const char pstrUsagePitchForwardBackward [] PROGMEM = "Pitch Fwd/Back"; +const char pstrUsageRollRightLeft [] PROGMEM = "Roll Right/Left"; +const char pstrUsageMoveRightLeft [] PROGMEM = "Move Right/Left"; +const char pstrUsageMoveForwardBackward [] PROGMEM = "Move Fwd/Back"; +const char pstrUsageMoveUpDown [] PROGMEM = "Move Up/Down"; +const char pstrUsageLeanRightLeft [] PROGMEM = "Lean Right/Left"; +const char pstrUsageLeanForwardBackward [] PROGMEM = "Lean Fwd/Back"; +const char pstrUsageHeightOfPOV [] PROGMEM = "Height of POV"; +const char pstrUsageFlipper [] PROGMEM = "Flipper"; +const char pstrUsageSecondaryFlipper [] PROGMEM = "Second Flipper"; +const char pstrUsageBump [] PROGMEM = "Bump"; +const char pstrUsageNewGame [] PROGMEM = "New Game"; +const char pstrUsageShootBall [] PROGMEM = "Shoot Ball"; +const char pstrUsagePlayer [] PROGMEM = "Player"; +const char pstrUsageGunBolt [] PROGMEM = "Gun Bolt"; +const char pstrUsageGunClip [] PROGMEM = "Gun Clip"; +const char pstrUsageGunSelector [] PROGMEM = "Gun Sel"; +const char pstrUsageGunSingleShot [] PROGMEM = "Gun Sngl Shot"; +const char pstrUsageGunBurst [] PROGMEM = "Gun Burst"; +const char pstrUsageGunAutomatic [] PROGMEM = "Gun Auto"; +const char pstrUsageGunSafety [] PROGMEM = "Gun Safety"; +const char pstrUsageGamepadFireJump [] PROGMEM = "Gamepad Fire/Jump"; +const char pstrUsageGamepadTrigger [] PROGMEM = "Gamepad Trig"; + +// Generic Device Controls Page +const char pstrUsageBatteryStrength [] PROGMEM = "Bat Strength"; +const char pstrUsageWirelessChannel [] PROGMEM = "Wireless Ch"; +const char pstrUsageWirelessID [] PROGMEM = "Wireless ID"; +const char pstrUsageDiscoverWirelessControl [] PROGMEM = "Discover Wireless Ctrl"; +const char pstrUsageSecurityCodeCharEntered [] PROGMEM = "Sec Code Char Entrd"; +const char pstrUsageSecurityCodeCharErased [] PROGMEM = "Sec Code Char Erased"; +const char pstrUsageSecurityCodeCleared [] PROGMEM = "Sec Code Cleared"; + +// LED Page +const char pstrUsageNumLock [] PROGMEM = "Num Lock"; +const char pstrUsageCapsLock [] PROGMEM = "Caps Lock"; +const char pstrUsageScrollLock [] PROGMEM = "Scroll Lock"; +const char pstrUsageCompose [] PROGMEM = "Compose"; +const char pstrUsageKana [] PROGMEM = "Kana"; +const char pstrUsagePower [] PROGMEM = "Pwr"; +const char pstrUsageShift [] PROGMEM = "Shift"; +const char pstrUsageDoNotDisturb [] PROGMEM = "DND"; +const char pstrUsageMute [] PROGMEM = "Mute"; +const char pstrUsageToneEnable [] PROGMEM = "Tone Enbl"; +const char pstrUsageHighCutFilter [] PROGMEM = "High Cut Fltr"; +const char pstrUsageLowCutFilter [] PROGMEM = "Low Cut Fltr"; +const char pstrUsageEqualizerEnable [] PROGMEM = "Eq Enbl"; +const char pstrUsageSoundFieldOn [] PROGMEM = "Sound Field On"; +const char pstrUsageSurroundOn [] PROGMEM = "Surround On"; +const char pstrUsageRepeat [] PROGMEM = "Repeat"; +const char pstrUsageStereo [] PROGMEM = "Stereo"; +const char pstrUsageSamplingRateDetect [] PROGMEM = "Smpl Rate Detect"; +const char pstrUsageSpinning [] PROGMEM = "Spinning"; +const char pstrUsageCAV [] PROGMEM = "CAV"; +const char pstrUsageCLV [] PROGMEM = "CLV"; +const char pstrUsageRecordingFormatDetect [] PROGMEM = "Rec Format Detect"; +const char pstrUsageOffHook [] PROGMEM = "Off Hook"; +const char pstrUsageRing [] PROGMEM = "Ring"; +const char pstrUsageMessageWaiting [] PROGMEM = "Msg Wait"; +const char pstrUsageDataMode [] PROGMEM = "Data Mode"; +const char pstrUsageBatteryOperation [] PROGMEM = "Bat Op"; +const char pstrUsageBatteryOK [] PROGMEM = "Bat OK"; +const char pstrUsageBatteryLow [] PROGMEM = "Bat Low"; +const char pstrUsageSpeaker [] PROGMEM = "Speaker"; +const char pstrUsageHeadSet [] PROGMEM = "Head Set"; +const char pstrUsageHold [] PROGMEM = "Hold"; +const char pstrUsageMicrophone [] PROGMEM = "Mic"; +const char pstrUsageCoverage [] PROGMEM = "Coverage"; +const char pstrUsageNightMode [] PROGMEM = "Night Mode"; +const char pstrUsageSendCalls [] PROGMEM = "Send Calls"; +const char pstrUsageCallPickup [] PROGMEM = "Call Pickup"; +const char pstrUsageConference [] PROGMEM = "Conf"; +const char pstrUsageStandBy [] PROGMEM = "Stand-by"; +const char pstrUsageCameraOn [] PROGMEM = "Cam On"; +const char pstrUsageCameraOff [] PROGMEM = "Cam Off"; +const char pstrUsageOnLine [] PROGMEM = "On-Line"; +const char pstrUsageOffLine [] PROGMEM = "Off-Line"; +const char pstrUsageBusy [] PROGMEM = "Busy"; +const char pstrUsageReady [] PROGMEM = "Ready"; +const char pstrUsagePaperOut [] PROGMEM = "Paper Out"; +const char pstrUsagePaperJam [] PROGMEM = "Paper Jam"; +const char pstrUsageRemote [] PROGMEM = "Remote"; +const char pstrUsageForward [] PROGMEM = "Fwd"; +const char pstrUsageReverse [] PROGMEM = "Rev"; +const char pstrUsageStop [] PROGMEM = "Stop"; +const char pstrUsageRewind [] PROGMEM = "Rewind"; +const char pstrUsageFastForward [] PROGMEM = "Fast Fwd"; +const char pstrUsagePlay [] PROGMEM = "Play"; +const char pstrUsagePause [] PROGMEM = "Pause"; +const char pstrUsageRecord [] PROGMEM = "Rec"; +const char pstrUsageError [] PROGMEM = "Error"; +const char pstrUsageSelectedIndicator [] PROGMEM = "Usage Sel Ind"; +const char pstrUsageInUseIndicator [] PROGMEM = "Usage In Use Ind"; +const char pstrUsageMultiModeIndicator [] PROGMEM = "Usage Multi Mode Ind"; +const char pstrUsageIndicatorOn [] PROGMEM = "Ind On"; +const char pstrUsageIndicatorFlash [] PROGMEM = "Ind Flash"; +const char pstrUsageIndicatorSlowBlink [] PROGMEM = "Ind Slow Blk"; +const char pstrUsageIndicatorFastBlink [] PROGMEM = "Ind Fast Blk"; +const char pstrUsageIndicatorOff [] PROGMEM = "Ind Off"; +const char pstrUsageFlashOnTime [] PROGMEM = "Flash On Time"; +const char pstrUsageSlowBlinkOnTime [] PROGMEM = "Slow Blk On Time"; +const char pstrUsageSlowBlinkOffTime [] PROGMEM = "Slow Blk Off Time"; +const char pstrUsageFastBlinkOnTime [] PROGMEM = "Fast Blk On Time"; +const char pstrUsageFastBlinkOffTime [] PROGMEM = "Fast Blk Off Time"; +const char pstrUsageIndicatorColor [] PROGMEM = "Usage Ind Color"; +const char pstrUsageIndicatorRed [] PROGMEM = "Ind Red"; +const char pstrUsageIndicatorGreen [] PROGMEM = "Ind Green"; +const char pstrUsageIndicatorAmber [] PROGMEM = "Ind Amber"; +const char pstrUsageGenericIndicator [] PROGMEM = "Gen Ind"; +const char pstrUsageSystemSuspend [] PROGMEM = "Sys Suspend"; +const char pstrUsageExternalPowerConnected [] PROGMEM = "Ext Pwr Conn"; + +// Telephony Usage Page +const char pstrUsagePhone [] PROGMEM = "Phone"; +const char pstrUsageAnsweringMachine [] PROGMEM = "Answ Mach"; +const char pstrUsageMessageControls [] PROGMEM = "Msg Ctrls"; +const char pstrUsageHandset [] PROGMEM = "Handset"; +const char pstrUsageHeadset [] PROGMEM = "Headset"; +const char pstrUsageTelephonyKeyPad [] PROGMEM = "Tel Key Pad"; +const char pstrUsageProgrammableButton [] PROGMEM = "Prog Button"; +const char pstrUsageHookSwitch [] PROGMEM = "Hook Sw"; +const char pstrUsageFlash [] PROGMEM = "Flash"; +const char pstrUsageFeature [] PROGMEM = "Feature"; +//const char pstrUsageHold [] PROGMEM = "Hold"; +const char pstrUsageRedial [] PROGMEM = "Redial"; +const char pstrUsageTransfer [] PROGMEM = "Transfer"; +const char pstrUsageDrop [] PROGMEM = "Drop"; +const char pstrUsagePark [] PROGMEM = "Park"; +const char pstrUsageForwardCalls [] PROGMEM = "Fwd Calls"; +const char pstrUsageAlternateFunction [] PROGMEM = "Alt Func"; +const char pstrUsageLine [] PROGMEM = "Line"; +const char pstrUsageSpeakerPhone [] PROGMEM = "Spk Phone"; +//const char pstrUsageConference [] PROGMEM = "Conference"; +const char pstrUsageRingEnable [] PROGMEM = "Ring Enbl"; +const char pstrUsageRingSelect [] PROGMEM = "Ring Sel"; +const char pstrUsagePhoneMute [] PROGMEM = "Phone Mute"; +const char pstrUsageCallerID [] PROGMEM = "Caller ID"; +const char pstrUsageSend [] PROGMEM = "Send"; +const char pstrUsageSpeedDial [] PROGMEM = "Speed Dial"; +const char pstrUsageStoreNumber [] PROGMEM = "Store Num"; +const char pstrUsageRecallNumber [] PROGMEM = "Recall Num"; +const char pstrUsagePhoneDirectory [] PROGMEM = "Phone Dir"; +const char pstrUsageVoiceMail [] PROGMEM = "Voice Mail"; +const char pstrUsageScreenCalls [] PROGMEM = "Screen Calls"; +//const char pstrUsageDoNotDisturb [] PROGMEM = "Do Not Disturb"; +const char pstrUsageMessage [] PROGMEM = "Msg"; +const char pstrUsageAnswerOnOff [] PROGMEM = "Answer On/Off"; +const char pstrUsageInsideDialTone [] PROGMEM = "Inside Dial Tone"; +const char pstrUsageOutsideDialTone [] PROGMEM = "Outside Dial Tone"; +const char pstrUsageInsideRingTone [] PROGMEM = "Inside Ring Tone"; +const char pstrUsageOutsideRingTone [] PROGMEM = "Outside Ring Tone"; +const char pstrUsagePriorityRingTone [] PROGMEM = "Prior Ring Tone"; +const char pstrUsageInsideRingback [] PROGMEM = "Inside Ringback"; +const char pstrUsagePriorityRingback [] PROGMEM = "Priority Ringback"; +const char pstrUsageLineBusyTone [] PROGMEM = "Ln Busy Tone"; +const char pstrUsageReorderTone [] PROGMEM = "Reorder Tone"; +const char pstrUsageCallWaitingTone [] PROGMEM = "Call Wait Tone"; +const char pstrUsageConfirmationTone1 [] PROGMEM = "Cnfrm Tone1"; +const char pstrUsageConfirmationTone2 [] PROGMEM = "Cnfrm Tone2"; +const char pstrUsageTonesOff [] PROGMEM = "Tones Off"; +const char pstrUsageOutsideRingback [] PROGMEM = "Outside Ringback"; +const char pstrUsageRinger [] PROGMEM = "Ringer"; +const char pstrUsagePhoneKey0 [] PROGMEM = "0"; +const char pstrUsagePhoneKey1 [] PROGMEM = "1"; +const char pstrUsagePhoneKey2 [] PROGMEM = "2"; +const char pstrUsagePhoneKey3 [] PROGMEM = "3"; +const char pstrUsagePhoneKey4 [] PROGMEM = "4"; +const char pstrUsagePhoneKey5 [] PROGMEM = "5"; +const char pstrUsagePhoneKey6 [] PROGMEM = "6"; +const char pstrUsagePhoneKey7 [] PROGMEM = "7"; +const char pstrUsagePhoneKey8 [] PROGMEM = "8"; +const char pstrUsagePhoneKey9 [] PROGMEM = "9"; +const char pstrUsagePhoneKeyStar [] PROGMEM = "*"; +const char pstrUsagePhoneKeyPound [] PROGMEM = "#"; +const char pstrUsagePhoneKeyA [] PROGMEM = "A"; +const char pstrUsagePhoneKeyB [] PROGMEM = "B"; +const char pstrUsagePhoneKeyC [] PROGMEM = "C"; +const char pstrUsagePhoneKeyD [] PROGMEM = "D"; + +// Consumer Usage Page +const char pstrUsageConsumerControl [] PROGMEM = "Consumer Ctrl"; +const char pstrUsageNumericKeyPad [] PROGMEM = "Num Key Pad"; +//const char pstrUsageProgrammableButton [] PROGMEM = "Prog Btn"; +//const char pstrUsageMicrophone [] PROGMEM = "Mic"; +const char pstrUsageHeadphone [] PROGMEM = "Headphone"; +const char pstrUsageGraphicEqualizer [] PROGMEM = "Graph Eq"; +const char pstrUsagePlus10 [] PROGMEM = "+10"; +const char pstrUsagePlus100 [] PROGMEM = "+100"; +const char pstrUsageAMPM [] PROGMEM = "AM/PM"; +//const char pstrUsagePower [] PROGMEM = "Pwr"; +const char pstrUsageReset [] PROGMEM = "Reset"; +const char pstrUsageSleep [] PROGMEM = "Sleep"; +const char pstrUsageSleepAfter [] PROGMEM = "Sleep After"; +const char pstrUsageSleepMode [] PROGMEM = "Sleep Mode"; +const char pstrUsageIllumination [] PROGMEM = "Illumin"; +const char pstrUsageFunctionButtons [] PROGMEM = "Func Btns"; +const char pstrUsageMenu [] PROGMEM = "Menu"; +const char pstrUsageMenuPick [] PROGMEM = "Menu Pick"; +const char pstrUsageMenuUp [] PROGMEM = "Menu Up"; +const char pstrUsageMenuDown [] PROGMEM = "Menu Down"; +const char pstrUsageMenuLeft [] PROGMEM = "Menu Left"; +const char pstrUsageMenuRight [] PROGMEM = "Menu Right"; +const char pstrUsageMenuEscape [] PROGMEM = "Menu Esc"; +const char pstrUsageMenuValueIncrease [] PROGMEM = "Menu Val Inc"; +const char pstrUsageMenuValueDecrease [] PROGMEM = "Menu Val Dec"; +const char pstrUsageDataOnScreen [] PROGMEM = "Data On Scr"; +const char pstrUsageClosedCaption [] PROGMEM = "Closed Cptn"; +const char pstrUsageClosedCaptionSelect [] PROGMEM = "Closed Cptn Sel"; +const char pstrUsageVCRTV [] PROGMEM = "VCR/TV"; +const char pstrUsageBroadcastMode [] PROGMEM = "Brdcast Mode"; +const char pstrUsageSnapshot [] PROGMEM = "Snapshot"; +const char pstrUsageStill [] PROGMEM = "Still"; +const char pstrUsageSelection [] PROGMEM = "Sel"; +const char pstrUsageAssignSelection [] PROGMEM = "Assign Sel"; +const char pstrUsageModeStep [] PROGMEM = "Mode Step"; +const char pstrUsageRecallLast [] PROGMEM = "Recall Last"; +const char pstrUsageEnterChannel [] PROGMEM = "Entr Channel"; +const char pstrUsageOrderMovie [] PROGMEM = "Ord Movie"; +const char pstrUsageChannel [] PROGMEM = "Channel"; +const char pstrUsageMediaSelection [] PROGMEM = "Med Sel"; +const char pstrUsageMediaSelectComputer [] PROGMEM = "Med Sel Comp"; +const char pstrUsageMediaSelectTV [] PROGMEM = "Med Sel TV"; +const char pstrUsageMediaSelectWWW [] PROGMEM = "Med Sel WWW"; +const char pstrUsageMediaSelectDVD [] PROGMEM = "Med Sel DVD"; +const char pstrUsageMediaSelectTelephone [] PROGMEM = "Med Sel Tel"; +const char pstrUsageMediaSelectProgramGuide [] PROGMEM = "Med Sel PG"; +const char pstrUsageMediaSelectVideoPhone [] PROGMEM = "Med Sel Vid"; +const char pstrUsageMediaSelectGames [] PROGMEM = "Med Sel Games"; +const char pstrUsageMediaSelectMessages [] PROGMEM = "Med Sel Msg"; +const char pstrUsageMediaSelectCD [] PROGMEM = "Med Sel CD"; +const char pstrUsageMediaSelectVCR [] PROGMEM = "Med Sel VCR"; +const char pstrUsageMediaSelectTuner [] PROGMEM = "Med Sel Tuner"; +const char pstrUsageQuit [] PROGMEM = "Quit"; +const char pstrUsageHelp [] PROGMEM = "Help"; +const char pstrUsageMediaSelectTape [] PROGMEM = "Med Sel Tape"; +const char pstrUsageMediaSelectCable [] PROGMEM = "Med Sel Cbl"; +const char pstrUsageMediaSelectSatellite [] PROGMEM = "Med Sel Sat"; +const char pstrUsageMediaSelectSecurity [] PROGMEM = "Med Sel Secur"; +const char pstrUsageMediaSelectHome [] PROGMEM = "Med Sel Home"; +const char pstrUsageMediaSelectCall [] PROGMEM = "Med Sel Call"; +const char pstrUsageChannelIncrement [] PROGMEM = "Ch Inc"; +const char pstrUsageChannelDecrement [] PROGMEM = "Ch Dec"; +const char pstrUsageMediaSelectSAP [] PROGMEM = "Med Sel SAP"; +const char pstrUsageVCRPlus [] PROGMEM = "VCR+"; +const char pstrUsageOnce [] PROGMEM = "Once"; +const char pstrUsageDaily [] PROGMEM = "Daily"; +const char pstrUsageWeekly [] PROGMEM = "Weekly"; +const char pstrUsageMonthly [] PROGMEM = "Monthly"; +//const char pstrUsagePlay [] PROGMEM = "Play"; +//const char pstrUsagePause [] PROGMEM = "Pause"; +//const char pstrUsageRecord [] PROGMEM = "Rec"; +//const char pstrUsageFastForward [] PROGMEM = "FF"; +//const char pstrUsageRewind [] PROGMEM = "Rewind"; +const char pstrUsageScanNextTrack [] PROGMEM = "Next Track"; +const char pstrUsageScanPreviousTrack [] PROGMEM = "Prev Track"; +//const char pstrUsageStop [] PROGMEM = "Stop"; +const char pstrUsageEject [] PROGMEM = "Eject"; +const char pstrUsageRandomPlay [] PROGMEM = "Random"; +const char pstrUsageSelectDisk [] PROGMEM = "Sel Disk"; +const char pstrUsageEnterDisk [] PROGMEM = "Ent Disk"; +//const char pstrUsageRepeat [] PROGMEM = "Repeat"; +const char pstrUsageTracking [] PROGMEM = "Tracking"; +const char pstrUsageTrackNormal [] PROGMEM = "Trk Norm"; +const char pstrUsageSlowTracking [] PROGMEM = "Slow Trk"; +const char pstrUsageFrameForward [] PROGMEM = "Frm Fwd"; +const char pstrUsageFrameBackwards [] PROGMEM = "Frm Back"; +const char pstrUsageMark [] PROGMEM = "Mark"; +const char pstrUsageClearMark [] PROGMEM = "Clr Mark"; +const char pstrUsageRepeatFromMark [] PROGMEM = "Rpt Mark"; +const char pstrUsageReturnToMark [] PROGMEM = "Ret to Mark"; +const char pstrUsageSearchMarkForward [] PROGMEM = "Search Mark Fwd"; +const char pstrUsageSearchMarkBackwards [] PROGMEM = "Search Mark Back"; +const char pstrUsageCounterReset [] PROGMEM = "Counter Reset"; +const char pstrUsageShowCounter [] PROGMEM = "Show Counter"; +const char pstrUsageTrackingIncrement [] PROGMEM = "Track Inc"; +const char pstrUsageTrackingDecrement [] PROGMEM = "Track Dec"; +const char pstrUsageStopEject [] PROGMEM = "Stop/Eject"; +const char pstrUsagePlayPause [] PROGMEM = "Play/Pause"; +const char pstrUsagePlaySkip [] PROGMEM = "Play/Skip"; +const char pstrUsageVolume [] PROGMEM = "Vol"; +const char pstrUsageBalance [] PROGMEM = "Balance"; +//const char pstrUsageMute [] PROGMEM = "Mute"; +const char pstrUsageBass [] PROGMEM = "Bass"; +const char pstrUsageTreble [] PROGMEM = "Treble"; +const char pstrUsageBassBoost [] PROGMEM = "Bass Boost"; +const char pstrUsageSurroundMode [] PROGMEM = "Surround"; +const char pstrUsageLoudness [] PROGMEM = "Loud"; +const char pstrUsageMPX [] PROGMEM = "MPX"; +const char pstrUsageVolumeIncrement [] PROGMEM = "Vol Inc"; +const char pstrUsageVolumeDecrement [] PROGMEM = "Vol Dec"; +const char pstrUsageSpeedSelect [] PROGMEM = "Speed"; +const char pstrUsagePlaybackSpeed [] PROGMEM = "Play Speed"; +const char pstrUsageStandardPlay [] PROGMEM = "Std Play"; +const char pstrUsageLongPlay [] PROGMEM = "Long Play"; +const char pstrUsageExtendedPlay [] PROGMEM = "Ext Play"; +const char pstrUsageSlow [] PROGMEM = "Slow"; +const char pstrUsageFanEnable [] PROGMEM = "Fan Enbl"; +const char pstrUsageFanSpeed [] PROGMEM = "Fan Speed"; +const char pstrUsageLightEnable [] PROGMEM = "Light Enbl"; +const char pstrUsageLightIlluminationLevel [] PROGMEM = "Light Illum Lev"; +const char pstrUsageClimateControlEnable [] PROGMEM = "Climate Enbl"; +const char pstrUsageRoomTemperature [] PROGMEM = "Room Temp"; +const char pstrUsageSecurityEnable [] PROGMEM = "Secur Enbl"; +const char pstrUsageFireAlarm [] PROGMEM = "Fire Alm"; +const char pstrUsagePoliceAlarm [] PROGMEM = "Police Alm"; +const char pstrUsageProximity [] PROGMEM = "Prox"; +const char pstrUsageMotion [] PROGMEM = "Motion"; +const char pstrUsageDuresAlarm [] PROGMEM = "Dures Alm"; +const char pstrUsageHoldupAlarm [] PROGMEM = "Holdup Alm"; +const char pstrUsageMedicalAlarm [] PROGMEM = "Med Alm"; +const char pstrUsageBalanceRight [] PROGMEM = "Balance Right"; +const char pstrUsageBalanceLeft [] PROGMEM = "Balance Left"; +const char pstrUsageBassIncrement [] PROGMEM = "Bass Inc"; +const char pstrUsageBassDecrement [] PROGMEM = "Bass Dec"; +const char pstrUsageTrebleIncrement [] PROGMEM = "Treble Inc"; +const char pstrUsageTrebleDecrement [] PROGMEM = "Treble Dec"; +const char pstrUsageSpeakerSystem [] PROGMEM = "Spk Sys"; +const char pstrUsageChannelLeft [] PROGMEM = "Ch Left"; +const char pstrUsageChannelRight [] PROGMEM = "Ch Right"; +const char pstrUsageChannelCenter [] PROGMEM = "Ch Center"; +const char pstrUsageChannelFront [] PROGMEM = "Ch Front"; +const char pstrUsageChannelCenterFront [] PROGMEM = "Ch Cntr Front"; +const char pstrUsageChannelSide [] PROGMEM = "Ch Side"; +const char pstrUsageChannelSurround [] PROGMEM = "Ch Surround"; +const char pstrUsageChannelLowFreqEnhancement [] PROGMEM = "Ch Low Freq Enh"; +const char pstrUsageChannelTop [] PROGMEM = "Ch Top"; +const char pstrUsageChannelUnknown [] PROGMEM = "Ch Unk"; +const char pstrUsageSubChannel [] PROGMEM = "Sub-ch"; +const char pstrUsageSubChannelIncrement [] PROGMEM = "Sub-ch Inc"; +const char pstrUsageSubChannelDecrement [] PROGMEM = "Sub-ch Dec"; +const char pstrUsageAlternateAudioIncrement [] PROGMEM = "Alt Aud Inc"; +const char pstrUsageAlternateAudioDecrement [] PROGMEM = "Alt Aud Dec"; +const char pstrUsageApplicationLaunchButtons [] PROGMEM = "App Launch Btns"; +const char pstrUsageALLaunchButtonConfigTool [] PROGMEM = "AL Launch Conf Tl"; +const char pstrUsageALProgrammableButton [] PROGMEM = "AL Pgm Btn"; +const char pstrUsageALConsumerControlConfig [] PROGMEM = "AL Cons Ctrl Cfg"; +const char pstrUsageALWordProcessor [] PROGMEM = "AL Word Proc"; +const char pstrUsageALTextEditor [] PROGMEM = "AL Txt Edtr"; +const char pstrUsageALSpreadsheet [] PROGMEM = "AL Sprdsheet"; +const char pstrUsageALGraphicsEditor [] PROGMEM = "AL Graph Edtr"; +const char pstrUsageALPresentationApp [] PROGMEM = "AL Present App"; +const char pstrUsageALDatabaseApp [] PROGMEM = "AL DB App"; +const char pstrUsageALEmailReader [] PROGMEM = "AL E-mail Rdr"; +const char pstrUsageALNewsreader [] PROGMEM = "AL Newsrdr"; +const char pstrUsageALVoicemail [] PROGMEM = "AL Voicemail"; +const char pstrUsageALContactsAddressBook [] PROGMEM = "AL Addr Book"; +const char pstrUsageALCalendarSchedule [] PROGMEM = "AL Clndr/Schdlr"; +const char pstrUsageALTaskProjectManager [] PROGMEM = "AL Task/Prj Mgr"; +const char pstrUsageALLogJournalTimecard [] PROGMEM = "AL Log/Jrnl/Tmcrd"; +const char pstrUsageALCheckbookFinance [] PROGMEM = "AL Chckbook/Fin"; +const char pstrUsageALCalculator [] PROGMEM = "AL Calc"; +const char pstrUsageALAVCapturePlayback [] PROGMEM = "AL A/V Capt/Play"; +const char pstrUsageALLocalMachineBrowser [] PROGMEM = "AL Loc Mach Brow"; +const char pstrUsageALLANWANBrow [] PROGMEM = "AL LAN/WAN Brow"; +const char pstrUsageALInternetBrowser [] PROGMEM = "AL I-net Brow"; +const char pstrUsageALRemoteNetISPConnect [] PROGMEM = "AL Rem Net Con"; +const char pstrUsageALNetworkConference [] PROGMEM = "AL Net Conf"; +const char pstrUsageALNetworkChat [] PROGMEM = "AL Net Chat"; +const char pstrUsageALTelephonyDialer [] PROGMEM = "AL Tel/Dial"; +const char pstrUsageALLogon [] PROGMEM = "AL Logon"; +const char pstrUsageALLogoff [] PROGMEM = "AL Logoff"; +const char pstrUsageALLogonLogoff [] PROGMEM = "AL Logon/Logoff"; +const char pstrUsageALTermLockScrSav [] PROGMEM = "AL Term Lock/Scr Sav"; +const char pstrUsageALControlPannel [] PROGMEM = "AL Ctrl Pan"; +const char pstrUsageALCommandLineProcessorRun [] PROGMEM = "AL Cmd/Run"; +const char pstrUsageALProcessTaskManager [] PROGMEM = "AL Task Mgr"; +const char pstrUsageALSelectTaskApplication [] PROGMEM = "AL Sel App"; +const char pstrUsageALNextTaskApplication [] PROGMEM = "AL Next App"; +const char pstrUsageALPreviousTaskApplication [] PROGMEM = "AL Prev App"; +const char pstrUsageALPreemptiveHaltTaskApp [] PROGMEM = "AL Prmpt Halt App"; +const char pstrUsageALIntegratedHelpCenter [] PROGMEM = "AL Hlp Cntr"; +const char pstrUsageALDocuments [] PROGMEM = "AL Docs"; +const char pstrUsageALThesaurus [] PROGMEM = "AL Thsrs"; +const char pstrUsageALDictionary [] PROGMEM = "AL Dict"; +const char pstrUsageALDesktop [] PROGMEM = "AL Desktop"; +const char pstrUsageALSpellCheck [] PROGMEM = "AL Spell Chk"; +const char pstrUsageALGrammarCheck [] PROGMEM = "AL Gram Chk"; +const char pstrUsageALWirelessStatus [] PROGMEM = "AL Wireless Sts"; +const char pstrUsageALKeyboardLayout [] PROGMEM = "AL Kbd Layout"; +const char pstrUsageALVirusProtection [] PROGMEM = "AL Vir Protect"; +const char pstrUsageALEncryption [] PROGMEM = "AL Encrypt"; +const char pstrUsageALScreenSaver [] PROGMEM = "AL Scr Sav"; +const char pstrUsageALAlarms [] PROGMEM = "AL Alarms"; +const char pstrUsageALClock [] PROGMEM = "AL Clock"; +const char pstrUsageALFileBrowser [] PROGMEM = "AL File Brow"; +const char pstrUsageALPowerStatus [] PROGMEM = "AL Pwr Sts"; +const char pstrUsageALImageBrowser [] PROGMEM = "AL Img Brow"; +const char pstrUsageALAudioBrowser [] PROGMEM = "AL Aud Brow"; +const char pstrUsageALMovieBrowser [] PROGMEM = "AL Mov Brow"; +const char pstrUsageALDigitalRightsManager [] PROGMEM = "AL Dig Rights Mgr"; +const char pstrUsageALDigitalWallet [] PROGMEM = "AL Dig Wallet"; +const char pstrUsageALInstantMessaging [] PROGMEM = "AL Inst Msg"; +const char pstrUsageALOEMFeaturesBrowser [] PROGMEM = "AL OEM Tips Brow"; +const char pstrUsageALOEMHelp [] PROGMEM = "AL OEM Hlp"; +const char pstrUsageALOnlineCommunity [] PROGMEM = "AL Online Com"; +const char pstrUsageALEntertainmentContentBrow [] PROGMEM = "AL Ent Cont Brow"; +const char pstrUsageALOnlineShoppingBrowser [] PROGMEM = "AL Online Shop Brow"; +const char pstrUsageALSmartCardInfoHelp [] PROGMEM = "AL SmartCard Inf"; +const char pstrUsageALMarketMonitorFinBrowser [] PROGMEM = "AL Market Brow"; +const char pstrUsageALCustomCorpNewsBrowser [] PROGMEM = "AL Cust Corp News Brow"; +const char pstrUsageALOnlineActivityBrowser [] PROGMEM = "AL Online Act Brow"; +const char pstrUsageALResearchSearchBrowser [] PROGMEM = "AL Search Brow"; +const char pstrUsageALAudioPlayer [] PROGMEM = "AL Aud Player"; +const char pstrUsageGenericGUIAppControls [] PROGMEM = "Gen GUI App Ctrl"; +const char pstrUsageACNew [] PROGMEM = "AC New"; +const char pstrUsageACOpen [] PROGMEM = "AC Open"; +const char pstrUsageACClose [] PROGMEM = "AC Close"; +const char pstrUsageACExit [] PROGMEM = "AC Exit"; +const char pstrUsageACMaximize [] PROGMEM = "AC Max"; +const char pstrUsageACMinimize [] PROGMEM = "AC Min"; +const char pstrUsageACSave [] PROGMEM = "AC Save"; +const char pstrUsageACPrint [] PROGMEM = "AC Print"; +const char pstrUsageACProperties [] PROGMEM = "AC Prop"; +const char pstrUsageACUndo [] PROGMEM = "AC Undo"; +const char pstrUsageACCopy [] PROGMEM = "AC Copy"; +const char pstrUsageACCut [] PROGMEM = "AC Cut"; +const char pstrUsageACPaste [] PROGMEM = "AC Paste"; +const char pstrUsageACSelectAll [] PROGMEM = "AC Sel All"; +const char pstrUsageACFind [] PROGMEM = "AC Find"; +const char pstrUsageACFindAndReplace [] PROGMEM = "AC Find/Replace"; +const char pstrUsageACSearch [] PROGMEM = "AC Search"; +const char pstrUsageACGoto [] PROGMEM = "AC Goto"; +const char pstrUsageACHome [] PROGMEM = "AC Home"; +const char pstrUsageACBack [] PROGMEM = "AC Back"; +const char pstrUsageACForward [] PROGMEM = "AC Fwd"; +const char pstrUsageACStop [] PROGMEM = "AC Stop"; +const char pstrUsageACRefresh [] PROGMEM = "AC Refresh"; +const char pstrUsageACPreviousLink [] PROGMEM = "AC Prev Link"; +const char pstrUsageACNextLink [] PROGMEM = "AC Next Link"; +const char pstrUsageACBookmarks [] PROGMEM = "AC Bkmarks"; +const char pstrUsageACHistory [] PROGMEM = "AC Hist"; +const char pstrUsageACSubscriptions [] PROGMEM = "AC Subscr"; +const char pstrUsageACZoomIn [] PROGMEM = "AC Zoom In"; +const char pstrUsageACZoomOut [] PROGMEM = "AC Zoom Out"; +const char pstrUsageACZoom [] PROGMEM = "AC Zoom"; +const char pstrUsageACFullScreenView [] PROGMEM = "AC Full Scr"; +const char pstrUsageACNormalView [] PROGMEM = "AC Norm View"; +const char pstrUsageACViewToggle [] PROGMEM = "AC View Tgl"; +const char pstrUsageACScrollUp [] PROGMEM = "AC Scroll Up"; +const char pstrUsageACScrollDown [] PROGMEM = "AC Scroll Down"; +const char pstrUsageACScroll [] PROGMEM = "AC Scroll"; +const char pstrUsageACPanLeft [] PROGMEM = "AC Pan Left"; +const char pstrUsageACPanRight [] PROGMEM = "AC Pan Right"; +const char pstrUsageACPan [] PROGMEM = "AC Pan"; +const char pstrUsageACNewWindow [] PROGMEM = "AC New Wnd"; +const char pstrUsageACTileHoriz [] PROGMEM = "AC Tile Horiz"; +const char pstrUsageACTileVert [] PROGMEM = "AC Tile Vert"; +const char pstrUsageACFormat [] PROGMEM = "AC Frmt"; +const char pstrUsageACEdit [] PROGMEM = "AC Edit"; +const char pstrUsageACBold [] PROGMEM = "AC Bold"; +const char pstrUsageACItalics [] PROGMEM = "AC Ital"; +const char pstrUsageACUnderline [] PROGMEM = "AC Under"; +const char pstrUsageACStrikethrough [] PROGMEM = "AC Strike"; +const char pstrUsageACSubscript [] PROGMEM = "AC Sub"; +const char pstrUsageACSuperscript [] PROGMEM = "AC Super"; +const char pstrUsageACAllCaps [] PROGMEM = "AC All Caps"; +const char pstrUsageACRotate [] PROGMEM = "AC Rotate"; +const char pstrUsageACResize [] PROGMEM = "AC Resize"; +const char pstrUsageACFlipHorizontal [] PROGMEM = "AC Flp H"; +const char pstrUsageACFlipVertical [] PROGMEM = "AC Flp V"; +const char pstrUsageACMirrorHorizontal [] PROGMEM = "AC Mir H"; +const char pstrUsageACMirrorVertical [] PROGMEM = "AC Mir V"; +const char pstrUsageACFontSelect [] PROGMEM = "AC Fnt Sel"; +const char pstrUsageACFontColor [] PROGMEM = "AC Fnt Clr"; +const char pstrUsageACFontSize [] PROGMEM = "AC Fnt Size"; +const char pstrUsageACJustifyLeft [] PROGMEM = "AC Just Left"; +const char pstrUsageACJustifyCenterH [] PROGMEM = "AC Just Cent H"; +const char pstrUsageACJustifyRight [] PROGMEM = "AC Just Right"; +const char pstrUsageACJustifyBlockH [] PROGMEM = "AC Just Block H"; +const char pstrUsageACJustifyTop [] PROGMEM = "AC Just Top"; +const char pstrUsageACJustifyCenterV [] PROGMEM = "AC Just Cent V"; +const char pstrUsageACJustifyBottom [] PROGMEM = "AC Just Bot"; +const char pstrUsageACJustifyBlockV [] PROGMEM = "AC Just Block V"; +const char pstrUsageACIndentDecrease [] PROGMEM = "AC Indent Dec"; +const char pstrUsageACIndentIncrease [] PROGMEM = "AC Indent Inc"; +const char pstrUsageACNumberedList [] PROGMEM = "AC Num List"; +const char pstrUsageACRestartNumbering [] PROGMEM = "AC Res Num"; +const char pstrUsageACBulletedList [] PROGMEM = "AC Blt List"; +const char pstrUsageACPromote [] PROGMEM = "AC Promote"; +const char pstrUsageACDemote [] PROGMEM = "AC Demote"; +const char pstrUsageACYes [] PROGMEM = "AC Yes"; +const char pstrUsageACNo [] PROGMEM = "AC No"; +const char pstrUsageACCancel [] PROGMEM = "AC Cancel"; +const char pstrUsageACCatalog [] PROGMEM = "AC Ctlg"; +const char pstrUsageACBuyChkout [] PROGMEM = "AC Buy"; +const char pstrUsageACAddToCart [] PROGMEM = "AC Add2Cart"; +const char pstrUsageACExpand [] PROGMEM = "AC Xpnd"; +const char pstrUsageACExpandAll [] PROGMEM = "AC Xpand All"; +const char pstrUsageACCollapse [] PROGMEM = "AC Collapse"; +const char pstrUsageACCollapseAll [] PROGMEM = "AC Collapse All"; +const char pstrUsageACPrintPreview [] PROGMEM = "AC Prn Prevw"; +const char pstrUsageACPasteSpecial [] PROGMEM = "AC Paste Spec"; +const char pstrUsageACInsertMode [] PROGMEM = "AC Ins Mode"; +const char pstrUsageACDelete [] PROGMEM = "AC Del"; +const char pstrUsageACLock [] PROGMEM = "AC Lock"; +const char pstrUsageACUnlock [] PROGMEM = "AC Unlock"; +const char pstrUsageACProtect [] PROGMEM = "AC Prot"; +const char pstrUsageACUnprotect [] PROGMEM = "AC Unprot"; +const char pstrUsageACAttachComment [] PROGMEM = "AC Attach Cmnt"; +const char pstrUsageACDeleteComment [] PROGMEM = "AC Del Cmnt"; +const char pstrUsageACViewComment [] PROGMEM = "AC View Cmnt"; +const char pstrUsageACSelectWord [] PROGMEM = "AC Sel Word"; +const char pstrUsageACSelectSentence [] PROGMEM = "AC Sel Sntc"; +const char pstrUsageACSelectParagraph [] PROGMEM = "AC Sel Para"; +const char pstrUsageACSelectColumn [] PROGMEM = "AC Sel Col"; +const char pstrUsageACSelectRow [] PROGMEM = "AC Sel Row"; +const char pstrUsageACSelectTable [] PROGMEM = "AC Sel Tbl"; +const char pstrUsageACSelectObject [] PROGMEM = "AC Sel Obj"; +const char pstrUsageACRedoRepeat [] PROGMEM = "AC Redo"; +const char pstrUsageACSort [] PROGMEM = "AC Sort"; +const char pstrUsageACSortAscending [] PROGMEM = "AC Sort Asc"; +const char pstrUsageACSortDescending [] PROGMEM = "AC Sort Desc"; +const char pstrUsageACFilter [] PROGMEM = "AC Filt"; +const char pstrUsageACSetClock [] PROGMEM = "AC Set Clk"; +const char pstrUsageACViewClock [] PROGMEM = "AC View Clk"; +const char pstrUsageACSelectTimeZone [] PROGMEM = "AC Sel Time Z"; +const char pstrUsageACEditTimeZone [] PROGMEM = "AC Edt Time Z"; +const char pstrUsageACSetAlarm [] PROGMEM = "AC Set Alm"; +const char pstrUsageACClearAlarm [] PROGMEM = "AC Clr Alm"; +const char pstrUsageACSnoozeAlarm [] PROGMEM = "AC Snz Alm"; +const char pstrUsageACResetAlarm [] PROGMEM = "AC Rst Alm"; +const char pstrUsageACSyncronize [] PROGMEM = "AC Sync"; +const char pstrUsageACSendReceive [] PROGMEM = "AC Snd/Rcv"; +const char pstrUsageACSendTo [] PROGMEM = "AC Snd To"; +const char pstrUsageACReply [] PROGMEM = "AC Reply"; +const char pstrUsageACReplyAll [] PROGMEM = "AC Reply All"; +const char pstrUsageACForwardMessage [] PROGMEM = "AC Fwd Msg"; +const char pstrUsageACSend [] PROGMEM = "AC Snd"; +const char pstrUsageACAttachFile [] PROGMEM = "AC Att File"; +const char pstrUsageACUpload [] PROGMEM = "AC Upld"; +const char pstrUsageACDownload [] PROGMEM = "AC Dnld"; +const char pstrUsageACSetBorders [] PROGMEM = "AC Set Brd"; +const char pstrUsageACInsertRow [] PROGMEM = "AC Ins Row"; +const char pstrUsageACInsertColumn [] PROGMEM = "AC Ins Col"; +const char pstrUsageACInsertFile [] PROGMEM = "AC Ins File"; +const char pstrUsageACInsertPicture [] PROGMEM = "AC Ins Pic"; +const char pstrUsageACInsertObject [] PROGMEM = "AC Ins Obj"; +const char pstrUsageACInsertSymbol [] PROGMEM = "AC Ins Sym"; +const char pstrUsageACSaveAndClose [] PROGMEM = "AC Sav&Cls"; +const char pstrUsageACRename [] PROGMEM = "AC Rename"; +const char pstrUsageACMerge [] PROGMEM = "AC Merge"; +const char pstrUsageACSplit [] PROGMEM = "AC Split"; +const char pstrUsageACDistributeHorizontaly [] PROGMEM = "AC Dist Hor"; +const char pstrUsageACDistributeVerticaly [] PROGMEM = "AC Dist Ver"; + +// Digitaizers +const char pstrUsageDigitizer [] PROGMEM = "Digitizer"; +const char pstrUsagePen [] PROGMEM = "Pen"; +const char pstrUsageLightPen [] PROGMEM = "Light Pen"; +const char pstrUsageTouchScreen [] PROGMEM = "Touch Scr"; +const char pstrUsageTouchPad [] PROGMEM = "Touch Pad"; +const char pstrUsageWhiteBoard [] PROGMEM = "White Brd"; +const char pstrUsageCoordinateMeasuringMachine [] PROGMEM = "Coord Meas Mach"; +const char pstrUsage3DDigitizer [] PROGMEM = "3D Dgtz"; +const char pstrUsageStereoPlotter [] PROGMEM = "Stereo Plot"; +const char pstrUsageArticulatedArm [] PROGMEM = "Art Arm"; +const char pstrUsageArmature [] PROGMEM = "Armature"; +const char pstrUsageMultiplePointDigitizer [] PROGMEM = "Multi Point Dgtz"; +const char pstrUsageFreeSpaceWand [] PROGMEM = "Free Space Wand"; +const char pstrUsageStylus [] PROGMEM = "Stylus"; +const char pstrUsagePuck [] PROGMEM = "Puck"; +const char pstrUsageFinger [] PROGMEM = "Finger"; +const char pstrUsageTipPressure [] PROGMEM = "Tip Press"; +const char pstrUsageBarrelPressure [] PROGMEM = "Brl Press"; +const char pstrUsageInRange [] PROGMEM = "In Range"; +const char pstrUsageTouch [] PROGMEM = "Touch"; +const char pstrUsageUntouch [] PROGMEM = "Untouch"; +const char pstrUsageTap [] PROGMEM = "Tap"; +const char pstrUsageQuality [] PROGMEM = "Qlty"; +const char pstrUsageDataValid [] PROGMEM = "Data Valid"; +const char pstrUsageTransducerIndex [] PROGMEM = "Transducer Ind"; +const char pstrUsageTabletFunctionKeys [] PROGMEM = "Tabl Func Keys"; +const char pstrUsageProgramChangeKeys [] PROGMEM = "Pgm Chng Keys"; +//const char pstrUsageBatteryStrength [] PROGMEM = "Bat Strength"; +const char pstrUsageInvert [] PROGMEM = "Invert"; +const char pstrUsageXTilt [] PROGMEM = "X Tilt"; +const char pstrUsageYTilt [] PROGMEM = "Y Tilt"; +const char pstrUsageAzimuth [] PROGMEM = "Azimuth"; +const char pstrUsageAltitude [] PROGMEM = "Altitude"; +const char pstrUsageTwist [] PROGMEM = "Twist"; +const char pstrUsageTipSwitch [] PROGMEM = "Tip Sw"; +const char pstrUsageSecondaryTipSwitch [] PROGMEM = "Scnd Tip Sw"; +const char pstrUsageBarrelSwitch [] PROGMEM = "Brl Sw"; +const char pstrUsageEraser [] PROGMEM = "Eraser"; +const char pstrUsageTabletPick [] PROGMEM = "Tbl Pick"; + +// Alphanumeric Display Page +const char pstrUsageAlphanumericDisplay [] PROGMEM = "Alphanum Disp"; +const char pstrUsageBitmappedDisplay [] PROGMEM = "Bmp Disp"; +const char pstrUsageDisplayAttributesReport [] PROGMEM = "Disp Attr Rpt"; +const char pstrUsageASCIICharacterSet [] PROGMEM = "ASCII chset"; +const char pstrUsageDataReadBack [] PROGMEM = "Data Rd Back"; +const char pstrUsageFontReadBack [] PROGMEM = "Fnt Rd Back"; +const char pstrUsageDisplayControlReport [] PROGMEM = "Disp Ctrl Rpt"; +const char pstrUsageClearDisplay [] PROGMEM = "Clr Disp"; +//const char pstrUsageDisplayEnable [] PROGMEM = "Disp Enbl"; +const char pstrUsageScreenSaverDelay [] PROGMEM = "Scr Sav Delay"; +const char pstrUsageScreenSaverEnable [] PROGMEM = "Scr Sav Enbl"; +const char pstrUsageVerticalScroll [] PROGMEM = "V Scroll"; +const char pstrUsageHorizontalScroll [] PROGMEM = "H Scroll"; +const char pstrUsageCharacterReport [] PROGMEM = "Char Rpt"; +const char pstrUsageDisplayData [] PROGMEM = "Disp Data"; +const char pstrUsageDisplayStatus [] PROGMEM = "Disp Stat"; +const char pstrUsageStatusNotReady [] PROGMEM = "Stat !Ready"; +const char pstrUsageStatusReady [] PROGMEM = "Stat Ready"; +const char pstrUsageErrorNotALoadableCharacter [] PROGMEM = "Err Not Ld Char"; +const char pstrUsageErrorFotDataCanNotBeRead [] PROGMEM = "Fnt Data Rd Err"; +const char pstrUsageCursorPositionReport [] PROGMEM = "Cur Pos Rpt"; +const char pstrUsageRow [] PROGMEM = "Row"; +const char pstrUsageColumn [] PROGMEM = "Col"; +const char pstrUsageRows [] PROGMEM = "Rows"; +const char pstrUsageColumns [] PROGMEM = "Cols"; +const char pstrUsageCursorPixelPosition [] PROGMEM = "Cur Pix Pos"; +const char pstrUsageCursorMode [] PROGMEM = "Cur Mode"; +const char pstrUsageCursorEnable [] PROGMEM = "Cur Enbl"; +const char pstrUsageCursorBlink [] PROGMEM = "Cur Blnk"; +const char pstrUsageFontReport [] PROGMEM = "Fnt Rpt"; +const char pstrUsageFontData [] PROGMEM = "Fnt Data"; +const char pstrUsageCharacterWidth [] PROGMEM = "Char Wdth"; +const char pstrUsageCharacterHeight [] PROGMEM = "Char Hght"; +const char pstrUsageCharacterSpacingHorizontal [] PROGMEM = "Char Space H"; +const char pstrUsageCharacterSpacingVertical [] PROGMEM = "Char Space V"; +const char pstrUsageUnicodeCharset [] PROGMEM = "Unicode Char"; +const char pstrUsageFont7Segment [] PROGMEM = "Fnt 7-seg"; +const char pstrUsage7SegmentDirectMap [] PROGMEM = "7-seg map"; +const char pstrUsageFont14Segment [] PROGMEM = "Fnt 14-seg"; +const char pstrUsage14SegmentDirectMap [] PROGMEM = "14-seg map"; +const char pstrUsageDisplayBrightness [] PROGMEM = "Disp Bright"; +const char pstrUsageDisplayContrast [] PROGMEM = "Disp Cntrst"; +const char pstrUsageCharacterAttribute [] PROGMEM = "Char Attr"; +const char pstrUsageAttributeReadback [] PROGMEM = "Attr Readbk"; +const char pstrUsageAttributeData [] PROGMEM = "Attr Data"; +const char pstrUsageCharAttributeEnhance [] PROGMEM = "Char Attr Enh"; +const char pstrUsageCharAttributeUnderline [] PROGMEM = "Char Attr Undl"; +const char pstrUsageCharAttributeBlink [] PROGMEM = "Char Attr Blnk"; +const char pstrUsageBitmapSizeX [] PROGMEM = "Bmp Size X"; +const char pstrUsageBitmapSizeY [] PROGMEM = "Bmp Size Y"; +const char pstrUsageBitDepthFormat [] PROGMEM = "Bit Dpth Fmt"; +const char pstrUsageDisplayOrientation [] PROGMEM = "Disp Ornt"; +const char pstrUsagePaletteReport [] PROGMEM = "Pal Rpt"; +const char pstrUsagePaletteDataSize [] PROGMEM = "Pal Data Size"; +const char pstrUsagePaletteDataOffset [] PROGMEM = "Pal Data Off"; +const char pstrUsagePaletteData [] PROGMEM = "Pal Data"; +const char pstrUsageBlitReport [] PROGMEM = "Blit Rpt"; +const char pstrUsageBlitRectangleX1 [] PROGMEM = "Blit Rect X1"; +const char pstrUsageBlitRectangleY1 [] PROGMEM = "Blit Rect Y1"; +const char pstrUsageBlitRectangleX2 [] PROGMEM = "Blit Rect X2"; +const char pstrUsageBlitRectangleY2 [] PROGMEM = "Blit Rect Y2"; +const char pstrUsageBlitData [] PROGMEM = "Blit Data"; +const char pstrUsageSoftButton [] PROGMEM = "Soft Btn"; +const char pstrUsageSoftButtonID [] PROGMEM = "Soft Btn ID"; +const char pstrUsageSoftButtonSide [] PROGMEM = "Soft Btn Side"; +const char pstrUsageSoftButtonOffset1 [] PROGMEM = "Soft Btn Off1"; +const char pstrUsageSoftButtonOffset2 [] PROGMEM = "Soft Btn Off2"; +const char pstrUsageSoftButtonReport [] PROGMEM = "Soft Btn Rpt"; + +// Medical Instrument Page +const char pstrUsageMedicalUltrasound [] PROGMEM = "Med Ultrasnd"; +const char pstrUsageVCRAcquisition [] PROGMEM = "VCR/Acq"; +const char pstrUsageFreezeThaw [] PROGMEM = "Freeze"; +const char pstrUsageClipStore [] PROGMEM = "Clip Store"; +const char pstrUsageUpdate [] PROGMEM = "Update"; +const char pstrUsageNext [] PROGMEM = "Next"; +const char pstrUsageSave [] PROGMEM = "Save"; +const char pstrUsagePrint [] PROGMEM = "Print"; +const char pstrUsageMicrophoneEnable [] PROGMEM = "Mic Enbl"; +const char pstrUsageCine [] PROGMEM = "Cine"; +const char pstrUsageTransmitPower [] PROGMEM = "Trans Pwr"; +//const char pstrUsageVolume [] PROGMEM = "Vol"; +const char pstrUsageFocus [] PROGMEM = "Focus"; +const char pstrUsageDepth [] PROGMEM = "Depth"; +const char pstrUsageSoftStepPrimary [] PROGMEM = "Soft Stp-Pri"; +const char pstrUsageSoftStepSecondary [] PROGMEM = "Soft Stp-Sec"; +const char pstrUsageDepthGainCompensation [] PROGMEM = "Dpth Gain Comp"; +const char pstrUsageZoomSelect [] PROGMEM = "Zoom Sel"; +const char pstrUsageZoomAdjust [] PROGMEM = "Zoom Adj"; +const char pstrUsageSpectralDopplerModeSelect [] PROGMEM = "Spec Dop Mode Sel"; +const char pstrUsageSpectralDopplerModeAdjust [] PROGMEM = "Spec Dop Mode Adj"; +const char pstrUsageColorDopplerModeSelect [] PROGMEM = "Color Dop Mode Sel"; +const char pstrUsageColorDopplerModeAdjust [] PROGMEM = "Color Dop Mode Adj"; +const char pstrUsageMotionModeSelect [] PROGMEM = "Motion Mode Sel"; +const char pstrUsageMotionModeAdjust [] PROGMEM = "Motion Mode Adj"; +const char pstrUsage2DModeSelect [] PROGMEM = "2D Mode Sel"; +const char pstrUsage2DModeAdjust [] PROGMEM = "2D Mode Adj"; +const char pstrUsageSoftControlSelect [] PROGMEM = "Soft Ctrl Sel"; +const char pstrUsageSoftControlAdjust [] PROGMEM = "Soft Ctrl Adj"; + +//extern const char *usagePageTitles0[15]; +//const char *usagePageTitles1[]; +//const char *genDesktopTitles0[]; +//const char *genDesktopTitles1[]; +//const char *genDesktopTitles2[]; +//const char *genDesktopTitles3[]; +//const char *genDesktopTitles4[]; +//const char *simuTitles0[]; +//const char *simuTitles1[]; +//const char *simuTitles2[]; +//const char *vrTitles0[]; +//const char *vrTitles1[]; +//const char *sportsCtrlTitles0[]; +//const char *sportsCtrlTitles1[]; +//const char *sportsCtrlTitles2[]; +//const char *gameTitles0[]; +//const char *gameTitles1[]; +//const char *genDevCtrlTitles[]; +//const char *ledTitles[]; +//const char *telTitles0[]; +//const char *telTitles1[]; +//const char *telTitles2[]; +//const char *telTitles3[]; +//const char *telTitles4[]; +//const char *telTitles5[]; +//const char *consTitles0[]; +//const char *consTitles1[]; +//const char *consTitles2[]; +//const char *consTitles3[]; +//const char *consTitles4[]; +//const char *consTitles5[]; +//const char *consTitles6[]; +//const char *consTitles7[]; +//const char *consTitles8[]; +//const char *consTitles9[]; +//const char *consTitlesA[]; +//const char *consTitlesB[]; +//const char *consTitlesC[]; +//const char *consTitlesD[]; +//const char *consTitlesE[]; +//const char *digitTitles0[]; +//const char *digitTitles1[]; +//const char *digitTitles2[]; +//const char *aplphanumTitles0[]; +//const char *aplphanumTitles1[]; +//const char *aplphanumTitles2[]; +//const char *medInstrTitles0[]; +//const char *medInstrTitles1[]; +//const char *medInstrTitles2[]; +//const char *medInstrTitles3[]; +//const char *medInstrTitles4[]; + #endif //__HIDUSAGESTR_H__ \ No newline at end of file diff --git a/hidusagetitlearrays.cpp b/hidusagetitlearrays.cpp index e8cda978..09d59302 100644 --- a/hidusagetitlearrays.cpp +++ b/hidusagetitlearrays.cpp @@ -1,1047 +1,1047 @@ -/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. - -This software may be distributed and modified under the terms of the GNU -General Public License version 2 (GPL2) as published by the Free Software -Foundation and appearing in the file GPL2.TXT included in the packaging of -this file. Please note that GPL2 Section 2[b] requires that all works based -on this software must also be made publicly available under the terms of -the GPL2 ("Copyleft"). - -Contact information -------------------- - -Circuits At Home, LTD -Web : http://www.circuitsathome.com -e-mail : support@circuitsathome.com -*/ -#if !defined(__HIDUSAGETITLEARRAYS_H__) -#define __HIDUSAGETITLEARRAYS_H__ - -#include -#include "hidusagestr.h" - -//const char *usagePageTitles0[] PROGMEM = -//{ -// pstrUsagePageGenericDesktopControls , -// pstrUsagePageSimulationControls , -// pstrUsagePageVRControls , -// pstrUsagePageSportControls , -// pstrUsagePageGameControls , -// pstrUsagePageGenericDeviceControls , -// pstrUsagePageKeyboardKeypad , -// pstrUsagePageLEDs , -// pstrUsagePageButton , -// pstrUsagePageOrdinal , -// pstrUsagePageTelephone , -// pstrUsagePageConsumer , -// pstrUsagePageDigitizer , -// pstrUsagePagePID , -// pstrUsagePageUnicode -//}; -// -//const char *usagePageTitles1[] PROGMEM = -//{ -// pstrUsagePageBarCodeScanner , -// pstrUsagePageScale , -// pstrUsagePageMSRDevices , -// pstrUsagePagePointOfSale , -// pstrUsagePageCameraControl , -// pstrUsagePageArcade -//}; -//const char *genDesktopTitles0[] PROGMEM = -//{ -// pstrUsagePointer , -// pstrUsageMouse , -// pstrUsageJoystick , -// pstrUsageGamePad , -// pstrUsageKeyboard , -// pstrUsageKeypad , -// pstrUsageMultiAxisController , -// pstrUsageTabletPCSystemControls -// -//}; -//const char *genDesktopTitles1[] PROGMEM = -//{ -// pstrUsageX , -// pstrUsageY , -// pstrUsageZ , -// pstrUsageRx , -// pstrUsageRy , -// pstrUsageRz , -// pstrUsageSlider , -// pstrUsageDial , -// pstrUsageWheel , -// pstrUsageHatSwitch , -// pstrUsageCountedBuffer , -// pstrUsageByteCount , -// pstrUsageMotionWakeup , -// pstrUsageStart , -// pstrUsageSelect , -// pstrUsagePageReserved , -// pstrUsageVx , -// pstrUsageVy , -// pstrUsageVz , -// pstrUsageVbrx , -// pstrUsageVbry , -// pstrUsageVbrz , -// pstrUsageVno , -// pstrUsageFeatureNotification , -// pstrUsageResolutionMultiplier -//}; -//const char *genDesktopTitles2[] PROGMEM = -//{ -// pstrUsageSystemControl , -// pstrUsageSystemPowerDown , -// pstrUsageSystemSleep , -// pstrUsageSystemWakeup , -// pstrUsageSystemContextMenu , -// pstrUsageSystemMainMenu , -// pstrUsageSystemAppMenu , -// pstrUsageSystemMenuHelp , -// pstrUsageSystemMenuExit , -// pstrUsageSystemMenuSelect , -// pstrUsageSystemMenuRight , -// pstrUsageSystemMenuLeft , -// pstrUsageSystemMenuUp , -// pstrUsageSystemMenuDown , -// pstrUsageSystemColdRestart , -// pstrUsageSystemWarmRestart , -// pstrUsageDPadUp , -// pstrUsageDPadDown , -// pstrUsageDPadRight , -// pstrUsageDPadLeft -//}; -//const char *genDesktopTitles3[] PROGMEM = -//{ -// pstrUsageSystemDock , -// pstrUsageSystemUndock , -// pstrUsageSystemSetup , -// pstrUsageSystemBreak , -// pstrUsageSystemDebuggerBreak , -// pstrUsageApplicationBreak , -// pstrUsageApplicationDebuggerBreak, -// pstrUsageSystemSpeakerMute , -// pstrUsageSystemHibernate -//}; -//const char *genDesktopTitles4[] PROGMEM = -//{ -// pstrUsageSystemDisplayInvert , -// pstrUsageSystemDisplayInternal , -// pstrUsageSystemDisplayExternal , -// pstrUsageSystemDisplayBoth , -// pstrUsageSystemDisplayDual , -// pstrUsageSystemDisplayToggleIntExt , -// pstrUsageSystemDisplaySwapPriSec , -// pstrUsageSystemDisplayLCDAutoscale -//}; -//const char *simuTitles0[] PROGMEM = -//{ -// pstrUsageFlightSimulationDevice , -// pstrUsageAutomobileSimulationDevice , -// pstrUsageTankSimulationDevice , -// pstrUsageSpaceshipSimulationDevice , -// pstrUsageSubmarineSimulationDevice , -// pstrUsageSailingSimulationDevice , -// pstrUsageMotocicleSimulationDevice , -// pstrUsageSportsSimulationDevice , -// pstrUsageAirplaneSimulationDevice , -// pstrUsageHelicopterSimulationDevice , -// pstrUsageMagicCarpetSimulationDevice, -// pstrUsageBicycleSimulationDevice -//}; -//const char *simuTitles1[] PROGMEM = -//{ -// pstrUsageFlightControlStick , -// pstrUsageFlightStick , -// pstrUsageCyclicControl , -// pstrUsageCyclicTrim , -// pstrUsageFlightYoke , -// pstrUsageTrackControl -//}; -//const char *simuTitles2[] PROGMEM = -//{ -// pstrUsageAileron , -// pstrUsageAileronTrim , -// pstrUsageAntiTorqueControl , -// pstrUsageAutopilotEnable , -// pstrUsageChaffRelease , -// pstrUsageCollectiveControl , -// pstrUsageDiveBrake , -// pstrUsageElectronicCountermeasures , -// pstrUsageElevator , -// pstrUsageElevatorTrim , -// pstrUsageRudder , -// pstrUsageThrottle , -// pstrUsageFlightCommunications , -// pstrUsageFlareRelease , -// pstrUsageLandingGear , -// pstrUsageToeBrake , -// pstrUsageTrigger , -// pstrUsageWeaponsArm , -// pstrUsageWeaponsSelect , -// pstrUsageWingFlaps , -// pstrUsageAccelerator , -// pstrUsageBrake , -// pstrUsageClutch , -// pstrUsageShifter , -// pstrUsageSteering , -// pstrUsageTurretDirection , -// pstrUsageBarrelElevation , -// pstrUsageDivePlane , -// pstrUsageBallast , -// pstrUsageBicycleCrank , -// pstrUsageHandleBars , -// pstrUsageFrontBrake , -// pstrUsageRearBrake -//}; -//const char *vrTitles0[] PROGMEM = -//{ -// pstrUsageBelt , -// pstrUsageBodySuit , -// pstrUsageFlexor , -// pstrUsageGlove , -// pstrUsageHeadTracker , -// pstrUsageHeadMountedDisplay , -// pstrUsageHandTracker , -// pstrUsageOculometer , -// pstrUsageVest , -// pstrUsageAnimatronicDevice -//}; -//const char *vrTitles1[] PROGMEM = -//{ -// pstrUsageStereoEnable , -// pstrUsageDisplayEnable -//}; -//const char *sportsCtrlTitles0[] PROGMEM = -//{ -// pstrUsageBaseballBat , -// pstrUsageGolfClub , -// pstrUsageRowingMachine , -// pstrUsageTreadmill -//}; -//const char *sportsCtrlTitles1[] PROGMEM = -//{ -// pstrUsageOar , -// pstrUsageSlope , -// pstrUsageRate , -// pstrUsageStickSpeed , -// pstrUsageStickFaceAngle , -// pstrUsageStickHeelToe , -// pstrUsageStickFollowThough , -// pstrUsageStickTempo , -// pstrUsageStickType , -// pstrUsageStickHeight -//}; -//const char *sportsCtrlTitles2[] PROGMEM = -//{ -// pstrUsagePutter , -// pstrUsage1Iron , -// pstrUsage2Iron , -// pstrUsage3Iron , -// pstrUsage4Iron , -// pstrUsage5Iron , -// pstrUsage6Iron , -// pstrUsage7Iron , -// pstrUsage8Iron , -// pstrUsage9Iron , -// pstrUsage10Iron , -// pstrUsage11Iron , -// pstrUsageSandWedge , -// pstrUsageLoftWedge , -// pstrUsagePowerWedge , -// pstrUsage1Wood , -// pstrUsage3Wood , -// pstrUsage5Wood , -// pstrUsage7Wood , -// pstrUsage9Wood -//}; -//const char *gameTitles0[] PROGMEM = -//{ -// pstrUsage3DGameController , -// pstrUsagePinballDevice , -// pstrUsageGunDevice -//}; -//const char *gameTitles1[] PROGMEM = -//{ -// pstrUsagePointOfView , -// pstrUsageTurnRightLeft , -// pstrUsagePitchForwardBackward , -// pstrUsageRollRightLeft , -// pstrUsageMoveRightLeft , -// pstrUsageMoveForwardBackward , -// pstrUsageMoveUpDown , -// pstrUsageLeanRightLeft , -// pstrUsageLeanForwardBackward , -// pstrUsageHeightOfPOV , -// pstrUsageFlipper , -// pstrUsageSecondaryFlipper , -// pstrUsageBump , -// pstrUsageNewGame , -// pstrUsageShootBall , -// pstrUsagePlayer , -// pstrUsageGunBolt , -// pstrUsageGunClip , -// pstrUsageGunSelector , -// pstrUsageGunSingleShot , -// pstrUsageGunBurst , -// pstrUsageGunAutomatic , -// pstrUsageGunSafety , -// pstrUsageGamepadFireJump , -// pstrUsageGamepadTrigger -//}; -//const char *genDevCtrlTitles[] PROGMEM = -//{ -// pstrUsageBatteryStrength, -// pstrUsageWirelessChannel, -// pstrUsageWirelessID, -// pstrUsageDiscoverWirelessControl, -// pstrUsageSecurityCodeCharEntered, -// pstrUsageSecurityCodeCharErased, -// pstrUsageSecurityCodeCleared -//}; -//const char *ledTitles[] PROGMEM = -//{ -// pstrUsageNumLock , -// pstrUsageCapsLock , -// pstrUsageScrollLock , -// pstrUsageCompose , -// pstrUsageKana , -// pstrUsagePower , -// pstrUsageShift , -// pstrUsageDoNotDisturb , -// pstrUsageMute , -// pstrUsageToneEnable , -// pstrUsageHighCutFilter , -// pstrUsageLowCutFilter , -// pstrUsageEqualizerEnable , -// pstrUsageSoundFieldOn , -// pstrUsageSurroundOn , -// pstrUsageRepeat , -// pstrUsageStereo , -// pstrUsageSamplingRateDetect , -// pstrUsageSpinning , -// pstrUsageCAV , -// pstrUsageCLV , -// pstrUsageRecordingFormatDetect , -// pstrUsageOffHook , -// pstrUsageRing , -// pstrUsageMessageWaiting , -// pstrUsageDataMode , -// pstrUsageBatteryOperation , -// pstrUsageBatteryOK , -// pstrUsageBatteryLow , -// pstrUsageSpeaker , -// pstrUsageHeadSet , -// pstrUsageHold , -// pstrUsageMicrophone , -// pstrUsageCoverage , -// pstrUsageNightMode , -// pstrUsageSendCalls , -// pstrUsageCallPickup , -// pstrUsageConference , -// pstrUsageStandBy , -// pstrUsageCameraOn , -// pstrUsageCameraOff , -// pstrUsageOnLine , -// pstrUsageOffLine , -// pstrUsageBusy , -// pstrUsageReady , -// pstrUsagePaperOut , -// pstrUsagePaperJam , -// pstrUsageRemote , -// pstrUsageForward , -// pstrUsageReverse , -// pstrUsageStop , -// pstrUsageRewind , -// pstrUsageFastForward , -// pstrUsagePlay , -// pstrUsagePause , -// pstrUsageRecord , -// pstrUsageError , -// pstrUsageSelectedIndicator , -// pstrUsageInUseIndicator , -// pstrUsageMultiModeIndicator , -// pstrUsageIndicatorOn , -// pstrUsageIndicatorFlash , -// pstrUsageIndicatorSlowBlink , -// pstrUsageIndicatorFastBlink , -// pstrUsageIndicatorOff , -// pstrUsageFlashOnTime , -// pstrUsageSlowBlinkOnTime , -// pstrUsageSlowBlinkOffTime , -// pstrUsageFastBlinkOnTime , -// pstrUsageFastBlinkOffTime , -// pstrUsageIndicatorColor , -// pstrUsageIndicatorRed , -// pstrUsageIndicatorGreen , -// pstrUsageIndicatorAmber , -// pstrUsageGenericIndicator , -// pstrUsageSystemSuspend , -// pstrUsageExternalPowerConnected -//}; -//const char *telTitles0 [] PROGMEM = -//{ -// pstrUsagePhone , -// pstrUsageAnsweringMachine , -// pstrUsageMessageControls , -// pstrUsageHandset , -// pstrUsageHeadset , -// pstrUsageTelephonyKeyPad , -// pstrUsageProgrammableButton -//}; -//const char *telTitles1 [] PROGMEM = -//{ -// pstrUsageHookSwitch , -// pstrUsageFlash , -// pstrUsageFeature , -// pstrUsageHold , -// pstrUsageRedial , -// pstrUsageTransfer , -// pstrUsageDrop , -// pstrUsagePark , -// pstrUsageForwardCalls , -// pstrUsageAlternateFunction , -// pstrUsageLine , -// pstrUsageSpeakerPhone , -// pstrUsageConference , -// pstrUsageRingEnable , -// pstrUsageRingSelect , -// pstrUsagePhoneMute , -// pstrUsageCallerID , -// pstrUsageSend -//}; -//const char *telTitles2 [] PROGMEM = -//{ -// pstrUsageSpeedDial , -// pstrUsageStoreNumber , -// pstrUsageRecallNumber , -// pstrUsagePhoneDirectory -//}; -//const char *telTitles3 [] PROGMEM = -//{ -// pstrUsageVoiceMail , -// pstrUsageScreenCalls , -// pstrUsageDoNotDisturb , -// pstrUsageMessage , -// pstrUsageAnswerOnOff -//}; -//const char *telTitles4 [] PROGMEM = -//{ -// pstrUsageInsideDialTone , -// pstrUsageOutsideDialTone , -// pstrUsageInsideRingTone , -// pstrUsageOutsideRingTone , -// pstrUsagePriorityRingTone , -// pstrUsageInsideRingback , -// pstrUsagePriorityRingback , -// pstrUsageLineBusyTone , -// pstrUsageReorderTone , -// pstrUsageCallWaitingTone , -// pstrUsageConfirmationTone1 , -// pstrUsageConfirmationTone2 , -// pstrUsageTonesOff , -// pstrUsageOutsideRingback , -// pstrUsageRinger -//}; -//const char *telTitles5 [] PROGMEM = -//{ -// pstrUsagePhoneKey0 , -// pstrUsagePhoneKey1 , -// pstrUsagePhoneKey2 , -// pstrUsagePhoneKey3 , -// pstrUsagePhoneKey4 , -// pstrUsagePhoneKey5 , -// pstrUsagePhoneKey6 , -// pstrUsagePhoneKey7 , -// pstrUsagePhoneKey8 , -// pstrUsagePhoneKey9 , -// pstrUsagePhoneKeyStar , -// pstrUsagePhoneKeyPound , -// pstrUsagePhoneKeyA , -// pstrUsagePhoneKeyB , -// pstrUsagePhoneKeyC , -// pstrUsagePhoneKeyD -//}; -//const char *consTitles0[] PROGMEM = -//{ -// pstrUsageConsumerControl, -// pstrUsageNumericKeyPad, -// pstrUsageProgrammableButton, -// pstrUsageMicrophone, -// pstrUsageHeadphone, -// pstrUsageGraphicEqualizer -//}; -//const char *consTitles1[] PROGMEM = -//{ -// pstrUsagePlus10 , -// pstrUsagePlus100, -// pstrUsageAMPM -//}; -//const char *consTitles2[] PROGMEM = -//{ -// pstrUsagePower , -// pstrUsageReset , -// pstrUsageSleep , -// pstrUsageSleepAfter , -// pstrUsageSleepMode , -// pstrUsageIllumination , -// pstrUsageFunctionButtons -// -//}; -//const char *consTitles3[] PROGMEM = -//{ -// pstrUsageMenu , -// pstrUsageMenuPick , -// pstrUsageMenuUp , -// pstrUsageMenuDown , -// pstrUsageMenuLeft , -// pstrUsageMenuRight , -// pstrUsageMenuEscape , -// pstrUsageMenuValueIncrease, -// pstrUsageMenuValueDecrease -//}; -//const char *consTitles4[] PROGMEM = -//{ -// pstrUsageDataOnScreen , -// pstrUsageClosedCaption , -// pstrUsageClosedCaptionSelect, -// pstrUsageVCRTV , -// pstrUsageBroadcastMode , -// pstrUsageSnapshot , -// pstrUsageStill -//}; -//const char *consTitles5[] PROGMEM = -//{ -// pstrUsageSelection , -// pstrUsageAssignSelection , -// pstrUsageModeStep , -// pstrUsageRecallLast , -// pstrUsageEnterChannel , -// pstrUsageOrderMovie , -// pstrUsageChannel , -// pstrUsageMediaSelection , -// pstrUsageMediaSelectComputer , -// pstrUsageMediaSelectTV , -// pstrUsageMediaSelectWWW , -// pstrUsageMediaSelectDVD , -// pstrUsageMediaSelectTelephone , -// pstrUsageMediaSelectProgramGuide , -// pstrUsageMediaSelectVideoPhone , -// pstrUsageMediaSelectGames , -// pstrUsageMediaSelectMessages , -// pstrUsageMediaSelectCD , -// pstrUsageMediaSelectVCR , -// pstrUsageMediaSelectTuner , -// pstrUsageQuit , -// pstrUsageHelp , -// pstrUsageMediaSelectTape , -// pstrUsageMediaSelectCable , -// pstrUsageMediaSelectSatellite , -// pstrUsageMediaSelectSecurity , -// pstrUsageMediaSelectHome , -// pstrUsageMediaSelectCall , -// pstrUsageChannelIncrement , -// pstrUsageChannelDecrement , -// pstrUsageMediaSelectSAP , -// pstrUsagePageReserved , -// pstrUsageVCRPlus , -// pstrUsageOnce , -// pstrUsageDaily , -// pstrUsageWeekly , -// pstrUsageMonthly -//}; -//const char *consTitles6[] PROGMEM = -//{ -// pstrUsagePlay , -// pstrUsagePause , -// pstrUsageRecord , -// pstrUsageFastForward , -// pstrUsageRewind , -// pstrUsageScanNextTrack , -// pstrUsageScanPreviousTrack , -// pstrUsageStop , -// pstrUsageEject , -// pstrUsageRandomPlay , -// pstrUsageSelectDisk , -// pstrUsageEnterDisk , -// pstrUsageRepeat , -// pstrUsageTracking , -// pstrUsageTrackNormal , -// pstrUsageSlowTracking , -// pstrUsageFrameForward , -// pstrUsageFrameBackwards , -// pstrUsageMark , -// pstrUsageClearMark , -// pstrUsageRepeatFromMark , -// pstrUsageReturnToMark , -// pstrUsageSearchMarkForward , -// pstrUsageSearchMarkBackwards , -// pstrUsageCounterReset , -// pstrUsageShowCounter , -// pstrUsageTrackingIncrement , -// pstrUsageTrackingDecrement , -// pstrUsageStopEject , -// pstrUsagePlayPause , -// pstrUsagePlaySkip -//}; -//const char *consTitles7[] PROGMEM = -//{ -// pstrUsageVolume , -// pstrUsageBalance , -// pstrUsageMute , -// pstrUsageBass , -// pstrUsageTreble , -// pstrUsageBassBoost , -// pstrUsageSurroundMode , -// pstrUsageLoudness , -// pstrUsageMPX , -// pstrUsageVolumeIncrement , -// pstrUsageVolumeDecrement -//}; -//const char *consTitles8[] PROGMEM = -//{ -// pstrUsageSpeedSelect , -// pstrUsagePlaybackSpeed , -// pstrUsageStandardPlay , -// pstrUsageLongPlay , -// pstrUsageExtendedPlay , -// pstrUsageSlow -//}; -//const char *consTitles9[] PROGMEM = -//{ -// pstrUsageFanEnable , -// pstrUsageFanSpeed , -// pstrUsageLightEnable , -// pstrUsageLightIlluminationLevel , -// pstrUsageClimateControlEnable , -// pstrUsageRoomTemperature , -// pstrUsageSecurityEnable , -// pstrUsageFireAlarm , -// pstrUsagePoliceAlarm , -// pstrUsageProximity , -// pstrUsageMotion , -// pstrUsageDuresAlarm , -// pstrUsageHoldupAlarm , -// pstrUsageMedicalAlarm -//}; -//const char *consTitlesA[] PROGMEM = -//{ -// pstrUsageBalanceRight , -// pstrUsageBalanceLeft , -// pstrUsageBassIncrement , -// pstrUsageBassDecrement , -// pstrUsageTrebleIncrement , -// pstrUsageTrebleDecrement -//}; -//const char *consTitlesB[] PROGMEM = -//{ -// pstrUsageSpeakerSystem , -// pstrUsageChannelLeft , -// pstrUsageChannelRight , -// pstrUsageChannelCenter , -// pstrUsageChannelFront , -// pstrUsageChannelCenterFront , -// pstrUsageChannelSide , -// pstrUsageChannelSurround , -// pstrUsageChannelLowFreqEnhancement , -// pstrUsageChannelTop , -// pstrUsageChannelUnknown -//}; -//const char *consTitlesC[] PROGMEM = -//{ -// pstrUsageSubChannel , -// pstrUsageSubChannelIncrement , -// pstrUsageSubChannelDecrement , -// pstrUsageAlternateAudioIncrement , -// pstrUsageAlternateAudioDecrement -//}; -//const char *consTitlesD[] PROGMEM = -//{ -// pstrUsageApplicationLaunchButtons , -// pstrUsageALLaunchButtonConfigTool , -// pstrUsageALProgrammableButton , -// pstrUsageALConsumerControlConfig , -// pstrUsageALWordProcessor , -// pstrUsageALTextEditor , -// pstrUsageALSpreadsheet , -// pstrUsageALGraphicsEditor , -// pstrUsageALPresentationApp , -// pstrUsageALDatabaseApp , -// pstrUsageALEmailReader , -// pstrUsageALNewsreader , -// pstrUsageALVoicemail , -// pstrUsageALContactsAddressBook , -// pstrUsageALCalendarSchedule , -// pstrUsageALTaskProjectManager , -// pstrUsageALLogJournalTimecard , -// pstrUsageALCheckbookFinance , -// pstrUsageALCalculator , -// pstrUsageALAVCapturePlayback , -// pstrUsageALLocalMachineBrowser , -// pstrUsageALLANWANBrow , -// pstrUsageALInternetBrowser , -// pstrUsageALRemoteNetISPConnect , -// pstrUsageALNetworkConference , -// pstrUsageALNetworkChat , -// pstrUsageALTelephonyDialer , -// pstrUsageALLogon , -// pstrUsageALLogoff , -// pstrUsageALLogonLogoff , -// pstrUsageALTermLockScrSav , -// pstrUsageALControlPannel , -// pstrUsageALCommandLineProcessorRun , -// pstrUsageALProcessTaskManager , -// pstrUsageALSelectTaskApplication , -// pstrUsageALNextTaskApplication , -// pstrUsageALPreviousTaskApplication , -// pstrUsageALPreemptiveHaltTaskApp , -// pstrUsageALIntegratedHelpCenter , -// pstrUsageALDocuments , -// pstrUsageALThesaurus , -// pstrUsageALDictionary , -// pstrUsageALDesktop , -// pstrUsageALSpellCheck , -// pstrUsageALGrammarCheck , -// pstrUsageALWirelessStatus , -// pstrUsageALKeyboardLayout , -// pstrUsageALVirusProtection , -// pstrUsageALEncryption , -// pstrUsageALScreenSaver , -// pstrUsageALAlarms , -// pstrUsageALClock , -// pstrUsageALFileBrowser , -// pstrUsageALPowerStatus , -// pstrUsageALImageBrowser , -// pstrUsageALAudioBrowser , -// pstrUsageALMovieBrowser , -// pstrUsageALDigitalRightsManager , -// pstrUsageALDigitalWallet , -// pstrUsagePageReserved , -// pstrUsageALInstantMessaging , -// pstrUsageALOEMFeaturesBrowser , -// pstrUsageALOEMHelp , -// pstrUsageALOnlineCommunity , -// pstrUsageALEntertainmentContentBrow , -// pstrUsageALOnlineShoppingBrowser , -// pstrUsageALSmartCardInfoHelp , -// pstrUsageALMarketMonitorFinBrowser , -// pstrUsageALCustomCorpNewsBrowser , -// pstrUsageALOnlineActivityBrowser , -// pstrUsageALResearchSearchBrowser , -// pstrUsageALAudioPlayer -//}; -//const char *consTitlesE[] PROGMEM = -//{ -// pstrUsageGenericGUIAppControls , -// pstrUsageACNew , -// pstrUsageACOpen , -// pstrUsageACClose , -// pstrUsageACExit , -// pstrUsageACMaximize , -// pstrUsageACMinimize , -// pstrUsageACSave , -// pstrUsageACPrint , -// pstrUsageACProperties , -// pstrUsageACUndo , -// pstrUsageACCopy , -// pstrUsageACCut , -// pstrUsageACPaste , -// pstrUsageACSelectAll , -// pstrUsageACFind , -// pstrUsageACFindAndReplace , -// pstrUsageACSearch , -// pstrUsageACGoto , -// pstrUsageACHome , -// pstrUsageACBack , -// pstrUsageACForward , -// pstrUsageACStop , -// pstrUsageACRefresh , -// pstrUsageACPreviousLink , -// pstrUsageACNextLink , -// pstrUsageACBookmarks , -// pstrUsageACHistory , -// pstrUsageACSubscriptions , -// pstrUsageACZoomIn , -// pstrUsageACZoomOut , -// pstrUsageACZoom , -// pstrUsageACFullScreenView , -// pstrUsageACNormalView , -// pstrUsageACViewToggle , -// pstrUsageACScrollUp , -// pstrUsageACScrollDown , -// pstrUsageACScroll , -// pstrUsageACPanLeft , -// pstrUsageACPanRight , -// pstrUsageACPan , -// pstrUsageACNewWindow , -// pstrUsageACTileHoriz , -// pstrUsageACTileVert , -// pstrUsageACFormat , -// pstrUsageACEdit , -// pstrUsageACBold , -// pstrUsageACItalics , -// pstrUsageACUnderline , -// pstrUsageACStrikethrough , -// pstrUsageACSubscript , -// pstrUsageACSuperscript , -// pstrUsageACAllCaps , -// pstrUsageACRotate , -// pstrUsageACResize , -// pstrUsageACFlipHorizontal , -// pstrUsageACFlipVertical , -// pstrUsageACMirrorHorizontal , -// pstrUsageACMirrorVertical , -// pstrUsageACFontSelect , -// pstrUsageACFontColor , -// pstrUsageACFontSize , -// pstrUsageACJustifyLeft , -// pstrUsageACJustifyCenterH , -// pstrUsageACJustifyRight , -// pstrUsageACJustifyBlockH , -// pstrUsageACJustifyTop , -// pstrUsageACJustifyCenterV , -// pstrUsageACJustifyBottom , -// pstrUsageACJustifyBlockV , -// pstrUsageACIndentDecrease , -// pstrUsageACIndentIncrease , -// pstrUsageACNumberedList , -// pstrUsageACRestartNumbering , -// pstrUsageACBulletedList , -// pstrUsageACPromote , -// pstrUsageACDemote , -// pstrUsageACYes , -// pstrUsageACNo , -// pstrUsageACCancel , -// pstrUsageACCatalog , -// pstrUsageACBuyChkout , -// pstrUsageACAddToCart , -// pstrUsageACExpand , -// pstrUsageACExpandAll , -// pstrUsageACCollapse , -// pstrUsageACCollapseAll , -// pstrUsageACPrintPreview , -// pstrUsageACPasteSpecial , -// pstrUsageACInsertMode , -// pstrUsageACDelete , -// pstrUsageACLock , -// pstrUsageACUnlock , -// pstrUsageACProtect , -// pstrUsageACUnprotect , -// pstrUsageACAttachComment , -// pstrUsageACDeleteComment , -// pstrUsageACViewComment , -// pstrUsageACSelectWord , -// pstrUsageACSelectSentence , -// pstrUsageACSelectParagraph , -// pstrUsageACSelectColumn , -// pstrUsageACSelectRow , -// pstrUsageACSelectTable , -// pstrUsageACSelectObject , -// pstrUsageACRedoRepeat , -// pstrUsageACSort , -// pstrUsageACSortAscending , -// pstrUsageACSortDescending , -// pstrUsageACFilter , -// pstrUsageACSetClock , -// pstrUsageACViewClock , -// pstrUsageACSelectTimeZone , -// pstrUsageACEditTimeZone , -// pstrUsageACSetAlarm , -// pstrUsageACClearAlarm , -// pstrUsageACSnoozeAlarm , -// pstrUsageACResetAlarm , -// pstrUsageACSyncronize , -// pstrUsageACSendReceive , -// pstrUsageACSendTo , -// pstrUsageACReply , -// pstrUsageACReplyAll , -// pstrUsageACForwardMessage , -// pstrUsageACSend , -// pstrUsageACAttachFile , -// pstrUsageACUpload , -// pstrUsageACDownload , -// pstrUsageACSetBorders , -// pstrUsageACInsertRow , -// pstrUsageACInsertColumn , -// pstrUsageACInsertFile , -// pstrUsageACInsertPicture , -// pstrUsageACInsertObject , -// pstrUsageACInsertSymbol , -// pstrUsageACSaveAndClose , -// pstrUsageACRename , -// pstrUsageACMerge , -// pstrUsageACSplit , -// pstrUsageACDistributeHorizontaly , -// pstrUsageACDistributeVerticaly -//}; -//const char *digitTitles0[] PROGMEM = -//{ -// pstrUsageDigitizer , -// pstrUsagePen , -// pstrUsageLightPen , -// pstrUsageTouchScreen , -// pstrUsageTouchPad , -// pstrUsageWhiteBoard , -// pstrUsageCoordinateMeasuringMachine , -// pstrUsage3DDigitizer , -// pstrUsageStereoPlotter , -// pstrUsageArticulatedArm , -// pstrUsageArmature , -// pstrUsageMultiplePointDigitizer , -// pstrUsageFreeSpaceWand -//}; -//const char *digitTitles1[] PROGMEM = -//{ -// pstrUsageStylus , -// pstrUsagePuck , -// pstrUsageFinger -// -//}; -//const char *digitTitles2[] PROGMEM = -//{ -// pstrUsageTipPressure , -// pstrUsageBarrelPressure , -// pstrUsageInRange , -// pstrUsageTouch , -// pstrUsageUntouch , -// pstrUsageTap , -// pstrUsageQuality , -// pstrUsageDataValid , -// pstrUsageTransducerIndex , -// pstrUsageTabletFunctionKeys , -// pstrUsageProgramChangeKeys , -// pstrUsageBatteryStrength , -// pstrUsageInvert , -// pstrUsageXTilt , -// pstrUsageYTilt , -// pstrUsageAzimuth , -// pstrUsageAltitude , -// pstrUsageTwist , -// pstrUsageTipSwitch , -// pstrUsageSecondaryTipSwitch , -// pstrUsageBarrelSwitch , -// pstrUsageEraser , -// pstrUsageTabletPick -//}; -//const char *aplphanumTitles0[] PROGMEM = -//{ -// pstrUsageAlphanumericDisplay, -// pstrUsageBitmappedDisplay -//}; -//const char *aplphanumTitles1[] PROGMEM = -//{ -// pstrUsageDisplayAttributesReport , -// pstrUsageASCIICharacterSet , -// pstrUsageDataReadBack , -// pstrUsageFontReadBack , -// pstrUsageDisplayControlReport , -// pstrUsageClearDisplay , -// pstrUsageDisplayEnable , -// pstrUsageScreenSaverDelay , -// pstrUsageScreenSaverEnable , -// pstrUsageVerticalScroll , -// pstrUsageHorizontalScroll , -// pstrUsageCharacterReport , -// pstrUsageDisplayData , -// pstrUsageDisplayStatus , -// pstrUsageStatusNotReady , -// pstrUsageStatusReady , -// pstrUsageErrorNotALoadableCharacter , -// pstrUsageErrorFotDataCanNotBeRead , -// pstrUsageCursorPositionReport , -// pstrUsageRow , -// pstrUsageColumn , -// pstrUsageRows , -// pstrUsageColumns , -// pstrUsageCursorPixelPosition , -// pstrUsageCursorMode , -// pstrUsageCursorEnable , -// pstrUsageCursorBlink , -// pstrUsageFontReport , -// pstrUsageFontData , -// pstrUsageCharacterWidth , -// pstrUsageCharacterHeight , -// pstrUsageCharacterSpacingHorizontal , -// pstrUsageCharacterSpacingVertical , -// pstrUsageUnicodeCharset , -// pstrUsageFont7Segment , -// pstrUsage7SegmentDirectMap , -// pstrUsageFont14Segment , -// pstrUsage14SegmentDirectMap , -// pstrUsageDisplayBrightness , -// pstrUsageDisplayContrast , -// pstrUsageCharacterAttribute , -// pstrUsageAttributeReadback , -// pstrUsageAttributeData , -// pstrUsageCharAttributeEnhance , -// pstrUsageCharAttributeUnderline , -// pstrUsageCharAttributeBlink -//}; -//const char *aplphanumTitles2[] PROGMEM = -//{ -// pstrUsageBitmapSizeX , -// pstrUsageBitmapSizeY , -// pstrUsagePageReserved , -// pstrUsageBitDepthFormat , -// pstrUsageDisplayOrientation , -// pstrUsagePaletteReport , -// pstrUsagePaletteDataSize , -// pstrUsagePaletteDataOffset , -// pstrUsagePaletteData , -// pstrUsageBlitReport , -// pstrUsageBlitRectangleX1 , -// pstrUsageBlitRectangleY1 , -// pstrUsageBlitRectangleX2 , -// pstrUsageBlitRectangleY2 , -// pstrUsageBlitData , -// pstrUsageSoftButton , -// pstrUsageSoftButtonID , -// pstrUsageSoftButtonSide , -// pstrUsageSoftButtonOffset1 , -// pstrUsageSoftButtonOffset2 , -// pstrUsageSoftButtonReport -//}; -//const char *medInstrTitles0[] PROGMEM = -//{ -// pstrUsageVCRAcquisition , -// pstrUsageFreezeThaw , -// pstrUsageClipStore , -// pstrUsageUpdate , -// pstrUsageNext , -// pstrUsageSave , -// pstrUsagePrint , -// pstrUsageMicrophoneEnable -//}; -//const char *medInstrTitles1[] PROGMEM = -//{ -// pstrUsageCine , -// pstrUsageTransmitPower , -// pstrUsageVolume , -// pstrUsageFocus , -// pstrUsageDepth -//}; -//const char *medInstrTitles2[] PROGMEM = -//{ -// pstrUsageSoftStepPrimary , -// pstrUsageSoftStepSecondary -//}; -//const char *medInstrTitles3[] PROGMEM = -//{ -// pstrUsageZoomSelect , -// pstrUsageZoomAdjust , -// pstrUsageSpectralDopplerModeSelect , -// pstrUsageSpectralDopplerModeAdjust , -// pstrUsageColorDopplerModeSelect , -// pstrUsageColorDopplerModeAdjust , -// pstrUsageMotionModeSelect , -// pstrUsageMotionModeAdjust , -// pstrUsage2DModeSelect , -// pstrUsage2DModeAdjust -//}; -//const char *medInstrTitles4[] PROGMEM = -//{ -// pstrUsageSoftControlSelect , -// pstrUsageSoftControlAdjust -//}; - +/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. + +This software may be distributed and modified under the terms of the GNU +General Public License version 2 (GPL2) as published by the Free Software +Foundation and appearing in the file GPL2.TXT included in the packaging of +this file. Please note that GPL2 Section 2[b] requires that all works based +on this software must also be made publicly available under the terms of +the GPL2 ("Copyleft"). + +Contact information +------------------- + +Circuits At Home, LTD +Web : http://www.circuitsathome.com +e-mail : support@circuitsathome.com + */ +#if !defined(__HIDUSAGETITLEARRAYS_H__) +#define __HIDUSAGETITLEARRAYS_H__ + +#include +#include "hidusagestr.h" + +//const char *usagePageTitles0[] PROGMEM = +//{ +// pstrUsagePageGenericDesktopControls , +// pstrUsagePageSimulationControls , +// pstrUsagePageVRControls , +// pstrUsagePageSportControls , +// pstrUsagePageGameControls , +// pstrUsagePageGenericDeviceControls , +// pstrUsagePageKeyboardKeypad , +// pstrUsagePageLEDs , +// pstrUsagePageButton , +// pstrUsagePageOrdinal , +// pstrUsagePageTelephone , +// pstrUsagePageConsumer , +// pstrUsagePageDigitizer , +// pstrUsagePagePID , +// pstrUsagePageUnicode +//}; +// +//const char *usagePageTitles1[] PROGMEM = +//{ +// pstrUsagePageBarCodeScanner , +// pstrUsagePageScale , +// pstrUsagePageMSRDevices , +// pstrUsagePagePointOfSale , +// pstrUsagePageCameraControl , +// pstrUsagePageArcade +//}; +//const char *genDesktopTitles0[] PROGMEM = +//{ +// pstrUsagePointer , +// pstrUsageMouse , +// pstrUsageJoystick , +// pstrUsageGamePad , +// pstrUsageKeyboard , +// pstrUsageKeypad , +// pstrUsageMultiAxisController , +// pstrUsageTabletPCSystemControls +// +//}; +//const char *genDesktopTitles1[] PROGMEM = +//{ +// pstrUsageX , +// pstrUsageY , +// pstrUsageZ , +// pstrUsageRx , +// pstrUsageRy , +// pstrUsageRz , +// pstrUsageSlider , +// pstrUsageDial , +// pstrUsageWheel , +// pstrUsageHatSwitch , +// pstrUsageCountedBuffer , +// pstrUsageByteCount , +// pstrUsageMotionWakeup , +// pstrUsageStart , +// pstrUsageSelect , +// pstrUsagePageReserved , +// pstrUsageVx , +// pstrUsageVy , +// pstrUsageVz , +// pstrUsageVbrx , +// pstrUsageVbry , +// pstrUsageVbrz , +// pstrUsageVno , +// pstrUsageFeatureNotification , +// pstrUsageResolutionMultiplier +//}; +//const char *genDesktopTitles2[] PROGMEM = +//{ +// pstrUsageSystemControl , +// pstrUsageSystemPowerDown , +// pstrUsageSystemSleep , +// pstrUsageSystemWakeup , +// pstrUsageSystemContextMenu , +// pstrUsageSystemMainMenu , +// pstrUsageSystemAppMenu , +// pstrUsageSystemMenuHelp , +// pstrUsageSystemMenuExit , +// pstrUsageSystemMenuSelect , +// pstrUsageSystemMenuRight , +// pstrUsageSystemMenuLeft , +// pstrUsageSystemMenuUp , +// pstrUsageSystemMenuDown , +// pstrUsageSystemColdRestart , +// pstrUsageSystemWarmRestart , +// pstrUsageDPadUp , +// pstrUsageDPadDown , +// pstrUsageDPadRight , +// pstrUsageDPadLeft +//}; +//const char *genDesktopTitles3[] PROGMEM = +//{ +// pstrUsageSystemDock , +// pstrUsageSystemUndock , +// pstrUsageSystemSetup , +// pstrUsageSystemBreak , +// pstrUsageSystemDebuggerBreak , +// pstrUsageApplicationBreak , +// pstrUsageApplicationDebuggerBreak, +// pstrUsageSystemSpeakerMute , +// pstrUsageSystemHibernate +//}; +//const char *genDesktopTitles4[] PROGMEM = +//{ +// pstrUsageSystemDisplayInvert , +// pstrUsageSystemDisplayInternal , +// pstrUsageSystemDisplayExternal , +// pstrUsageSystemDisplayBoth , +// pstrUsageSystemDisplayDual , +// pstrUsageSystemDisplayToggleIntExt , +// pstrUsageSystemDisplaySwapPriSec , +// pstrUsageSystemDisplayLCDAutoscale +//}; +//const char *simuTitles0[] PROGMEM = +//{ +// pstrUsageFlightSimulationDevice , +// pstrUsageAutomobileSimulationDevice , +// pstrUsageTankSimulationDevice , +// pstrUsageSpaceshipSimulationDevice , +// pstrUsageSubmarineSimulationDevice , +// pstrUsageSailingSimulationDevice , +// pstrUsageMotocicleSimulationDevice , +// pstrUsageSportsSimulationDevice , +// pstrUsageAirplaneSimulationDevice , +// pstrUsageHelicopterSimulationDevice , +// pstrUsageMagicCarpetSimulationDevice, +// pstrUsageBicycleSimulationDevice +//}; +//const char *simuTitles1[] PROGMEM = +//{ +// pstrUsageFlightControlStick , +// pstrUsageFlightStick , +// pstrUsageCyclicControl , +// pstrUsageCyclicTrim , +// pstrUsageFlightYoke , +// pstrUsageTrackControl +//}; +//const char *simuTitles2[] PROGMEM = +//{ +// pstrUsageAileron , +// pstrUsageAileronTrim , +// pstrUsageAntiTorqueControl , +// pstrUsageAutopilotEnable , +// pstrUsageChaffRelease , +// pstrUsageCollectiveControl , +// pstrUsageDiveBrake , +// pstrUsageElectronicCountermeasures , +// pstrUsageElevator , +// pstrUsageElevatorTrim , +// pstrUsageRudder , +// pstrUsageThrottle , +// pstrUsageFlightCommunications , +// pstrUsageFlareRelease , +// pstrUsageLandingGear , +// pstrUsageToeBrake , +// pstrUsageTrigger , +// pstrUsageWeaponsArm , +// pstrUsageWeaponsSelect , +// pstrUsageWingFlaps , +// pstrUsageAccelerator , +// pstrUsageBrake , +// pstrUsageClutch , +// pstrUsageShifter , +// pstrUsageSteering , +// pstrUsageTurretDirection , +// pstrUsageBarrelElevation , +// pstrUsageDivePlane , +// pstrUsageBallast , +// pstrUsageBicycleCrank , +// pstrUsageHandleBars , +// pstrUsageFrontBrake , +// pstrUsageRearBrake +//}; +//const char *vrTitles0[] PROGMEM = +//{ +// pstrUsageBelt , +// pstrUsageBodySuit , +// pstrUsageFlexor , +// pstrUsageGlove , +// pstrUsageHeadTracker , +// pstrUsageHeadMountedDisplay , +// pstrUsageHandTracker , +// pstrUsageOculometer , +// pstrUsageVest , +// pstrUsageAnimatronicDevice +//}; +//const char *vrTitles1[] PROGMEM = +//{ +// pstrUsageStereoEnable , +// pstrUsageDisplayEnable +//}; +//const char *sportsCtrlTitles0[] PROGMEM = +//{ +// pstrUsageBaseballBat , +// pstrUsageGolfClub , +// pstrUsageRowingMachine , +// pstrUsageTreadmill +//}; +//const char *sportsCtrlTitles1[] PROGMEM = +//{ +// pstrUsageOar , +// pstrUsageSlope , +// pstrUsageRate , +// pstrUsageStickSpeed , +// pstrUsageStickFaceAngle , +// pstrUsageStickHeelToe , +// pstrUsageStickFollowThough , +// pstrUsageStickTempo , +// pstrUsageStickType , +// pstrUsageStickHeight +//}; +//const char *sportsCtrlTitles2[] PROGMEM = +//{ +// pstrUsagePutter , +// pstrUsage1Iron , +// pstrUsage2Iron , +// pstrUsage3Iron , +// pstrUsage4Iron , +// pstrUsage5Iron , +// pstrUsage6Iron , +// pstrUsage7Iron , +// pstrUsage8Iron , +// pstrUsage9Iron , +// pstrUsage10Iron , +// pstrUsage11Iron , +// pstrUsageSandWedge , +// pstrUsageLoftWedge , +// pstrUsagePowerWedge , +// pstrUsage1Wood , +// pstrUsage3Wood , +// pstrUsage5Wood , +// pstrUsage7Wood , +// pstrUsage9Wood +//}; +//const char *gameTitles0[] PROGMEM = +//{ +// pstrUsage3DGameController , +// pstrUsagePinballDevice , +// pstrUsageGunDevice +//}; +//const char *gameTitles1[] PROGMEM = +//{ +// pstrUsagePointOfView , +// pstrUsageTurnRightLeft , +// pstrUsagePitchForwardBackward , +// pstrUsageRollRightLeft , +// pstrUsageMoveRightLeft , +// pstrUsageMoveForwardBackward , +// pstrUsageMoveUpDown , +// pstrUsageLeanRightLeft , +// pstrUsageLeanForwardBackward , +// pstrUsageHeightOfPOV , +// pstrUsageFlipper , +// pstrUsageSecondaryFlipper , +// pstrUsageBump , +// pstrUsageNewGame , +// pstrUsageShootBall , +// pstrUsagePlayer , +// pstrUsageGunBolt , +// pstrUsageGunClip , +// pstrUsageGunSelector , +// pstrUsageGunSingleShot , +// pstrUsageGunBurst , +// pstrUsageGunAutomatic , +// pstrUsageGunSafety , +// pstrUsageGamepadFireJump , +// pstrUsageGamepadTrigger +//}; +//const char *genDevCtrlTitles[] PROGMEM = +//{ +// pstrUsageBatteryStrength, +// pstrUsageWirelessChannel, +// pstrUsageWirelessID, +// pstrUsageDiscoverWirelessControl, +// pstrUsageSecurityCodeCharEntered, +// pstrUsageSecurityCodeCharErased, +// pstrUsageSecurityCodeCleared +//}; +//const char *ledTitles[] PROGMEM = +//{ +// pstrUsageNumLock , +// pstrUsageCapsLock , +// pstrUsageScrollLock , +// pstrUsageCompose , +// pstrUsageKana , +// pstrUsagePower , +// pstrUsageShift , +// pstrUsageDoNotDisturb , +// pstrUsageMute , +// pstrUsageToneEnable , +// pstrUsageHighCutFilter , +// pstrUsageLowCutFilter , +// pstrUsageEqualizerEnable , +// pstrUsageSoundFieldOn , +// pstrUsageSurroundOn , +// pstrUsageRepeat , +// pstrUsageStereo , +// pstrUsageSamplingRateDetect , +// pstrUsageSpinning , +// pstrUsageCAV , +// pstrUsageCLV , +// pstrUsageRecordingFormatDetect , +// pstrUsageOffHook , +// pstrUsageRing , +// pstrUsageMessageWaiting , +// pstrUsageDataMode , +// pstrUsageBatteryOperation , +// pstrUsageBatteryOK , +// pstrUsageBatteryLow , +// pstrUsageSpeaker , +// pstrUsageHeadSet , +// pstrUsageHold , +// pstrUsageMicrophone , +// pstrUsageCoverage , +// pstrUsageNightMode , +// pstrUsageSendCalls , +// pstrUsageCallPickup , +// pstrUsageConference , +// pstrUsageStandBy , +// pstrUsageCameraOn , +// pstrUsageCameraOff , +// pstrUsageOnLine , +// pstrUsageOffLine , +// pstrUsageBusy , +// pstrUsageReady , +// pstrUsagePaperOut , +// pstrUsagePaperJam , +// pstrUsageRemote , +// pstrUsageForward , +// pstrUsageReverse , +// pstrUsageStop , +// pstrUsageRewind , +// pstrUsageFastForward , +// pstrUsagePlay , +// pstrUsagePause , +// pstrUsageRecord , +// pstrUsageError , +// pstrUsageSelectedIndicator , +// pstrUsageInUseIndicator , +// pstrUsageMultiModeIndicator , +// pstrUsageIndicatorOn , +// pstrUsageIndicatorFlash , +// pstrUsageIndicatorSlowBlink , +// pstrUsageIndicatorFastBlink , +// pstrUsageIndicatorOff , +// pstrUsageFlashOnTime , +// pstrUsageSlowBlinkOnTime , +// pstrUsageSlowBlinkOffTime , +// pstrUsageFastBlinkOnTime , +// pstrUsageFastBlinkOffTime , +// pstrUsageIndicatorColor , +// pstrUsageIndicatorRed , +// pstrUsageIndicatorGreen , +// pstrUsageIndicatorAmber , +// pstrUsageGenericIndicator , +// pstrUsageSystemSuspend , +// pstrUsageExternalPowerConnected +//}; +//const char *telTitles0 [] PROGMEM = +//{ +// pstrUsagePhone , +// pstrUsageAnsweringMachine , +// pstrUsageMessageControls , +// pstrUsageHandset , +// pstrUsageHeadset , +// pstrUsageTelephonyKeyPad , +// pstrUsageProgrammableButton +//}; +//const char *telTitles1 [] PROGMEM = +//{ +// pstrUsageHookSwitch , +// pstrUsageFlash , +// pstrUsageFeature , +// pstrUsageHold , +// pstrUsageRedial , +// pstrUsageTransfer , +// pstrUsageDrop , +// pstrUsagePark , +// pstrUsageForwardCalls , +// pstrUsageAlternateFunction , +// pstrUsageLine , +// pstrUsageSpeakerPhone , +// pstrUsageConference , +// pstrUsageRingEnable , +// pstrUsageRingSelect , +// pstrUsagePhoneMute , +// pstrUsageCallerID , +// pstrUsageSend +//}; +//const char *telTitles2 [] PROGMEM = +//{ +// pstrUsageSpeedDial , +// pstrUsageStoreNumber , +// pstrUsageRecallNumber , +// pstrUsagePhoneDirectory +//}; +//const char *telTitles3 [] PROGMEM = +//{ +// pstrUsageVoiceMail , +// pstrUsageScreenCalls , +// pstrUsageDoNotDisturb , +// pstrUsageMessage , +// pstrUsageAnswerOnOff +//}; +//const char *telTitles4 [] PROGMEM = +//{ +// pstrUsageInsideDialTone , +// pstrUsageOutsideDialTone , +// pstrUsageInsideRingTone , +// pstrUsageOutsideRingTone , +// pstrUsagePriorityRingTone , +// pstrUsageInsideRingback , +// pstrUsagePriorityRingback , +// pstrUsageLineBusyTone , +// pstrUsageReorderTone , +// pstrUsageCallWaitingTone , +// pstrUsageConfirmationTone1 , +// pstrUsageConfirmationTone2 , +// pstrUsageTonesOff , +// pstrUsageOutsideRingback , +// pstrUsageRinger +//}; +//const char *telTitles5 [] PROGMEM = +//{ +// pstrUsagePhoneKey0 , +// pstrUsagePhoneKey1 , +// pstrUsagePhoneKey2 , +// pstrUsagePhoneKey3 , +// pstrUsagePhoneKey4 , +// pstrUsagePhoneKey5 , +// pstrUsagePhoneKey6 , +// pstrUsagePhoneKey7 , +// pstrUsagePhoneKey8 , +// pstrUsagePhoneKey9 , +// pstrUsagePhoneKeyStar , +// pstrUsagePhoneKeyPound , +// pstrUsagePhoneKeyA , +// pstrUsagePhoneKeyB , +// pstrUsagePhoneKeyC , +// pstrUsagePhoneKeyD +//}; +//const char *consTitles0[] PROGMEM = +//{ +// pstrUsageConsumerControl, +// pstrUsageNumericKeyPad, +// pstrUsageProgrammableButton, +// pstrUsageMicrophone, +// pstrUsageHeadphone, +// pstrUsageGraphicEqualizer +//}; +//const char *consTitles1[] PROGMEM = +//{ +// pstrUsagePlus10 , +// pstrUsagePlus100, +// pstrUsageAMPM +//}; +//const char *consTitles2[] PROGMEM = +//{ +// pstrUsagePower , +// pstrUsageReset , +// pstrUsageSleep , +// pstrUsageSleepAfter , +// pstrUsageSleepMode , +// pstrUsageIllumination , +// pstrUsageFunctionButtons +// +//}; +//const char *consTitles3[] PROGMEM = +//{ +// pstrUsageMenu , +// pstrUsageMenuPick , +// pstrUsageMenuUp , +// pstrUsageMenuDown , +// pstrUsageMenuLeft , +// pstrUsageMenuRight , +// pstrUsageMenuEscape , +// pstrUsageMenuValueIncrease, +// pstrUsageMenuValueDecrease +//}; +//const char *consTitles4[] PROGMEM = +//{ +// pstrUsageDataOnScreen , +// pstrUsageClosedCaption , +// pstrUsageClosedCaptionSelect, +// pstrUsageVCRTV , +// pstrUsageBroadcastMode , +// pstrUsageSnapshot , +// pstrUsageStill +//}; +//const char *consTitles5[] PROGMEM = +//{ +// pstrUsageSelection , +// pstrUsageAssignSelection , +// pstrUsageModeStep , +// pstrUsageRecallLast , +// pstrUsageEnterChannel , +// pstrUsageOrderMovie , +// pstrUsageChannel , +// pstrUsageMediaSelection , +// pstrUsageMediaSelectComputer , +// pstrUsageMediaSelectTV , +// pstrUsageMediaSelectWWW , +// pstrUsageMediaSelectDVD , +// pstrUsageMediaSelectTelephone , +// pstrUsageMediaSelectProgramGuide , +// pstrUsageMediaSelectVideoPhone , +// pstrUsageMediaSelectGames , +// pstrUsageMediaSelectMessages , +// pstrUsageMediaSelectCD , +// pstrUsageMediaSelectVCR , +// pstrUsageMediaSelectTuner , +// pstrUsageQuit , +// pstrUsageHelp , +// pstrUsageMediaSelectTape , +// pstrUsageMediaSelectCable , +// pstrUsageMediaSelectSatellite , +// pstrUsageMediaSelectSecurity , +// pstrUsageMediaSelectHome , +// pstrUsageMediaSelectCall , +// pstrUsageChannelIncrement , +// pstrUsageChannelDecrement , +// pstrUsageMediaSelectSAP , +// pstrUsagePageReserved , +// pstrUsageVCRPlus , +// pstrUsageOnce , +// pstrUsageDaily , +// pstrUsageWeekly , +// pstrUsageMonthly +//}; +//const char *consTitles6[] PROGMEM = +//{ +// pstrUsagePlay , +// pstrUsagePause , +// pstrUsageRecord , +// pstrUsageFastForward , +// pstrUsageRewind , +// pstrUsageScanNextTrack , +// pstrUsageScanPreviousTrack , +// pstrUsageStop , +// pstrUsageEject , +// pstrUsageRandomPlay , +// pstrUsageSelectDisk , +// pstrUsageEnterDisk , +// pstrUsageRepeat , +// pstrUsageTracking , +// pstrUsageTrackNormal , +// pstrUsageSlowTracking , +// pstrUsageFrameForward , +// pstrUsageFrameBackwards , +// pstrUsageMark , +// pstrUsageClearMark , +// pstrUsageRepeatFromMark , +// pstrUsageReturnToMark , +// pstrUsageSearchMarkForward , +// pstrUsageSearchMarkBackwards , +// pstrUsageCounterReset , +// pstrUsageShowCounter , +// pstrUsageTrackingIncrement , +// pstrUsageTrackingDecrement , +// pstrUsageStopEject , +// pstrUsagePlayPause , +// pstrUsagePlaySkip +//}; +//const char *consTitles7[] PROGMEM = +//{ +// pstrUsageVolume , +// pstrUsageBalance , +// pstrUsageMute , +// pstrUsageBass , +// pstrUsageTreble , +// pstrUsageBassBoost , +// pstrUsageSurroundMode , +// pstrUsageLoudness , +// pstrUsageMPX , +// pstrUsageVolumeIncrement , +// pstrUsageVolumeDecrement +//}; +//const char *consTitles8[] PROGMEM = +//{ +// pstrUsageSpeedSelect , +// pstrUsagePlaybackSpeed , +// pstrUsageStandardPlay , +// pstrUsageLongPlay , +// pstrUsageExtendedPlay , +// pstrUsageSlow +//}; +//const char *consTitles9[] PROGMEM = +//{ +// pstrUsageFanEnable , +// pstrUsageFanSpeed , +// pstrUsageLightEnable , +// pstrUsageLightIlluminationLevel , +// pstrUsageClimateControlEnable , +// pstrUsageRoomTemperature , +// pstrUsageSecurityEnable , +// pstrUsageFireAlarm , +// pstrUsagePoliceAlarm , +// pstrUsageProximity , +// pstrUsageMotion , +// pstrUsageDuresAlarm , +// pstrUsageHoldupAlarm , +// pstrUsageMedicalAlarm +//}; +//const char *consTitlesA[] PROGMEM = +//{ +// pstrUsageBalanceRight , +// pstrUsageBalanceLeft , +// pstrUsageBassIncrement , +// pstrUsageBassDecrement , +// pstrUsageTrebleIncrement , +// pstrUsageTrebleDecrement +//}; +//const char *consTitlesB[] PROGMEM = +//{ +// pstrUsageSpeakerSystem , +// pstrUsageChannelLeft , +// pstrUsageChannelRight , +// pstrUsageChannelCenter , +// pstrUsageChannelFront , +// pstrUsageChannelCenterFront , +// pstrUsageChannelSide , +// pstrUsageChannelSurround , +// pstrUsageChannelLowFreqEnhancement , +// pstrUsageChannelTop , +// pstrUsageChannelUnknown +//}; +//const char *consTitlesC[] PROGMEM = +//{ +// pstrUsageSubChannel , +// pstrUsageSubChannelIncrement , +// pstrUsageSubChannelDecrement , +// pstrUsageAlternateAudioIncrement , +// pstrUsageAlternateAudioDecrement +//}; +//const char *consTitlesD[] PROGMEM = +//{ +// pstrUsageApplicationLaunchButtons , +// pstrUsageALLaunchButtonConfigTool , +// pstrUsageALProgrammableButton , +// pstrUsageALConsumerControlConfig , +// pstrUsageALWordProcessor , +// pstrUsageALTextEditor , +// pstrUsageALSpreadsheet , +// pstrUsageALGraphicsEditor , +// pstrUsageALPresentationApp , +// pstrUsageALDatabaseApp , +// pstrUsageALEmailReader , +// pstrUsageALNewsreader , +// pstrUsageALVoicemail , +// pstrUsageALContactsAddressBook , +// pstrUsageALCalendarSchedule , +// pstrUsageALTaskProjectManager , +// pstrUsageALLogJournalTimecard , +// pstrUsageALCheckbookFinance , +// pstrUsageALCalculator , +// pstrUsageALAVCapturePlayback , +// pstrUsageALLocalMachineBrowser , +// pstrUsageALLANWANBrow , +// pstrUsageALInternetBrowser , +// pstrUsageALRemoteNetISPConnect , +// pstrUsageALNetworkConference , +// pstrUsageALNetworkChat , +// pstrUsageALTelephonyDialer , +// pstrUsageALLogon , +// pstrUsageALLogoff , +// pstrUsageALLogonLogoff , +// pstrUsageALTermLockScrSav , +// pstrUsageALControlPannel , +// pstrUsageALCommandLineProcessorRun , +// pstrUsageALProcessTaskManager , +// pstrUsageALSelectTaskApplication , +// pstrUsageALNextTaskApplication , +// pstrUsageALPreviousTaskApplication , +// pstrUsageALPreemptiveHaltTaskApp , +// pstrUsageALIntegratedHelpCenter , +// pstrUsageALDocuments , +// pstrUsageALThesaurus , +// pstrUsageALDictionary , +// pstrUsageALDesktop , +// pstrUsageALSpellCheck , +// pstrUsageALGrammarCheck , +// pstrUsageALWirelessStatus , +// pstrUsageALKeyboardLayout , +// pstrUsageALVirusProtection , +// pstrUsageALEncryption , +// pstrUsageALScreenSaver , +// pstrUsageALAlarms , +// pstrUsageALClock , +// pstrUsageALFileBrowser , +// pstrUsageALPowerStatus , +// pstrUsageALImageBrowser , +// pstrUsageALAudioBrowser , +// pstrUsageALMovieBrowser , +// pstrUsageALDigitalRightsManager , +// pstrUsageALDigitalWallet , +// pstrUsagePageReserved , +// pstrUsageALInstantMessaging , +// pstrUsageALOEMFeaturesBrowser , +// pstrUsageALOEMHelp , +// pstrUsageALOnlineCommunity , +// pstrUsageALEntertainmentContentBrow , +// pstrUsageALOnlineShoppingBrowser , +// pstrUsageALSmartCardInfoHelp , +// pstrUsageALMarketMonitorFinBrowser , +// pstrUsageALCustomCorpNewsBrowser , +// pstrUsageALOnlineActivityBrowser , +// pstrUsageALResearchSearchBrowser , +// pstrUsageALAudioPlayer +//}; +//const char *consTitlesE[] PROGMEM = +//{ +// pstrUsageGenericGUIAppControls , +// pstrUsageACNew , +// pstrUsageACOpen , +// pstrUsageACClose , +// pstrUsageACExit , +// pstrUsageACMaximize , +// pstrUsageACMinimize , +// pstrUsageACSave , +// pstrUsageACPrint , +// pstrUsageACProperties , +// pstrUsageACUndo , +// pstrUsageACCopy , +// pstrUsageACCut , +// pstrUsageACPaste , +// pstrUsageACSelectAll , +// pstrUsageACFind , +// pstrUsageACFindAndReplace , +// pstrUsageACSearch , +// pstrUsageACGoto , +// pstrUsageACHome , +// pstrUsageACBack , +// pstrUsageACForward , +// pstrUsageACStop , +// pstrUsageACRefresh , +// pstrUsageACPreviousLink , +// pstrUsageACNextLink , +// pstrUsageACBookmarks , +// pstrUsageACHistory , +// pstrUsageACSubscriptions , +// pstrUsageACZoomIn , +// pstrUsageACZoomOut , +// pstrUsageACZoom , +// pstrUsageACFullScreenView , +// pstrUsageACNormalView , +// pstrUsageACViewToggle , +// pstrUsageACScrollUp , +// pstrUsageACScrollDown , +// pstrUsageACScroll , +// pstrUsageACPanLeft , +// pstrUsageACPanRight , +// pstrUsageACPan , +// pstrUsageACNewWindow , +// pstrUsageACTileHoriz , +// pstrUsageACTileVert , +// pstrUsageACFormat , +// pstrUsageACEdit , +// pstrUsageACBold , +// pstrUsageACItalics , +// pstrUsageACUnderline , +// pstrUsageACStrikethrough , +// pstrUsageACSubscript , +// pstrUsageACSuperscript , +// pstrUsageACAllCaps , +// pstrUsageACRotate , +// pstrUsageACResize , +// pstrUsageACFlipHorizontal , +// pstrUsageACFlipVertical , +// pstrUsageACMirrorHorizontal , +// pstrUsageACMirrorVertical , +// pstrUsageACFontSelect , +// pstrUsageACFontColor , +// pstrUsageACFontSize , +// pstrUsageACJustifyLeft , +// pstrUsageACJustifyCenterH , +// pstrUsageACJustifyRight , +// pstrUsageACJustifyBlockH , +// pstrUsageACJustifyTop , +// pstrUsageACJustifyCenterV , +// pstrUsageACJustifyBottom , +// pstrUsageACJustifyBlockV , +// pstrUsageACIndentDecrease , +// pstrUsageACIndentIncrease , +// pstrUsageACNumberedList , +// pstrUsageACRestartNumbering , +// pstrUsageACBulletedList , +// pstrUsageACPromote , +// pstrUsageACDemote , +// pstrUsageACYes , +// pstrUsageACNo , +// pstrUsageACCancel , +// pstrUsageACCatalog , +// pstrUsageACBuyChkout , +// pstrUsageACAddToCart , +// pstrUsageACExpand , +// pstrUsageACExpandAll , +// pstrUsageACCollapse , +// pstrUsageACCollapseAll , +// pstrUsageACPrintPreview , +// pstrUsageACPasteSpecial , +// pstrUsageACInsertMode , +// pstrUsageACDelete , +// pstrUsageACLock , +// pstrUsageACUnlock , +// pstrUsageACProtect , +// pstrUsageACUnprotect , +// pstrUsageACAttachComment , +// pstrUsageACDeleteComment , +// pstrUsageACViewComment , +// pstrUsageACSelectWord , +// pstrUsageACSelectSentence , +// pstrUsageACSelectParagraph , +// pstrUsageACSelectColumn , +// pstrUsageACSelectRow , +// pstrUsageACSelectTable , +// pstrUsageACSelectObject , +// pstrUsageACRedoRepeat , +// pstrUsageACSort , +// pstrUsageACSortAscending , +// pstrUsageACSortDescending , +// pstrUsageACFilter , +// pstrUsageACSetClock , +// pstrUsageACViewClock , +// pstrUsageACSelectTimeZone , +// pstrUsageACEditTimeZone , +// pstrUsageACSetAlarm , +// pstrUsageACClearAlarm , +// pstrUsageACSnoozeAlarm , +// pstrUsageACResetAlarm , +// pstrUsageACSyncronize , +// pstrUsageACSendReceive , +// pstrUsageACSendTo , +// pstrUsageACReply , +// pstrUsageACReplyAll , +// pstrUsageACForwardMessage , +// pstrUsageACSend , +// pstrUsageACAttachFile , +// pstrUsageACUpload , +// pstrUsageACDownload , +// pstrUsageACSetBorders , +// pstrUsageACInsertRow , +// pstrUsageACInsertColumn , +// pstrUsageACInsertFile , +// pstrUsageACInsertPicture , +// pstrUsageACInsertObject , +// pstrUsageACInsertSymbol , +// pstrUsageACSaveAndClose , +// pstrUsageACRename , +// pstrUsageACMerge , +// pstrUsageACSplit , +// pstrUsageACDistributeHorizontaly , +// pstrUsageACDistributeVerticaly +//}; +//const char *digitTitles0[] PROGMEM = +//{ +// pstrUsageDigitizer , +// pstrUsagePen , +// pstrUsageLightPen , +// pstrUsageTouchScreen , +// pstrUsageTouchPad , +// pstrUsageWhiteBoard , +// pstrUsageCoordinateMeasuringMachine , +// pstrUsage3DDigitizer , +// pstrUsageStereoPlotter , +// pstrUsageArticulatedArm , +// pstrUsageArmature , +// pstrUsageMultiplePointDigitizer , +// pstrUsageFreeSpaceWand +//}; +//const char *digitTitles1[] PROGMEM = +//{ +// pstrUsageStylus , +// pstrUsagePuck , +// pstrUsageFinger +// +//}; +//const char *digitTitles2[] PROGMEM = +//{ +// pstrUsageTipPressure , +// pstrUsageBarrelPressure , +// pstrUsageInRange , +// pstrUsageTouch , +// pstrUsageUntouch , +// pstrUsageTap , +// pstrUsageQuality , +// pstrUsageDataValid , +// pstrUsageTransducerIndex , +// pstrUsageTabletFunctionKeys , +// pstrUsageProgramChangeKeys , +// pstrUsageBatteryStrength , +// pstrUsageInvert , +// pstrUsageXTilt , +// pstrUsageYTilt , +// pstrUsageAzimuth , +// pstrUsageAltitude , +// pstrUsageTwist , +// pstrUsageTipSwitch , +// pstrUsageSecondaryTipSwitch , +// pstrUsageBarrelSwitch , +// pstrUsageEraser , +// pstrUsageTabletPick +//}; +//const char *aplphanumTitles0[] PROGMEM = +//{ +// pstrUsageAlphanumericDisplay, +// pstrUsageBitmappedDisplay +//}; +//const char *aplphanumTitles1[] PROGMEM = +//{ +// pstrUsageDisplayAttributesReport , +// pstrUsageASCIICharacterSet , +// pstrUsageDataReadBack , +// pstrUsageFontReadBack , +// pstrUsageDisplayControlReport , +// pstrUsageClearDisplay , +// pstrUsageDisplayEnable , +// pstrUsageScreenSaverDelay , +// pstrUsageScreenSaverEnable , +// pstrUsageVerticalScroll , +// pstrUsageHorizontalScroll , +// pstrUsageCharacterReport , +// pstrUsageDisplayData , +// pstrUsageDisplayStatus , +// pstrUsageStatusNotReady , +// pstrUsageStatusReady , +// pstrUsageErrorNotALoadableCharacter , +// pstrUsageErrorFotDataCanNotBeRead , +// pstrUsageCursorPositionReport , +// pstrUsageRow , +// pstrUsageColumn , +// pstrUsageRows , +// pstrUsageColumns , +// pstrUsageCursorPixelPosition , +// pstrUsageCursorMode , +// pstrUsageCursorEnable , +// pstrUsageCursorBlink , +// pstrUsageFontReport , +// pstrUsageFontData , +// pstrUsageCharacterWidth , +// pstrUsageCharacterHeight , +// pstrUsageCharacterSpacingHorizontal , +// pstrUsageCharacterSpacingVertical , +// pstrUsageUnicodeCharset , +// pstrUsageFont7Segment , +// pstrUsage7SegmentDirectMap , +// pstrUsageFont14Segment , +// pstrUsage14SegmentDirectMap , +// pstrUsageDisplayBrightness , +// pstrUsageDisplayContrast , +// pstrUsageCharacterAttribute , +// pstrUsageAttributeReadback , +// pstrUsageAttributeData , +// pstrUsageCharAttributeEnhance , +// pstrUsageCharAttributeUnderline , +// pstrUsageCharAttributeBlink +//}; +//const char *aplphanumTitles2[] PROGMEM = +//{ +// pstrUsageBitmapSizeX , +// pstrUsageBitmapSizeY , +// pstrUsagePageReserved , +// pstrUsageBitDepthFormat , +// pstrUsageDisplayOrientation , +// pstrUsagePaletteReport , +// pstrUsagePaletteDataSize , +// pstrUsagePaletteDataOffset , +// pstrUsagePaletteData , +// pstrUsageBlitReport , +// pstrUsageBlitRectangleX1 , +// pstrUsageBlitRectangleY1 , +// pstrUsageBlitRectangleX2 , +// pstrUsageBlitRectangleY2 , +// pstrUsageBlitData , +// pstrUsageSoftButton , +// pstrUsageSoftButtonID , +// pstrUsageSoftButtonSide , +// pstrUsageSoftButtonOffset1 , +// pstrUsageSoftButtonOffset2 , +// pstrUsageSoftButtonReport +//}; +//const char *medInstrTitles0[] PROGMEM = +//{ +// pstrUsageVCRAcquisition , +// pstrUsageFreezeThaw , +// pstrUsageClipStore , +// pstrUsageUpdate , +// pstrUsageNext , +// pstrUsageSave , +// pstrUsagePrint , +// pstrUsageMicrophoneEnable +//}; +//const char *medInstrTitles1[] PROGMEM = +//{ +// pstrUsageCine , +// pstrUsageTransmitPower , +// pstrUsageVolume , +// pstrUsageFocus , +// pstrUsageDepth +//}; +//const char *medInstrTitles2[] PROGMEM = +//{ +// pstrUsageSoftStepPrimary , +// pstrUsageSoftStepSecondary +//}; +//const char *medInstrTitles3[] PROGMEM = +//{ +// pstrUsageZoomSelect , +// pstrUsageZoomAdjust , +// pstrUsageSpectralDopplerModeSelect , +// pstrUsageSpectralDopplerModeAdjust , +// pstrUsageColorDopplerModeSelect , +// pstrUsageColorDopplerModeAdjust , +// pstrUsageMotionModeSelect , +// pstrUsageMotionModeAdjust , +// pstrUsage2DModeSelect , +// pstrUsage2DModeAdjust +//}; +//const char *medInstrTitles4[] PROGMEM = +//{ +// pstrUsageSoftControlSelect , +// pstrUsageSoftControlAdjust +//}; + #endif // __HIDUSAGETITLEARRAYS_H__ \ No newline at end of file diff --git a/masstorage.cpp b/masstorage.cpp index e95fd0d0..1fca5f55 100644 --- a/masstorage.cpp +++ b/masstorage.cpp @@ -1,646 +1,861 @@ -#include "masstorage.h" - - -//bool BulkReadParser::IsValidCSW(uint8_t size, uint8_t *pcsw) -//{ -// if (size != 0x0d) -// { -// Notify(PSTR("CSW:Size error")); -// return false; -// } -// if (*((uint32_t*)pcsw) != MASS_CSW_SIGNATURE) -// { -// Notify(PSTR("CSW:Sig error")); -// return false; -// } -// //if (size != 0x0d || *((uint32_t*)pcsw) != MASS_CSW_SIGNATURE || -// // ((CommandStatusWrapper*)pcsw)->dCSWTag != dCBWTag) -// // return false; -// return true; -//} - -//bool BulkReadParser::IsMeaningfulCSW(uint8_t size, uint8_t *pcsw) -//{ -// if (((CommandStatusWrapper*)pcsw)->bCSWStatus < 2 && -// ((CommandStatusWrapper*)pcsw)->dCSWDataResidue <= dCBWDataTransferLength ) -// return true; -// if ( ((CommandStatusWrapper*)pcsw)->bCSWStatus == 2 ) -// return true; -// return false; -//} - -//void BulkReadParser::Parse(const uint16_t len, const uint8_t *pbuf, const uint16_t &offset) -//{ -// if (offset == 0 && len > sizeof(CommandStatusWrapper)) -// if (IsValidCSW(sizeof(CommandStatusWrapper), pbuf) && IsMeaningfulCSW(sizeof(CommandStatusWrapper), pbuf)) -// { -// CommandStatusWrapper *pCSW = (CommandStatusWrapper*)pbuf; -// -// Serial.println("Sig:"); -// PrintHex(pCSW->dCSWSignature); -// Serial.println("Tag:"); -// PrintHex(pCSW->dCSWTag); -// Serial.println("Res:"); -// PrintHex(pCSW->dCSWDataResidue); -// Serial.println("Ret:"); -// PrintHex(pCSW->bCSWStatus); -// } -//} - -const uint8_t BulkOnly::epDataInIndex = 1; -const uint8_t BulkOnly::epDataOutIndex = 2; -const uint8_t BulkOnly::epInterruptInIndex = 3; - -BulkOnly::BulkOnly(USB *p /*, CDCAsyncOper *pasync*/) : - pUsb(p), - //pAsync(pasync), - bAddress(0), - qNextPollTime(0), - bPollEnable(false), - bIface(0), - bNumEP(1) -{ - for(uint8_t i=0; iRegisterDeviceClass(this); -} - -uint8_t BulkOnly::Init(uint8_t parent, uint8_t port, bool lowspeed) -{ - const uint8_t constBufSize = sizeof(USB_DEVICE_DESCRIPTOR); - - uint8_t buf[constBufSize]; - uint8_t rcode; - UsbDevice *p = NULL; - EpInfo *oldep_ptr = NULL; - uint8_t num_of_conf; // number of configurations - - AddressPool &addrPool = pUsb->GetAddressPool(); - - USBTRACE("MS Init\r\n"); - - if (bAddress) - return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE; - - // Get pointer to pseudo device with address 0 assigned - p = addrPool.GetUsbDevicePtr(0); - - if (!p) - return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; - - if (!p->epinfo) - { - USBTRACE("epinfo\r\n"); - return USB_ERROR_EPINFO_IS_NULL; - } - - // Save old pointer to EP_RECORD of address 0 - oldep_ptr = p->epinfo; - - // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence - p->epinfo = epInfo; - - p->lowspeed = lowspeed; - - // Get device descriptor - rcode = pUsb->getDevDescr( 0, 0, constBufSize, (uint8_t*)buf ); - - // Restore p->epinfo - p->epinfo = oldep_ptr; - - if( rcode ) - goto FailGetDevDescr; - - // Allocate new address according to device class - bAddress = addrPool.AllocAddress(parent, false, port); - - if (!bAddress) - return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; - - // Extract Max Packet Size from the device descriptor - epInfo[0].maxPktSize = (uint8_t)((USB_DEVICE_DESCRIPTOR*)buf)->bMaxPacketSize0; - - // Assign new address to the device - rcode = pUsb->setAddr( 0, 0, bAddress ); - - if (rcode) - { - p->lowspeed = false; - addrPool.FreeAddress(bAddress); - bAddress = 0; - USBTRACE2("setAddr:",rcode); - return rcode; - } - - USBTRACE2("Addr:", bAddress); - - p->lowspeed = false; - - p = addrPool.GetUsbDevicePtr(bAddress); - - if (!p) - return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; - - p->lowspeed = lowspeed; - - num_of_conf = ((USB_DEVICE_DESCRIPTOR*)buf)->bNumConfigurations; - - // Assign epInfo to epinfo pointer - rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); - - if (rcode) - goto FailSetDevTblEntry; - - USBTRACE2("NC:", num_of_conf); - - for (uint8_t i=0; i HexDump; - ConfigDescParser< USB_CLASS_MASS_STORAGE, - MASS_SUBCLASS_SCSI, - MASS_PROTO_BBB, - CP_MASK_COMPARE_CLASS | - CP_MASK_COMPARE_SUBCLASS | - CP_MASK_COMPARE_PROTOCOL> BulkOnlyParser(this); - - rcode = pUsb->getConfDescr(bAddress, 0, i, &HexDump); - rcode = pUsb->getConfDescr(bAddress, 0, i, &BulkOnlyParser); - - - if (bNumEP > 1) - break; - } // for - - if (bNumEP < 3) - return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; - - // Assign epInfo to epinfo pointer - rcode = pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo); - - USBTRACE2("Conf:", bConfNum); - - // Set Configuration Value - rcode = pUsb->setConf(bAddress, 0, bConfNum); - - if (rcode) - goto FailSetConf; - - delay(5000); - - //rcode = pAsync->OnInit(this); - - //if (rcode) - // goto FailOnInit; - - rcode = GetMaxLUN(&bMaxLUN); - - if (rcode) - goto FailGetMaxLUN; - - delay(10); - - { - InquiryResponse response; - rcode = Inquiry(bMaxLUN, sizeof(InquiryResponse), (uint8_t*)&response); - - if (rcode) - goto FailInquiry; - - //if (response.DeviceType != 0) - // goto FailInvalidDevice; - } - - delay(10); - - USBTRACE("MS configured\r\n"); - - bPollEnable = true; - - //USBTRACE("Poll enabled\r\n"); - return 0; - -FailGetDevDescr: - USBTRACE("getDevDescr:"); - goto Fail; - -FailSetDevTblEntry: - USBTRACE("setDevTblEn:"); - goto Fail; - -FailGetConfDescr: - USBTRACE("getConf:"); - goto Fail; - -FailSetConf: - USBTRACE("setConf:"); - goto Fail; - -FailOnInit: - USBTRACE("OnInit:"); - goto Fail; - -FailGetMaxLUN: - USBTRACE("GetMaxLUN:"); - goto Fail; - -FailInquiry: - USBTRACE("Inquiry:"); - goto Fail; - -Fail: - Serial.println(rcode, HEX); - Release(); - return rcode; -} - - -void BulkOnly::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *pep) -{ - ErrorMessage(PSTR("Conf.Val"), conf); - ErrorMessage(PSTR("Iface Num"),iface); - ErrorMessage(PSTR("Alt.Set"), alt); - - bConfNum = conf; - - uint8_t index; - - if ((pep->bmAttributes & 0x03) == 3 && (pep->bEndpointAddress & 0x80) == 0x80) - index = epInterruptInIndex; - else - if ((pep->bmAttributes & 0x02) == 2) - index = ((pep->bEndpointAddress & 0x80) == 0x80) ? epDataInIndex : epDataOutIndex; - else - return; - - // Fill in the endpoint info structure - epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F); - epInfo[index].maxPktSize = (uint8_t)pep->wMaxPacketSize; - epInfo[index].epAttribs = 0; - - bNumEP ++; - - PrintEndpointDescriptor(pep); -} - -uint8_t BulkOnly::Release() -{ - pUsb->GetAddressPool().FreeAddress(bAddress); - - bIface = 0; - bNumEP = 1; - - bAddress = 0; - qNextPollTime = 0; - bPollEnable = false; - return 0; -} - -uint8_t BulkOnly::Poll() -{ - uint8_t rcode = 0; - - if (!bPollEnable) - return 0; - - uint32_t time_now = millis(); - - //if (qNextPollTime <= time_now) - //{ - // qNextPollTime = time_now + 100; - - // uint8_t rcode; - // const uint8_t constBufSize = 16; - // uint8_t buf[constBufSize]; - - // for (uint8_t i=0; i epInfo[epInterruptInIndex].maxPktSize) - // ? epInfo[epInterruptInIndex].maxPktSize : constBufSize; - // rcode = pUsb->inTransfer(bAddress, epInfo[epInterruptInIndex].epAddr, &read, buf); - - // if (rcode) - // return rcode; - - // for (uint8_t i=0; i(buf[i]); - // Serial.print(" "); - // } - // USBTRACE("\r\n"); - //} - return rcode; -} - -bool BulkOnly::IsValidCBW(uint8_t size, uint8_t *pcbw) -{ - if (size != 0x1f || *((uint32_t*)pcbw) != MASS_CBW_SIGNATURE) - return false; - return true; -} - -bool BulkOnly::IsMeaningfulCBW(uint8_t size, uint8_t *pcbw) -{ - if (((CommandBlockWrapper*)pcbw)->bmReserved1 != 0 || - ((CommandBlockWrapper*)pcbw)->bmReserved2 != 0 || - ((CommandBlockWrapper*)pcbw)->bmCBWLUN > bMaxLUN || - ((CommandBlockWrapper*)pcbw)->bmCBWCBLength > 0x10 ) - return false; - return true; -} - -uint8_t BulkOnly::Reset() -{ - return( pUsb->ctrlReq( bAddress, 0, bmREQ_MASSOUT, MASS_REQ_BOMSR, 0, 0, bIface, 0, 0, NULL, NULL )); -} - -uint8_t BulkOnly::GetMaxLUN(uint8_t *plun) -{ - uint8_t cnt = 3; - - bLastUsbError = pUsb->ctrlReq( bAddress, 0, bmREQ_MASSIN, MASS_REQ_GET_MAX_LUN, 0, 0, bIface, 1, 1, plun, NULL ); - - delay(10); - //Serial.println(F("bLastUsbError: ")); - //Serial.println(bLastUsbError); - - if (bLastUsbError == hrSTALL) - { - *plun = 0; - bLastUsbError = ClearEpHalt(epDataInIndex); - return MASS_ERR_SUCCESS; - } - if (bLastUsbError == hrJERR) - return MASS_ERR_DEVICE_DISCONNECTED; - else if (bLastUsbError) - return MASS_ERR_GENERAL_USB_ERROR; - return MASS_ERR_SUCCESS; -} - -uint8_t BulkOnly::HandleUsbError(uint8_t index) -{ - uint8_t count = 3; - - while (bLastUsbError && count) - { - switch (bLastUsbError) - { - case hrSUCCESS: - return MASS_ERR_SUCCESS; - case hrJERR: - bLastUsbError = hrSUCCESS; - return MASS_ERR_DEVICE_DISCONNECTED; - case hrSTALL: - bLastUsbError = ClearEpHalt(index); - break; - default: - return MASS_ERR_GENERAL_USB_ERROR; - } - count --; - } // while - - return MASS_ERR_SUCCESS; -} - -uint8_t BulkOnly::ClearEpHalt(uint8_t index) -{ - return (pUsb->ctrlReq( bAddress, 0, USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_STANDARD|USB_SETUP_RECIPIENT_ENDPOINT, - USB_REQUEST_CLEAR_FEATURE, USB_FEATURE_ENDPOINT_HALT, 0, epInfo[index].epAddr, 0, 0, NULL, NULL )); -} - -uint8_t BulkOnly::ResetRecovery() -{ - bLastUsbError = Reset(); - - if (bLastUsbError) - return bLastUsbError; - - delay(6); - - bLastUsbError = ClearEpHalt(epDataInIndex); - - if (bLastUsbError) - return bLastUsbError; - - delay(6); - - bLastUsbError = ClearEpHalt(epDataOutIndex); - - delay(6); - - return bLastUsbError; -} - -uint8_t BulkOnly::Inquiry(uint8_t lun, uint16_t bsize, uint8_t *buf) -{ - CommandBlockWrapper cbw; - - cbw.dCBWSignature = MASS_CBW_SIGNATURE; - cbw.dCBWTag = 0xdeadbeef; - cbw.dCBWDataTransferLength = bsize; - cbw.bmCBWFlags = MASS_CMD_DIR_IN, - cbw.bmCBWLUN = lun; - cbw.bmCBWCBLength = 6; - - for (uint8_t i=0; i<16; i++) - cbw.CBWCB[i] = 0; - - cbw.CBWCB[0] = SCSI_CMD_INQUIRY; - cbw.CBWCB[4] = bsize; - - return Transaction(&cbw, bsize, buf, 0); -} - -uint8_t BulkOnly::RequestSense(uint8_t lun, uint16_t size, uint8_t *buf) -{ - CommandBlockWrapper cbw; - - cbw.dCBWSignature = MASS_CBW_SIGNATURE; - cbw.dCBWTag = 0xdeadbeef; - cbw.dCBWDataTransferLength = size; - cbw.bmCBWFlags = MASS_CMD_DIR_IN, - cbw.bmCBWLUN = lun; - cbw.bmCBWCBLength = 6; - - for (uint8_t i=0; i<16; i++) - cbw.CBWCB[i] = 0; - - cbw.CBWCB[0] = SCSI_CMD_REQUEST_SENSE; - cbw.CBWCB[4] = size; - - return Transaction(&cbw, size, buf, 0); -} - -uint8_t BulkOnly::ReadCapacity(uint8_t lun, uint16_t bsize, uint8_t *buf) -{ - CommandBlockWrapper cbw; - - cbw.dCBWSignature = MASS_CBW_SIGNATURE; - cbw.dCBWTag = 0xdeadbeef; - cbw.dCBWDataTransferLength = bsize; - cbw.bmCBWFlags = MASS_CMD_DIR_IN, - cbw.bmCBWLUN = lun; - cbw.bmCBWCBLength = 10; - - for (uint8_t i=0; i<16; i++) - cbw.CBWCB[i] = 0; - - cbw.CBWCB[0] = SCSI_CMD_READ_CAPACITY_10; - cbw.CBWCB[4] = bsize; - - return Transaction(&cbw, bsize, buf, 0); -} - -uint8_t BulkOnly::TestUnitReady(uint8_t lun) -{ - CommandBlockWrapper cbw; - - cbw.dCBWSignature = MASS_CBW_SIGNATURE; - cbw.dCBWTag = 0xdeadbeef; - cbw.dCBWDataTransferLength = 0; - cbw.bmCBWFlags = MASS_CMD_DIR_OUT, - cbw.bmCBWLUN = lun; - cbw.bmCBWCBLength = 6; - - for (uint8_t i=0; i<16; i++) - cbw.CBWCB[i] = 0; - - cbw.CBWCB[0] = SCSI_CMD_TEST_UNIT_READY; - - return Transaction(&cbw, 0, NULL, 0); -} - -uint8_t BulkOnly::Read(uint8_t lun, uint32_t addr, uint16_t bsize, USBReadParser *prs) -{ - CommandBlockWrapper cbw; - - cbw.dCBWSignature = MASS_CBW_SIGNATURE; - cbw.dCBWTag = 0xdeadbeef; - cbw.dCBWDataTransferLength = bsize; - cbw.bmCBWFlags = MASS_CMD_DIR_IN, - cbw.bmCBWLUN = lun; - cbw.bmCBWCBLength = 10; - - for (uint8_t i=0; i<16; i++) - cbw.CBWCB[i] = 0; - - cbw.CBWCB[0] = SCSI_CMD_READ_10; - cbw.CBWCB[8] = 1; - cbw.CBWCB[5] = (addr & 0xff); - cbw.CBWCB[4] = ((addr >> 8) & 0xff); - cbw.CBWCB[3] = ((addr >> 16) & 0xff); - cbw.CBWCB[2] = ((addr >> 24) & 0xff); - - return Transaction(&cbw, bsize, prs, 1); -} - -uint8_t BulkOnly::Transaction(CommandBlockWrapper *cbw, uint16_t size, void *buf, uint8_t flags) -{ - uint16_t read; - { - bLastUsbError = pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, sizeof(CommandBlockWrapper), (uint8_t*)cbw); - - uint8_t ret = HandleUsbError(epDataOutIndex); - - if (ret) - { - ErrorMessage(PSTR("CBW"), ret); - return ret; - } - } - - if (size && buf) - { - read = size; - - if (cbw->bmCBWFlags & MASS_CMD_DIR_IN) - { - if ((flags & MASS_TRANS_FLG_CALLBACK) == MASS_TRANS_FLG_CALLBACK) - { - const uint8_t bufSize = 64; - uint16_t total = size; - uint16_t count = 0; - uint8_t rbuf[bufSize]; - - read = bufSize; - - while(count < total && - ((bLastUsbError = pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, &read, (uint8_t*)rbuf)) == hrSUCCESS) - ) - { - ((USBReadParser*)buf)->Parse(read, rbuf, count); - - count += read; - read = bufSize; - } - - if (bLastUsbError == hrSTALL) - bLastUsbError = ClearEpHalt(epDataInIndex); - - if (bLastUsbError) - { - ErrorMessage(PSTR("RDR"), bLastUsbError); - return MASS_ERR_GENERAL_USB_ERROR; - } - } // if ((flags & 1) == 1) - else - bLastUsbError = pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, &read, (uint8_t*)buf); - } // if (cbw->bmCBWFlags & MASS_CMD_DIR_IN) - - else if (cbw->bmCBWFlags & MASS_CMD_DIR_OUT) - bLastUsbError = pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, read, (uint8_t*)buf); - } - - uint8_t ret = HandleUsbError((cbw->bmCBWFlags & MASS_CMD_DIR_IN) ? epDataInIndex : epDataOutIndex); - - if (ret) - { - ErrorMessage(PSTR("RSP"), ret); - return MASS_ERR_GENERAL_USB_ERROR; - } - { - CommandStatusWrapper csw; - read = sizeof(CommandStatusWrapper); - - bLastUsbError = pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, &read, (uint8_t*)&csw); - - uint8_t ret = HandleUsbError(epDataInIndex); - - if (ret) - { - ErrorMessage(PSTR("CSW"), ret); - return ret; - } - //if (csw.bCSWStatus == MASS_ERR_PHASE_ERROR) - // bLastUsbError = ResetRecovery(); - - return csw.bCSWStatus; - } - //return MASS_ERR_SUCCESS; -} - -void BulkOnly::PrintEndpointDescriptor( const USB_ENDPOINT_DESCRIPTOR* ep_ptr ) -{ - Notify(PSTR("Endpoint descriptor:")); - Notify(PSTR("\r\nLength:\t\t")); - PrintHex(ep_ptr->bLength); - Notify(PSTR("\r\nType:\t\t")); - PrintHex(ep_ptr->bDescriptorType); - Notify(PSTR("\r\nAddress:\t")); - PrintHex(ep_ptr->bEndpointAddress); - Notify(PSTR("\r\nAttributes:\t")); - PrintHex(ep_ptr->bmAttributes); - Notify(PSTR("\r\nMaxPktSize:\t")); - PrintHex(ep_ptr->wMaxPacketSize); - Notify(PSTR("\r\nPoll Intrv:\t")); - PrintHex(ep_ptr->bInterval); - Notify(PSTR("\r\n")); -} +#include "masstorage.h" +const uint8_t BulkOnly::epDataInIndex = 1; +const uint8_t BulkOnly::epDataOutIndex = 2; +const uint8_t BulkOnly::epInterruptInIndex = 3; + +bool BulkOnly::IsValidCSW(CommandStatusWrapper *pcsw, CommandBlockWrapperBase *pcbw) { + if (pcsw->dCSWSignature != MASS_CSW_SIGNATURE) { + Notify(PSTR("CSW:Sig error\r\n"), 0x80); + return false; + } + if (pcsw->dCSWTag != pcbw->dCBWTag) { + Notify(PSTR("CSW:Wrong tag\r\n"), 0x80); + return false; + } + return true; +} + +BulkOnly::BulkOnly(USB *p) : +pUsb(p), +bAddress(0), +bIface(0), +bNumEP(1), +qNextPollTime(0), +bPollEnable(false), +dCBWTag(0), +bLastUsbError(0) { + for (uint8_t i = 0; i < MASS_MAX_ENDPOINTS; i++) { + epInfo[i].epAddr = 0; + epInfo[i].maxPktSize = (i) ? 0 : 8; + epInfo[i].epAttribs = 0; + + if (!i) + epInfo[i].bmNakPower = USB_NAK_MAX_POWER; + } + if (pUsb) + pUsb->RegisterDeviceClass(this); +} + +uint8_t BulkOnly::Init(uint8_t parent, uint8_t port, bool lowspeed) { + + const uint8_t constBufSize = sizeof (USB_DEVICE_DESCRIPTOR); + + uint8_t buf[constBufSize]; + uint8_t rcode; + UsbDevice *p = NULL; + EpInfo *oldep_ptr = NULL; + uint8_t num_of_conf; // number of configurations + + for (uint8_t i = 0; i < MASS_MAX_ENDPOINTS; i++) { + epInfo[i].epAddr = 0; + epInfo[i].maxPktSize = (i) ? 0 : 8; + epInfo[i].epAttribs = 0; + + if (!i) + epInfo[i].bmNakPower = USB_NAK_MAX_POWER; + } + + AddressPool &addrPool = pUsb->GetAddressPool(); + + + if (bAddress) + return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE; + + USBTRACE("MS Init\r\n"); + // Get pointer to pseudo device with address 0 assigned + p = addrPool.GetUsbDevicePtr(0); + + if (!p) { + return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; + } + + if (!p->epinfo) { + USBTRACE("epinfo\r\n"); + return USB_ERROR_EPINFO_IS_NULL; + } + + // Save old pointer to EP_RECORD of address 0 + oldep_ptr = p->epinfo; + + // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence + p->epinfo = epInfo; + + p->lowspeed = lowspeed; + // Get device descriptor + rcode = pUsb->getDevDescr(0, 0, constBufSize, (uint8_t*) buf); + + // Restore p->epinfo + p->epinfo = oldep_ptr; + + if (rcode) { + goto FailGetDevDescr; + } + // Allocate new address according to device class + bAddress = addrPool.AllocAddress(parent, false, port); + + if (!bAddress) + return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; + + // Extract Max Packet Size from the device descriptor + epInfo[0].maxPktSize = (uint8_t) ((USB_DEVICE_DESCRIPTOR*) buf)->bMaxPacketSize0; + + // Assign new address to the device + rcode = pUsb->setAddr(0, 0, bAddress); + + if (rcode) { + p->lowspeed = false; + addrPool.FreeAddress(bAddress); + bAddress = 0; + USBTRACE2("setAddr:", rcode); + return rcode; + } + + USBTRACE2("Addr:", bAddress); + + p->lowspeed = false; + + p = addrPool.GetUsbDevicePtr(bAddress); + + if (!p) + return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; + + p->lowspeed = lowspeed; + + num_of_conf = ((USB_DEVICE_DESCRIPTOR*) buf)->bNumConfigurations; + + // Assign epInfo to epinfo pointer + rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); + + if (rcode) + goto FailSetDevTblEntry; + + USBTRACE2("NC:", num_of_conf); + + for (uint8_t i = 0; i < num_of_conf; i++) { + ConfigDescParser< USB_CLASS_MASS_STORAGE, + MASS_SUBCLASS_SCSI, + MASS_PROTO_BBB, + CP_MASK_COMPARE_CLASS | + CP_MASK_COMPARE_SUBCLASS | + CP_MASK_COMPARE_PROTOCOL > BulkOnlyParser(this); + + rcode = pUsb->getConfDescr(bAddress, 0, i, &BulkOnlyParser); + + if (rcode) + goto FailGetConfDescr; + + if (bNumEP > 1) + break; + } // for + + if (bNumEP < 3) + return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; + + // Assign epInfo to epinfo pointer + rcode = pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo); + + USBTRACE2("Conf:", bConfNum); + + // Set Configuration Value + rcode = pUsb->setConf(bAddress, 0, bConfNum); + + if (rcode) + goto FailSetConf; + + delay(10000); + + rcode = GetMaxLUN(&bMaxLUN); + if (rcode) + goto FailGetMaxLUN; + + ErrorMessage (PSTR("MaxLUN"), bMaxLUN); + + delay(10); + + bTheLUN = bMaxLUN; + + //if (bMaxLUN > 0) + { + for (uint8_t lun = 0; lun <= bMaxLUN; lun++) { + ErrorMessage (PSTR("\r\nLUN"), lun); + Notify(PSTR("--------\r\n"), 0x80); + + uint8_t count = 0; + + MediaCTL(lun, 0x01); + while (rcode = TestUnitReady(lun)) { + if (rcode == MASS_ERR_NO_MEDIA) + break; + + if (rcode == MASS_ERR_DEVICE_DISCONNECTED) + goto Fail; + + if (!count) + Notify(PSTR("Not ready...\r\n"), 0x80); + + if (count == 0xff) + break; + + delay(100); + count++; + } + if (count == 0xff) + continue; + + rcode = 0; + InquiryResponse response; + rcode = Inquiry(lun, sizeof (InquiryResponse), (uint8_t*) & response); + + if (rcode) + ErrorMessage (PSTR("Inquiry"), rcode); + + rcode = 0; + Capacity capacity; + rcode = ReadCapacity(lun, sizeof (Capacity), (uint8_t*) & capacity); + + if (rcode) + ErrorMessage (PSTR("ReadCapacity"), rcode); + else { + for (uint8_t i = 0; i (capacity.data[i], 0x80); + Notify(PSTR("\r\n\r\n"), 0x80); + // Only 512/1024/2048/4096 are valid values! + uint32_t c = ((uint32_t) capacity.data[4] << 24) + ((uint32_t) capacity.data[5] << 16) + ((uint32_t) capacity.data[6] << 8) + (uint32_t) capacity.data[7]; + if (c != 0x0200LU && c != 0x0400LU && c != 0x0800LU && c != 0x1000LU) { + rcode = 255; + goto FailInvalidSectorSize; + } + } + + rcode = 0; +#if 0 + { + uint8_t buf[512]; + rcode = Read(lun, 0, 512, 1, buf); + + if (rcode) + ErrorMessage (PSTR("Read"), rcode); + else { + Notify(PSTR("Read: OK\r\n\r\n"), 0x80); + /* + for(int i=0; i<512; i++) { + PrintHex(buf[i], 0x80); + Notify(PSTR(" "), 0x80); + } + Notify(PSTR("\r\n\r\n"), 0x80); + */ + } + } + { + uint8_t buf[192]; + rcode = ModeSense(lun, 0, 0x3f, 0, 192, buf); + + if (rcode) + ErrorMessage (PSTR("ModeSense"), rcode); + else + Notify(PSTR("ModeSense: OK\r\n\r\n"), 0x80); + } +#endif + } + Notify(PSTR("==========\r\n"), 0x80); + } + + if (TestUnitReady(bTheLUN)) { + Notify(PSTR("Unit not ready\r\n"), 0x80); + + rcode = MASS_ERR_UNIT_NOT_READY; + //goto FailOnInit; + } + + rcode = OnInit(); + + if (rcode) + goto FailOnInit; + + USBTRACE("MS configured\r\n\r\n"); + + bPollEnable = true; + + //USBTRACE("Poll enabled\r\n"); + return 0; + +FailGetDevDescr: + USBTRACE("getDevDescr:"); + goto Fail; + +FailSetDevTblEntry: + USBTRACE("setDevTblEn:"); + goto Fail; + +FailGetConfDescr: + USBTRACE("getConf:"); + goto Fail; + +FailSetConf: + USBTRACE("setConf:"); + goto Fail; + +FailOnInit: + USBTRACE("OnInit:"); + goto Fail; + +FailGetMaxLUN: + USBTRACE("GetMaxLUN:"); + goto Fail; + +FailInquiry: + USBTRACE("Inquiry:"); + goto Fail; + +FailReadCapacity: + USBTRACE("ReadCapacity:"); + goto Fail; + +FailInvalidSectorSize: + USBTRACE("Sector Size is NOT VALID: "); + goto Fail; + +FailRead0: + USBTRACE("Read0:"); + goto Fail; + +FailModeSense0: + USBTRACE("ModeSense0:"); + goto Fail; + +FailModeSense1: + USBTRACE("ModeSense1:"); + goto Fail; + +Fail: + PrintHex (rcode, 0x80); + Notify(PSTR("\r\n"), 0x80); + //Serial.println(rcode, HEX); + Release(); + return rcode; +} + +void BulkOnly::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *pep) { + ErrorMessage (PSTR("Conf.Val"), conf); + ErrorMessage (PSTR("Iface Num"), iface); + ErrorMessage (PSTR("Alt.Set"), alt); + + bConfNum = conf; + + uint8_t index; + + if ((pep->bmAttributes & 0x03) == 3 && (pep->bEndpointAddress & 0x80) == 0x80) + index = epInterruptInIndex; + else + if ((pep->bmAttributes & 0x02) == 2) + index = ((pep->bEndpointAddress & 0x80) == 0x80) ? epDataInIndex : epDataOutIndex; + else + return; + + // Fill in the endpoint info structure + epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F); + epInfo[index].maxPktSize = (uint8_t) pep->wMaxPacketSize; + epInfo[index].epAttribs = 0; + + bNumEP++; + + PrintEndpointDescriptor(pep); +} + +uint8_t BulkOnly::Release() { + pUsb->GetAddressPool().FreeAddress(bAddress); + + bIface = 0; + bNumEP = 1; + + bAddress = 0; + qNextPollTime = 0; + bPollEnable = false; + bLastUsbError = 0; + bMaxLUN = 0; + bTheLUN = 0; + dCBWTag = 0; + return 0; +} + +uint8_t BulkOnly::Poll() { + uint8_t rcode = 0; + + if (!bPollEnable) + return 0; + + return rcode; +} + +uint8_t BulkOnly::Reset() { + return ( pUsb->ctrlReq(bAddress, 0, bmREQ_MASSOUT, MASS_REQ_BOMSR, 0, 0, bIface, 0, 0, NULL, NULL)); +} + +uint8_t BulkOnly::GetMaxLUN(uint8_t *plun) { + uint8_t ret = pUsb->ctrlReq(bAddress, 0, bmREQ_MASSIN, MASS_REQ_GET_MAX_LUN, 0, 0, bIface, 1, 1, plun, NULL); + + if (ret == hrSTALL) + *plun = 0; + + return 0; +} + +uint8_t BulkOnly::HandleUsbError(uint8_t error, uint8_t index) { + uint8_t count = 3; + + bLastUsbError = error; + + while (error && count) { + if (error != hrSUCCESS) { + ErrorMessage (PSTR("USB Error"), error); + ErrorMessage (PSTR("Index"), index); + } + switch (error) { + case hrSUCCESS: return MASS_ERR_SUCCESS; + case hrBUSY: return MASS_ERR_UNIT_BUSY; + case hrTIMEOUT: + case hrJERR: return MASS_ERR_DEVICE_DISCONNECTED; + case hrSTALL: + if (index == 0) + return MASS_ERR_SUCCESS; + + error = ClearEpHalt(index); + //return MASS_ERR_STALL; + return MASS_ERR_SUCCESS; + + //error = ClearEpHalt(index); + //break; + case hrTOGERR: + if (bAddress && bConfNum) { + error = pUsb->setConf(bAddress, 0, bConfNum); + + if (error) + break; + } + return MASS_ERR_SUCCESS; + default: + ErrorMessage (PSTR("\r\nUSB"), error); + return MASS_ERR_GENERAL_USB_ERROR; + } + count--; + } // while + + return ((error && !count) ? MASS_ERR_GENERAL_USB_ERROR : MASS_ERR_SUCCESS); +} + +uint8_t BulkOnly::ClearEpHalt(uint8_t index) { + if (index == 0) + return 0; + + uint8_t ret = 0; + + ret = (pUsb->ctrlReq(bAddress, 0, USB_SETUP_HOST_TO_DEVICE | USB_SETUP_TYPE_STANDARD | USB_SETUP_RECIPIENT_ENDPOINT, + USB_REQUEST_CLEAR_FEATURE, USB_FEATURE_ENDPOINT_HALT, 0, ((index == epDataInIndex) ? (0x80 | epInfo[index].epAddr) : epInfo[index].epAddr), 0, 0, NULL, NULL)); + + ////ret = (pUsb->ctrlReq(bAddress, 0, USB_SETUP_HOST_TO_DEVICE|USB_SETUP_RECIPIENT_ENDPOINT|USB_SETUP_TYPE_STANDARD, + ////USB_REQUEST_CLEAR_FEATURE, USB_FEATURE_ENDPOINT_HALT, 0, epInfo[index].epAddr, 0, 0, NULL, NULL)); + //// + if (ret) { + ErrorMessage (PSTR("ClearEpHalt"), ret); + ErrorMessage (PSTR("EP"), ((index == epDataInIndex) ? (0x80 | epInfo[index].epAddr) : epInfo[index].epAddr)); + return ret; + } + epInfo[index].epAttribs = 0; + return 0; +} + +uint8_t BulkOnly::ResetRecovery() { + Notify(PSTR("\r\nResetRecovery\r\n"), 0x80); + Notify(PSTR("-----------------\r\n"), 0x80); + + bLastUsbError = Reset(); + + if (bLastUsbError) { + return bLastUsbError; + } + delay(6); + + bLastUsbError = ClearEpHalt(epDataInIndex); + + if (bLastUsbError) { + return bLastUsbError; + } + delay(6); + + bLastUsbError = ClearEpHalt(epDataOutIndex); + + delay(6); + + return bLastUsbError; +} + +uint8_t BulkOnly::Inquiry(uint8_t lun, uint16_t bsize, uint8_t *buf) { + Notify(PSTR("\r\nInquiry\r\n"), 0x80); + Notify(PSTR("---------\r\n"), 0x80); + + CommandBlockWrapper cbw; + + cbw.dCBWSignature = MASS_CBW_SIGNATURE; + cbw.dCBWTag = ++dCBWTag; + cbw.dCBWDataTransferLength = bsize; + cbw.bmCBWFlags = MASS_CMD_DIR_IN, + cbw.bmCBWLUN = lun; + cbw.bmCBWCBLength = 6; + + for (uint8_t i = 0; i < 16; i++) + cbw.CBWCB[i] = 0; + + cbw.CBWCB[0] = SCSI_CMD_INQUIRY; + cbw.CBWCB[4] = bsize; + + return HandleSCSIError(Transaction(&cbw, bsize, buf, 0)); +} + +uint8_t BulkOnly::RequestSense(uint8_t lun, uint16_t size, uint8_t *buf) { + Notify(PSTR("\r\nRequestSense\r\n"), 0x80); + Notify(PSTR("----------------\r\n"), 0x80); + + CommandBlockWrapper cbw; + + cbw.dCBWSignature = MASS_CBW_SIGNATURE; + cbw.dCBWTag = ++dCBWTag; + cbw.dCBWDataTransferLength = size; + cbw.bmCBWFlags = MASS_CMD_DIR_IN, + cbw.bmCBWLUN = lun; + cbw.bmCBWCBLength = 6; + + for (uint8_t i = 0; i < 16; i++) + cbw.CBWCB[i] = 0; + + cbw.CBWCB[0] = SCSI_CMD_REQUEST_SENSE; + cbw.CBWCB[4] = size; + + return HandleSCSIError(Transaction(&cbw, size, buf, 0)); +} + +uint8_t BulkOnly::ReadCapacity(uint8_t lun, uint16_t bsize, uint8_t *buf) { + Notify(PSTR("\r\nReadCapacity\r\n"), 0x80); + Notify(PSTR("---------------\r\n"), 0x80); + + CommandBlockWrapper cbw; + + cbw.dCBWSignature = MASS_CBW_SIGNATURE; + cbw.dCBWTag = ++dCBWTag; + cbw.dCBWDataTransferLength = bsize; + cbw.bmCBWFlags = MASS_CMD_DIR_IN, + cbw.bmCBWLUN = lun; + cbw.bmCBWCBLength = 10; + + for (uint8_t i = 0; i < 16; i++) + cbw.CBWCB[i] = 0; + + cbw.CBWCB[0] = SCSI_CMD_READ_CAPACITY_10; + //cbw.CBWCB[4] = bsize; + + return HandleSCSIError(Transaction(&cbw, bsize, buf, 0)); +} + +uint8_t BulkOnly::TestUnitReady(uint8_t lun) { + if (!bAddress) // || !bPollEnable) + return MASS_ERR_UNIT_NOT_READY; + + Notify(PSTR("\r\nTestUnitReady\r\n"), 0x80); + Notify(PSTR("-----------------\r\n"), 0x80); + + CommandBlockWrapper cbw; + + cbw.dCBWSignature = MASS_CBW_SIGNATURE; + cbw.dCBWTag = ++dCBWTag; + cbw.dCBWDataTransferLength = 0; + cbw.bmCBWFlags = MASS_CMD_DIR_OUT, + cbw.bmCBWLUN = lun; + cbw.bmCBWCBLength = 6; + + for (uint8_t i = 0; i < 16; i++) + cbw.CBWCB[i] = 0; + + cbw.CBWCB[0] = SCSI_CMD_TEST_UNIT_READY; + + return HandleSCSIError(Transaction(&cbw, 0, NULL, 0)); +} + +/* Media control: 0x00 Stop Motor, 0x01 Start Motor, 0x02 Eject Media, 0x03 Load Media */ +uint8_t BulkOnly::MediaCTL(uint8_t lun, uint8_t ctl) { + uint8_t rcode = MASS_ERR_UNIT_NOT_READY; + if (bAddress) { + CommandBlockWrapper cbw; + + cbw.dCBWSignature = MASS_CBW_SIGNATURE; + cbw.dCBWTag = ++dCBWTag; + cbw.dCBWDataTransferLength = 0; + cbw.bmCBWFlags = MASS_CMD_DIR_OUT, + cbw.bmCBWLUN = lun; + cbw.bmCBWCBLength = 6; + + for (uint8_t i = 0; i < 16; i++) + cbw.CBWCB[i] = 0; + + cbw.CBWCB[0] = SCSI_CMD_START_STOP_UNIT; + cbw.CBWCB[4] = ctl & 0x03; + + rcode = HandleSCSIError(Transaction(&cbw, 0, NULL, 0)); + } + return rcode; +} + +uint8_t BulkOnly::Read(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, uint8_t *buf) { + Notify(PSTR("\r\nRead\r\n"), 0x80); + Notify(PSTR("---------\r\n"), 0x80); + + CommandBlockWrapper cbw; + + cbw.dCBWSignature = MASS_CBW_SIGNATURE; + cbw.dCBWTag = ++dCBWTag; + cbw.dCBWDataTransferLength = ((uint32_t) bsize * blocks); + cbw.bmCBWFlags = MASS_CMD_DIR_IN, + cbw.bmCBWLUN = lun; + cbw.bmCBWCBLength = 10; + + for (uint8_t i = 0; i < 16; i++) + cbw.CBWCB[i] = 0; + + cbw.CBWCB[0] = SCSI_CMD_READ_10; + cbw.CBWCB[8] = blocks; + cbw.CBWCB[2] = ((addr >> 24) & 0xff); + cbw.CBWCB[3] = ((addr >> 16) & 0xff); + cbw.CBWCB[4] = ((addr >> 8) & 0xff); + cbw.CBWCB[5] = (addr & 0xff); + return HandleSCSIError(Transaction(&cbw, bsize, buf, 0)); +} + +/* We won't be needing this... */ +uint8_t BulkOnly::Read(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, USBReadParser *prs) { +#if 0 + Notify(PSTR("\r\nRead (With parser)\r\n"), 0x80); + Notify(PSTR("---------\r\n"), 0x80); + + CommandBlockWrapper cbw; + + cbw.dCBWSignature = MASS_CBW_SIGNATURE; + cbw.dCBWTag = ++dCBWTag; + cbw.dCBWDataTransferLength = ((uint32_t) bsize * blocks); + cbw.bmCBWFlags = MASS_CMD_DIR_IN, + cbw.bmCBWLUN = lun; + cbw.bmCBWCBLength = 10; + + for (uint8_t i = 0; i < 16; i++) + cbw.CBWCB[i] = 0; + + cbw.CBWCB[0] = SCSI_CMD_READ_10; + cbw.CBWCB[8] = blocks; + cbw.CBWCB[2] = ((addr >> 24) & 0xff); + cbw.CBWCB[3] = ((addr >> 16) & 0xff); + cbw.CBWCB[4] = ((addr >> 8) & 0xff); + cbw.CBWCB[5] = (addr & 0xff); + + return HandleSCSIError(Transaction(&cbw, bsize, prs, 1)); +#endif +} + +uint8_t BulkOnly::Write(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, const uint8_t *buf) { + Notify(PSTR("\r\nWrite\r\n"), 0x80); + Notify(PSTR("---------\r\n"), 0x80); + + //MediaCTL(lun, 0x01); + CommandBlockWrapper cbw; + + cbw.dCBWSignature = MASS_CBW_SIGNATURE; + cbw.dCBWTag = ++dCBWTag; + cbw.dCBWDataTransferLength = ((uint32_t) bsize * blocks); + cbw.bmCBWFlags = MASS_CMD_DIR_OUT, + cbw.bmCBWLUN = lun; + cbw.bmCBWCBLength = 10; + + for (uint8_t i = 0; i < 16; i++) + cbw.CBWCB[i] = 0; + + cbw.CBWCB[0] = SCSI_CMD_WRITE_10; + cbw.CBWCB[8] = 1; + cbw.CBWCB[5] = (addr & 0xff); + cbw.CBWCB[4] = ((addr >> 8) & 0xff); + cbw.CBWCB[3] = ((addr >> 16) & 0xff); + cbw.CBWCB[2] = ((addr >> 24) & 0xff); + + return HandleSCSIError(Transaction(&cbw, bsize, (void*) buf, 0)); +} + +uint8_t BulkOnly::ModeSense(uint8_t lun, uint8_t pc, uint8_t page, uint8_t subpage, uint8_t len, uint8_t *pbuf) { + Notify(PSTR("\r\rModeSense\r\n"), 0x80); + Notify(PSTR("------------\r\n"), 0x80); + + CommandBlockWrapper cbw; + + cbw.dCBWSignature = MASS_CBW_SIGNATURE; + cbw.dCBWTag = ++dCBWTag; + cbw.dCBWDataTransferLength = len; + cbw.bmCBWFlags = MASS_CMD_DIR_IN, + cbw.bmCBWLUN = lun; + cbw.bmCBWCBLength = 6; + + for (uint8_t i = 0; i < 16; i++) + cbw.CBWCB[i] = 0; + + cbw.CBWCB[0] = SCSI_CMD_MODE_SENSE_6; + cbw.CBWCB[2] = ((pc << 6) | page); + cbw.CBWCB[3] = subpage; + cbw.CBWCB[4] = len; + + return HandleSCSIError(Transaction(&cbw, 512, pbuf, 0)); +} + +uint8_t BulkOnly::Transaction(CommandBlockWrapper *pcbw, uint16_t buf_size, void *buf, uint8_t flags) { + uint16_t read; + uint8_t ret = 0; + + ErrorMessage (PSTR("CBW.dCBWTag"), pcbw->dCBWTag); + + ret = HandleUsbError(pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, sizeof (CommandBlockWrapper), (uint8_t*) pcbw), epDataOutIndex); + + if (ret) { + ErrorMessage (PSTR("CBW"), ret); + return ret; + } + Notify(PSTR("CBW:\t\tOK\r\n"), 0x80); + + ret = 0; + + read = (pcbw->dCBWDataTransferLength > buf_size) ? buf_size : pcbw->dCBWDataTransferLength; + + if (read) { + if (pcbw->bmCBWFlags & MASS_CMD_DIR_IN) { + if ((flags & MASS_TRANS_FLG_CALLBACK) == MASS_TRANS_FLG_CALLBACK) { + uint8_t rbuf[read]; + uint8_t err = 0; + ret = pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, &read, rbuf); + if (ret == hrSUCCESS) ((USBReadParser*) buf)->Parse(read, rbuf, 0); + if (ret == hrSTALL) err = ClearEpHalt(epDataInIndex); + if (ret) { + ErrorMessage (PSTR("RDR"), err); + return MASS_ERR_GENERAL_USB_ERROR; + } + } else + ret = pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, &read, (uint8_t*) buf); + } else + ret = pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, read, (uint8_t*) buf); + + ret = HandleUsbError(ret, (pcbw->bmCBWFlags & MASS_CMD_DIR_IN) ? epDataInIndex : epDataOutIndex); + + if (ret) { + ErrorMessage (PSTR("DAT"), ret); + return MASS_ERR_GENERAL_USB_ERROR; + } + + Notify(PSTR("Data Stage:\tOK\r\n"), 0x80); + } + + uint8_t count = 2; + + while (count) { + CommandStatusWrapper csw; + read = sizeof (CommandStatusWrapper); + + ret = HandleUsbError(pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, &read, (uint8_t*) & csw), epDataInIndex); + + if (ret) { + ErrorMessage (PSTR("CSW"), ret); + count--; + continue; //return ret; + } + if (IsValidCSW(&csw, pcbw)) { + ErrorMessage (PSTR("CSW.dCBWTag"), csw.dCSWTag); + ErrorMessage (PSTR("bCSWStatus"), csw.bCSWStatus); + ErrorMessage (PSTR("dCSWDataResidue"), csw.dCSWDataResidue); + Notify(PSTR("CSW:\t\tOK\r\n\r\n"), 0x80); + return csw.bCSWStatus; + } else { + Notify(PSTR("Invalid CSW\r\n"), 0x80); + ResetRecovery(); + return MASS_ERR_SUCCESS; //MASS_ERR_INVALID_CSW; + } + count--; + } + if (count) + ResetRecovery(); + + return MASS_ERR_SUCCESS; +} + +uint8_t BulkOnly::SetCurLUN(uint8_t lun) { + if (lun > bMaxLUN) + return MASS_ERR_INVALID_LUN; + + bTheLUN = lun; + return MASS_ERR_SUCCESS; +}; + +uint8_t BulkOnly::HandleSCSIError(uint8_t status) { + uint8_t ret = 0; + + switch (status) { + case 0: return MASS_ERR_SUCCESS; + //case 4: return MASS_ERR_UNIT_BUSY; + case 2: + ErrorMessage (PSTR("Phase"), status); + ResetRecovery(); + return MASS_ERR_GENERAL_SCSI_ERROR; + case 1: + ErrorMessage (PSTR("SCSI Error"), status); + RequestSenseResponce rsp; + + ret = RequestSense(bTheLUN, sizeof (RequestSenseResponce), (uint8_t*) & rsp); + + if (ret) + return MASS_ERR_GENERAL_SCSI_ERROR; + + ErrorMessage (PSTR("Response Code"), rsp.bResponseCode); + ErrorMessage (PSTR("Sense Key"), rsp.bmSenseKey); + ErrorMessage (PSTR("Add Sense Code"), rsp.bAdditionalSenseCode); + ErrorMessage (PSTR("Add Sense Qual"), rsp.bAdditionalSenseQualifier); + switch (rsp.bmSenseKey) { + case 0: + return MASS_ERR_SUCCESS; + case SCSI_S_NOT_READY: + switch (rsp.bAdditionalSenseCode) { + case SCSI_ASC_MEDIUM_NOT_PRESENT: + return MASS_ERR_NO_MEDIA; + default: + return MASS_ERR_UNIT_NOT_READY; + } + case SCSI_S_ILLEGAL_REQUEST: + switch (rsp.bAdditionalSenseCode) { + case SCSI_ASC_LBA_OUT_OF_RANGE: + return MASS_ERR_BAD_LBA; + default: + return MASS_ERR_CMD_NOT_SUPPORTED; + } + default: return MASS_ERR_GENERAL_SCSI_ERROR; + } + + default: + Reset(); + ErrorMessage (PSTR("Gen SCSI Err"), status); + return status; //MASS_ERR_GENERAL_SCSI_ERROR; + } // switch +} + +void BulkOnly::PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr) { + Notify(PSTR("Endpoint descriptor:"), 0x80); + Notify(PSTR("\r\nLength:\t\t"), 0x80); + PrintHex (ep_ptr->bLength, 0x80); + Notify(PSTR("\r\nType:\t\t"), 0x80); + PrintHex (ep_ptr->bDescriptorType, 0x80); + Notify(PSTR("\r\nAddress:\t"), 0x80); + PrintHex (ep_ptr->bEndpointAddress, 0x80); + Notify(PSTR("\r\nAttributes:\t"), 0x80); + PrintHex (ep_ptr->bmAttributes, 0x80); + Notify(PSTR("\r\nMaxPktSize:\t"), 0x80); + PrintHex (ep_ptr->wMaxPacketSize, 0x80); + Notify(PSTR("\r\nPoll Intrv:\t"), 0x80); + PrintHex (ep_ptr->bInterval, 0x80); + Notify(PSTR("\r\n"), 0x80); +} diff --git a/masstorage.h b/masstorage.h index e856cb70..de16d12b 100644 --- a/masstorage.h +++ b/masstorage.h @@ -1,252 +1,276 @@ -#if !defined(__MASSTORAGE_H__) -#define __MASSTORAGE_H__ - -#include -#include -#include "avrpins.h" -#include "max3421e.h" -#include "usbhost.h" -#include "usb_ch9.h" -#include "Usb.h" - -#if defined(ARDUINO) && ARDUINO >=100 -#include "Arduino.h" -#else -#include -#endif - -#include "printhex.h" -#include "hexdump.h" -#include "message.h" - -#include "confdescparser.h" - -#define SWAP(a, b) (((a) ^= (b)), ((b) ^= (a)), ((a) ^= (b))) - -#define bmREQ_MASSOUT USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE -#define bmREQ_MASSIN USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE - -// Mass Storage Subclass Constants -#define MASS_SUBCLASS_SCSI_NOT_REPORTED 0x00 // De facto use -#define MASS_SUBCLASS_RBC 0x01 -#define MASS_SUBCLASS_ATAPI 0x02 // MMC-5 (ATAPI) -#define MASS_SUBCLASS_OBSOLETE1 0x03 // Was QIC-157 -#define MASS_SUBCLASS_UFI 0x04 // Specifies how to interface Floppy Disk Drives to USB -#define MASS_SUBCLASS_OBSOLETE2 0x05 // Was SFF-8070i -#define MASS_SUBCLASS_SCSI 0x06 // SCSI Transparent Command Set -#define MASS_SUBCLASS_LSDFS 0x07 // Specifies how host has to negotiate access before trying SCSI -#define MASS_SUBCLASS_IEEE1667 0x08 - -// Mass Storage Class Protocols -#define MASS_PROTO_CBI 0x00 // CBI (with command completion interrupt) -#define MASS_PROTO_CBI_NO_INT 0x01 // CBI (without command completion interrupt) -#define MASS_PROTO_OBSOLETE 0x02 -#define MASS_PROTO_BBB 0x50 // Bulk Only Transport -#define MASS_PROTO_UAS 0x62 - -// Request Codes -#define MASS_REQ_ADSC 0x00 -#define MASS_REQ_GET 0xFC -#define MASS_REQ_PUT 0xFD -#define MASS_REQ_GET_MAX_LUN 0xFE -#define MASS_REQ_BOMSR 0xFF // Bulk-Only Mass Storage Reset - -#define MASS_CBW_SIGNATURE 0x43425355 -#define MASS_CSW_SIGNATURE 0x53425355 - -#define MASS_CMD_DIR_OUT (0 << 7) -#define MASS_CMD_DIR_IN (1 << 7) - -#define SCSI_CMD_INQUIRY 0x12 -#define SCSI_CMD_REPORT_LUNS 0xA0 -#define SCSI_CMD_REQUEST_SENSE 0x03 -#define SCSI_CMD_FORMAT_UNIT 0x04 -#define SCSI_CMD_READ_6 0x08 -#define SCSI_CMD_READ_10 0x28 -#define SCSI_CMD_READ_CAPACITY_10 0x25 -#define SCSI_CMD_TEST_UNIT_READY 0x00 -#define SCSI_CMD_WRITE_6 0x0A -#define SCSI_CMD_WRITE_10 0x2A -#define SCSI_CMD_MODE_SENSE_6 0x1A -#define SCSI_CMD_MODE_SENSE_10 0x5A - -#define MASS_ERR_SUCCESS 0x00 -#define MASS_ERR_PHASE_ERROR 0x01 -#define MASS_ERR_DEVICE_DISCONNECTED 0x11 -#define MASS_ERR_UNABLE_TO_RECOVER 0x12 // Reset recovery error -#define MASS_ERR_GENERAL_USB_ERROR 0xFF - -#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_PHASE_CHECK 0x04 // PHASE_ERROR is not checked - - -struct Capacity -{ - uint8_t data[8]; - //uint32_t dwBlockAddress; - //uint32_t dwBlockLength; -}; - -struct InquiryResponse -{ - uint8_t DeviceType : 5; - uint8_t PeripheralQualifier : 3; - - unsigned Reserved : 7; - unsigned Removable : 1; - - uint8_t Version; - - unsigned ResponseDataFormat : 4; - unsigned Reserved2 : 1; - unsigned NormACA : 1; - unsigned TrmTsk : 1; - unsigned AERC : 1; - - uint8_t AdditionalLength; - uint8_t Reserved3[2]; - - unsigned SoftReset : 1; - unsigned CmdQue : 1; - unsigned Reserved4 : 1; - unsigned Linked : 1; - unsigned Sync : 1; - unsigned WideBus16Bit : 1; - unsigned WideBus32Bit : 1; - unsigned RelAddr : 1; - - uint8_t VendorID[8]; - uint8_t ProductID[16]; - uint8_t RevisionID[4]; -}; - -struct CommandBlockWrapper -{ - uint32_t dCBWSignature; - uint32_t dCBWTag; - uint32_t dCBWDataTransferLength; - uint8_t bmCBWFlags; - - struct - { - uint8_t bmCBWLUN : 4; - uint8_t bmReserved1 : 4; - }; - struct - { - uint8_t bmCBWCBLength : 4; - uint8_t bmReserved2 : 4; - }; - - uint8_t CBWCB[16]; -} ; - -struct CommandStatusWrapper -{ - uint32_t dCSWSignature; - uint32_t dCSWTag; - uint32_t dCSWDataResidue; - uint8_t bCSWStatus; -}; - -struct RequestSenseResponce -{ - uint8_t bResponseCode; - uint8_t bSegmentNumber; - - uint8_t bmSenseKey : 4; - uint8_t bmReserved : 1; - uint8_t bmILI : 1; - uint8_t bmEOM : 1; - uint8_t bmFileMark : 1; - - uint8_t Information[4]; - uint8_t bAdditionalLength; - uint8_t CmdSpecificInformation[4]; - uint8_t bAdditionalSenseCode; - uint8_t bAdditionalSenseQualifier; - uint8_t bFieldReplaceableUnitCode; - uint8_t SenseKeySpecific[3]; -}; - -//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 - -class BulkOnly : public USBDeviceConfig, public UsbConfigXtracter -{ -protected: - static const uint8_t epDataInIndex; // DataIn endpoint index - static const uint8_t epDataOutIndex; // DataOUT endpoint index - static const uint8_t epInterruptInIndex; // InterruptIN endpoint index - - USB *pUsb; - uint8_t bAddress; - uint8_t bConfNum; // configuration number - uint8_t bIface; // interface value - uint8_t bNumEP; // total number of EP in the configuration - uint32_t qNextPollTime; // next poll time - bool bPollEnable; // poll enable flag - - EpInfo epInfo[MASS_MAX_ENDPOINTS]; - - uint32_t dCBWTag; // Tag - uint32_t dCBWDataTransferLength; // Data Transfer Length - uint8_t bMaxLUN; // Max LUN - uint8_t bLastUsbError; // Last USB error - -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); - - bool IsValidCBW(uint8_t size, uint8_t *pcbw); - bool IsMeaningfulCBW(uint8_t size, uint8_t *pcbw); - - uint8_t ClearEpHalt(uint8_t index); - uint8_t Transaction(CommandBlockWrapper *cbw, uint16_t bsize, void *buf, uint8_t flags); - uint8_t HandleUsbError(uint8_t index); - -public: - BulkOnly(USB *p); - uint8_t GetLastUsbError() { return bLastUsbError; }; - - uint8_t Reset(); - uint8_t GetMaxLUN(uint8_t *max_lun); - - uint8_t ResetRecovery(); - uint8_t Inquiry(uint8_t lun, uint16_t size, uint8_t *buf); - uint8_t TestUnitReady(uint8_t lun); - 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 Read(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t *buf); - uint8_t Read(uint8_t lun, uint32_t addr, uint16_t bsize, USBReadParser *prs); - - // USBDeviceConfig implementation - virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed); - virtual uint8_t Release(); - virtual uint8_t Poll(); - virtual uint8_t GetAddress() { return bAddress; }; - - // UsbConfigXtracter implementation - virtual void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep); -}; - -#endif // __MASSTORAGE_H__ \ No newline at end of file +#if !defined(__MASSTORAGE_H__) +#define __MASSTORAGE_H__ + +#include +#include "avrpins.h" +#include +#include "max3421e.h" +#include "usbhost.h" +#include "usb_ch9.h" +#include "Usb.h" + +#if defined(ARDUINO) && ARDUINO >=100 +#include "Arduino.h" +#else +#include +#endif + +#include "printhex.h" +#include "hexdump.h" +#include "message.h" + +#include + +#define SWAP(a, b) (((a) ^= (b)), ((b) ^= (a)), ((a) ^= (b))) + +#define bmREQ_MASSOUT USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE +#define bmREQ_MASSIN USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE + +// Mass Storage Subclass Constants +#define MASS_SUBCLASS_SCSI_NOT_REPORTED 0x00 // De facto use +#define MASS_SUBCLASS_RBC 0x01 +#define MASS_SUBCLASS_ATAPI 0x02 // MMC-5 (ATAPI) +#define MASS_SUBCLASS_OBSOLETE1 0x03 // Was QIC-157 +#define MASS_SUBCLASS_UFI 0x04 // Specifies how to interface Floppy Disk Drives to USB +#define MASS_SUBCLASS_OBSOLETE2 0x05 // Was SFF-8070i +#define MASS_SUBCLASS_SCSI 0x06 // SCSI Transparent Command Set +#define MASS_SUBCLASS_LSDFS 0x07 // Specifies how host has to negotiate access before trying SCSI +#define MASS_SUBCLASS_IEEE1667 0x08 + +// Mass Storage Class Protocols +#define MASS_PROTO_CBI 0x00 // CBI (with command completion interrupt) +#define MASS_PROTO_CBI_NO_INT 0x01 // CBI (without command completion interrupt) +#define MASS_PROTO_OBSOLETE 0x02 +#define MASS_PROTO_BBB 0x50 // Bulk Only Transport +#define MASS_PROTO_UAS 0x62 + +// Request Codes +#define MASS_REQ_ADSC 0x00 +#define MASS_REQ_GET 0xFC +#define MASS_REQ_PUT 0xFD +#define MASS_REQ_GET_MAX_LUN 0xFE +#define MASS_REQ_BOMSR 0xFF // Bulk-Only Mass Storage Reset + +#define MASS_CBW_SIGNATURE 0x43425355 +#define MASS_CSW_SIGNATURE 0x53425355 + +#define MASS_CMD_DIR_OUT (0 << 7) +#define MASS_CMD_DIR_IN (1 << 7) + +#define SCSI_CMD_INQUIRY 0x12 +#define SCSI_CMD_REPORT_LUNS 0xA0 +#define SCSI_CMD_REQUEST_SENSE 0x03 +#define SCSI_CMD_FORMAT_UNIT 0x04 +#define SCSI_CMD_READ_6 0x08 +#define SCSI_CMD_READ_10 0x28 +#define SCSI_CMD_READ_CAPACITY_10 0x25 +#define SCSI_CMD_TEST_UNIT_READY 0x00 +#define SCSI_CMD_WRITE_6 0x0A +#define SCSI_CMD_WRITE_10 0x2A +#define SCSI_CMD_MODE_SENSE_6 0x1A +#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_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_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_USER 0xA0 // For subclasses to define their own error codes + +#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_PHASE_CHECK 0x04 // PHASE_ERROR is not checked + +struct Capacity { + uint8_t data[8]; + //uint32_t dwBlockAddress; + //uint32_t dwBlockLength; +}__attribute__((packed)); + +struct InquiryResponse { + uint8_t DeviceType : 5; + uint8_t PeripheralQualifier : 3; + + unsigned Reserved : 7; + unsigned Removable : 1; + + uint8_t Version; + + unsigned ResponseDataFormat : 4; + unsigned Reserved2 : 1; + unsigned NormACA : 1; + unsigned TrmTsk : 1; + unsigned AERC : 1; + + uint8_t AdditionalLength; + uint8_t Reserved3[2]; + + unsigned SoftReset : 1; + unsigned CmdQue : 1; + unsigned Reserved4 : 1; + unsigned Linked : 1; + unsigned Sync : 1; + unsigned WideBus16Bit : 1; + unsigned WideBus32Bit : 1; + unsigned RelAddr : 1; + + uint8_t VendorID[8]; + uint8_t ProductID[16]; + uint8_t RevisionID[4]; +}__attribute__((packed)); + +struct CommandBlockWrapperBase { + uint32_t dCBWSignature; + uint32_t dCBWTag; + uint32_t dCBWDataTransferLength; + uint8_t bmCBWFlags; +}__attribute__((packed)); + +struct CommandBlockWrapper : public CommandBlockWrapperBase { + + struct { + uint8_t bmCBWLUN : 4; + uint8_t bmReserved1 : 4; + }; + + struct { + uint8_t bmCBWCBLength : 4; + uint8_t bmReserved2 : 4; + }; + + uint8_t CBWCB[16]; +}__attribute__((packed)); + +struct CommandStatusWrapper { + uint32_t dCSWSignature; + uint32_t dCSWTag; + uint32_t dCSWDataResidue; + uint8_t bCSWStatus; +}__attribute__((packed)); + +struct RequestSenseResponce { + uint8_t bResponseCode; + uint8_t bSegmentNumber; + + uint8_t bmSenseKey : 4; + uint8_t bmReserved : 1; + uint8_t bmILI : 1; + uint8_t bmEOM : 1; + uint8_t bmFileMark : 1; + + uint8_t Information[4]; + uint8_t bAdditionalLength; + uint8_t CmdSpecificInformation[4]; + uint8_t bAdditionalSenseCode; + uint8_t bAdditionalSenseQualifier; + uint8_t bFieldReplaceableUnitCode; + uint8_t SenseKeySpecific[3]; +}__attribute__((packed)); + +#define MASS_MAX_ENDPOINTS 3 + +class BulkOnly : public USBDeviceConfig, public UsbConfigXtracter { +protected: + static const uint8_t epDataInIndex; // DataIn endpoint index + static const uint8_t epDataOutIndex; // DataOUT endpoint index + static const uint8_t epInterruptInIndex; // InterruptIN endpoint index + + USB *pUsb; + uint8_t bAddress; + uint8_t bConfNum; // configuration number + uint8_t bIface; // interface value + uint8_t bNumEP; // total number of EP in the configuration + uint32_t qNextPollTime; // next poll time + bool bPollEnable; // poll enable flag + + EpInfo epInfo[MASS_MAX_ENDPOINTS]; + + uint32_t dCBWTag; // Tag + uint32_t dCBWDataTransferLength; // Data Transfer Length + uint8_t bLastUsbError; // Last USB error + uint8_t bMaxLUN; // Max LUN + uint8_t bTheLUN; // Active LUN + +protected: + void PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr); + + bool IsValidCBW(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 Transaction(CommandBlockWrapper *cbw, uint16_t bsize, void *buf, uint8_t flags); + uint8_t HandleUsbError(uint8_t error, uint8_t index); + uint8_t HandleSCSIError(uint8_t status); + +public: + BulkOnly(USB *p); + + uint8_t GetLastUsbError() { + return bLastUsbError; + }; + + uint8_t GetbMaxLUN() { + return bMaxLUN; // Max LUN + } + + uint8_t GetbTheLUN() { + return bTheLUN; // Active LUN + } + + uint8_t Reset(); + uint8_t GetMaxLUN(uint8_t *max_lun); + uint8_t SetCurLUN(uint8_t lun); + + uint8_t ResetRecovery(); + uint8_t Inquiry(uint8_t lun, uint16_t size, uint8_t *buf); + uint8_t TestUnitReady(uint8_t lun); + 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 ModeSense(uint8_t lun, uint8_t pc, uint8_t page, uint8_t subpage, uint8_t len, uint8_t *buf); + 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 + virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed); + virtual uint8_t Release(); + virtual uint8_t Poll(); + + virtual uint8_t GetAddress() { + return bAddress; + }; + + // UsbConfigXtracter implementation + virtual void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep); + +protected: + // Additional Initialization Method for Subclasses + + virtual uint8_t OnInit() { + return 0; + }; +}; + +#endif // __MASSTORAGE_H__ diff --git a/max3421e.h b/max3421e.h index cab2359c..9fdff593 100644 --- a/max3421e.h +++ b/max3421e.h @@ -13,7 +13,7 @@ Contact information Circuits At Home, LTD Web : http://www.circuitsathome.com e-mail : support@circuitsathome.com -*/ + */ /* MAX3421E register/bit names and bitmasks */ #ifndef _max3421e_h_ @@ -37,7 +37,7 @@ e-mail : support@circuitsathome.com /* MAX3421E command byte format: rrrrr0wa where 'r' is register number */ // -// MAX3421E Registers in HOST mode. +// MAX3421E Registers in HOST mode. // #define rRCVFIFO 0x08 //1<<3 #define rSNDFIFO 0x10 //2<<3 @@ -141,7 +141,7 @@ e-mail : support@circuitsathome.com #define rHIRQ 0xc8 //25<<3 /* HIRQ Bits */ -#define bmBUSEVENTIRQ 0x01 // indicates BUS Reset Done or BUS Resume +#define bmBUSEVENTIRQ 0x01 // indicates BUS Reset Done or BUS Resume #define bmRWUIRQ 0x02 #define bmRCVDAVIRQ 0x04 #define bmSNDBAVIRQ 0x08 @@ -194,7 +194,7 @@ e-mail : support@circuitsathome.com #define tokIN 0x00 // HS=0, ISO=0, OUTNIN=0, SETUP=0 #define tokOUT 0x20 // HS=0, ISO=0, OUTNIN=1, SETUP=0 #define tokINHS 0x80 // HS=1, ISO=0, OUTNIN=0, SETUP=0 -#define tokOUTHS 0xA0 // HS=1, ISO=0, OUTNIN=1, SETUP=0 +#define tokOUTHS 0xA0 // HS=1, ISO=0, OUTNIN=1, SETUP=0 #define tokISOIN 0x40 // HS=0, ISO=1, OUTNIN=0, SETUP=0 #define tokISOOUT 0x60 // HS=0, ISO=1, OUTNIN=1, SETUP=0 @@ -206,7 +206,7 @@ e-mail : support@circuitsathome.com #define bmKSTATUS 0x40 #define bmJSTATUS 0x80 #define bmSE0 0x00 //SE0 - disconnect state -#define bmSE1 0xc0 //SE1 - illegal state +#define bmSE1 0xc0 //SE1 - illegal state /* Host error result codes, the 4 LSB's in the HRSL register */ #define hrSUCCESS 0x00 diff --git a/max_LCD.cpp b/max_LCD.cpp index 307f6409..1ea842d1 100644 --- a/max_LCD.cpp +++ b/max_LCD.cpp @@ -1,250 +1,256 @@ -/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. - -This software may be distributed and modified under the terms of the GNU -General Public License version 2 (GPL2) as published by the Free Software -Foundation and appearing in the file GPL2.TXT included in the packaging of -this file. Please note that GPL2 Section 2[b] requires that all works based -on this software must also be made publicly available under the terms of -the GPL2 ("Copyleft"). - -Contact information -------------------- - -Circuits At Home, LTD -Web : http://www.circuitsathome.com -e-mail : support@circuitsathome.com -*/ -#include "max_LCD.h" -#include "max3421e.h" - -#include -#include -#include - -#if defined(ARDUINO) && ARDUINO >=100 -#include "Arduino.h" -#else -#include -#endif - -// pin definition and set/clear - -#define RS 0x04 // RS pin -#define E 0x08 // E pin - -#define SET_RS lcdPins |= RS -#define CLR_RS lcdPins &= ~RS -#define SET_E lcdPins |= E -#define CLR_E lcdPins &= ~E - -#define SENDlcdPins() pUsb->gpioWr( lcdPins ) - -#define LCD_sendcmd(a) { CLR_RS; \ - sendbyte(a); \ - } - -#define LCD_sendchar(a) { SET_RS; \ - sendbyte(a); \ - } - -static byte lcdPins; //copy of LCD pins - -Max_LCD::Max_LCD(USB *pusb) : pUsb(pusb) -{ - lcdPins = 0; -} - - -void Max_LCD::init() -{ - _displayfunction = LCD_4BITMODE | LCD_1LINE | LCD_5x8DOTS; - - // MAX3421E::gpioWr(0x55); - - begin(16, 1); -} - -void Max_LCD::begin(uint8_t cols, uint8_t lines, uint8_t dotsize) { - if (lines > 1) { - _displayfunction |= LCD_2LINE; - } - _numlines = lines; - _currline = 0; - - // for some 1 line displays you can select a 10 pixel high font - if ((dotsize != 0) && (lines == 1)) { - _displayfunction |= LCD_5x10DOTS; - } - - // SEE PAGE 45/46 FOR INITIALIZATION SPECIFICATION! - // according to datasheet, we need at least 40ms after power rises above 2.7V - // before sending commands. Arduino can turn on way befer 4.5V so we'll wait 50 - delayMicroseconds(50000); - lcdPins = 0x30; - SET_E; - SENDlcdPins(); - CLR_E; - SENDlcdPins(); - delayMicroseconds(10000); // wait min 4.1ms - //second try - SET_E; - SENDlcdPins(); - CLR_E; - SENDlcdPins(); - delayMicroseconds(10000); // wait min 4.1ms - // third go! - SET_E; - SENDlcdPins(); - CLR_E; - SENDlcdPins(); - delayMicroseconds(10000); - // finally, set to 4-bit interface - lcdPins = 0x20; - //SET_RS; - SET_E; - SENDlcdPins(); - //CLR_RS; - CLR_E; - SENDlcdPins(); - delayMicroseconds(10000); - // finally, set # lines, font size, etc. - command(LCD_FUNCTIONSET | _displayfunction); - - // turn the display on with no cursor or blinking default - _displaycontrol = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF; - display(); - - // clear it off - clear(); - - // Initialize to default text direction (for romance languages) - _displaymode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT; - // set the entry mode - command(LCD_ENTRYMODESET | _displaymode); -} - -/********** high level commands, for the user! */ -void Max_LCD::clear() -{ - command(LCD_CLEARDISPLAY); // clear display, set cursor position to zero - delayMicroseconds(2000); // this command takes a long time! -} - -void Max_LCD::home() -{ - command(LCD_RETURNHOME); // set cursor position to zero - delayMicroseconds(2000); // this command takes a long time! -} - -void Max_LCD::setCursor(uint8_t col, uint8_t row) -{ - int row_offsets[] = { 0x00, 0x40, 0x14, 0x54 }; - if ( row > _numlines ) { - row = _numlines-1; // we count rows starting w/0 - } - - command(LCD_SETDDRAMADDR | (col + row_offsets[row])); -} - -// Turn the display on/off (quickly) -void Max_LCD::noDisplay() { - _displaycontrol &= ~LCD_DISPLAYON; - command(LCD_DISPLAYCONTROL | _displaycontrol); -} -void Max_LCD::display() { - _displaycontrol |= LCD_DISPLAYON; - command(LCD_DISPLAYCONTROL | _displaycontrol); -} - -// Turns the underline cursor on/off -void Max_LCD::noCursor() { - _displaycontrol &= ~LCD_CURSORON; - command(LCD_DISPLAYCONTROL | _displaycontrol); -} -void Max_LCD::cursor() { - _displaycontrol |= LCD_CURSORON; - command(LCD_DISPLAYCONTROL | _displaycontrol); -} - - -// Turn on and off the blinking cursor -void Max_LCD::noBlink() { - _displaycontrol &= ~LCD_BLINKON; - command(LCD_DISPLAYCONTROL | _displaycontrol); -} -void Max_LCD::blink() { - _displaycontrol |= LCD_BLINKON; - command(LCD_DISPLAYCONTROL | _displaycontrol); -} - -// These commands scroll the display without changing the RAM -void Max_LCD::scrollDisplayLeft(void) { - command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVELEFT); -} -void Max_LCD::scrollDisplayRight(void) { - command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVERIGHT); -} - -// This is for text that flows Left to Right -void Max_LCD::leftToRight(void) { - _displaymode |= LCD_ENTRYLEFT; - command(LCD_ENTRYMODESET | _displaymode); -} - -// This is for text that flows Right to Left -void Max_LCD::rightToLeft(void) { - _displaymode &= ~LCD_ENTRYLEFT; - command(LCD_ENTRYMODESET | _displaymode); -} - -// This will 'right justify' text from the cursor -void Max_LCD::autoscroll(void) { - _displaymode |= LCD_ENTRYSHIFTINCREMENT; - command(LCD_ENTRYMODESET | _displaymode); -} - -// This will 'left justify' text from the cursor -void Max_LCD::noAutoscroll(void) { - _displaymode &= ~LCD_ENTRYSHIFTINCREMENT; - command(LCD_ENTRYMODESET | _displaymode); -} - -// Allows us to fill the first 8 CGRAM locations -// with custom characters -void Max_LCD::createChar(uint8_t location, uint8_t charmap[]) { - location &= 0x7; // we only have 8 locations 0-7 - command(LCD_SETCGRAMADDR | (location << 3)); - for (int i=0; i<8; i++) { - write(charmap[i]); - } -} - -/*********** mid level commands, for sending data/cmds */ - -inline void Max_LCD::command(uint8_t value) { - LCD_sendcmd(value); - delayMicroseconds(100); -} - -inline void Max_LCD::write(uint8_t value) { - LCD_sendchar(value); -} - -void Max_LCD::sendbyte( uint8_t val ) -{ - lcdPins &= 0x0f; //prepare place for the upper nibble - lcdPins |= ( val & 0xf0 ); //copy upper nibble to LCD variable - SET_E; //send - SENDlcdPins(); - delayMicroseconds(2); - CLR_E; - delayMicroseconds(2); - SENDlcdPins(); - lcdPins &= 0x0f; //prepare place for the lower nibble - lcdPins |= ( val << 4 ) & 0xf0; //copy lower nibble to LCD variable - SET_E; //send - SENDlcdPins(); - CLR_E; - SENDlcdPins(); - delayMicroseconds(100); -} +/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. + +This software may be distributed and modified under the terms of the GNU +General Public License version 2 (GPL2) as published by the Free Software +Foundation and appearing in the file GPL2.TXT included in the packaging of +this file. Please note that GPL2 Section 2[b] requires that all works based +on this software must also be made publicly available under the terms of +the GPL2 ("Copyleft"). + +Contact information +------------------- + +Circuits At Home, LTD +Web : http://www.circuitsathome.com +e-mail : support@circuitsathome.com + */ +#include "max_LCD.h" +#include "max3421e.h" + +#include +#include +#include + +#if defined(ARDUINO) && ARDUINO >=100 +#include "Arduino.h" +#else +#include +#endif + +// pin definition and set/clear + +#define RS 0x04 // RS pin +#define E 0x08 // E pin + +#define SET_RS lcdPins |= RS +#define CLR_RS lcdPins &= ~RS +#define SET_E lcdPins |= E +#define CLR_E lcdPins &= ~E + +#define SENDlcdPins() pUsb->gpioWr( lcdPins ) + +#define LCD_sendcmd(a) { CLR_RS; \ + sendbyte(a); \ + } + +#define LCD_sendchar(a) { SET_RS; \ + sendbyte(a); \ + } + +static byte lcdPins; //copy of LCD pins + +Max_LCD::Max_LCD(USB *pusb) : pUsb(pusb) { + lcdPins = 0; +} + +void Max_LCD::init() { + _displayfunction = LCD_4BITMODE | LCD_1LINE | LCD_5x8DOTS; + + // MAX3421E::gpioWr(0x55); + + begin(16, 1); +} + +void Max_LCD::begin(uint8_t cols, uint8_t lines, uint8_t dotsize) { + if (lines > 1) { + _displayfunction |= LCD_2LINE; + } + _numlines = lines; + _currline = 0; + + // for some 1 line displays you can select a 10 pixel high font + if ((dotsize != 0) && (lines == 1)) { + _displayfunction |= LCD_5x10DOTS; + } + + // SEE PAGE 45/46 FOR INITIALIZATION SPECIFICATION! + // according to datasheet, we need at least 40ms after power rises above 2.7V + // before sending commands. Arduino can turn on way befer 4.5V so we'll wait 50 + delayMicroseconds(50000); + lcdPins = 0x30; + SET_E; + SENDlcdPins(); + CLR_E; + SENDlcdPins(); + delayMicroseconds(10000); // wait min 4.1ms + //second try + SET_E; + SENDlcdPins(); + CLR_E; + SENDlcdPins(); + delayMicroseconds(10000); // wait min 4.1ms + // third go! + SET_E; + SENDlcdPins(); + CLR_E; + SENDlcdPins(); + delayMicroseconds(10000); + // finally, set to 4-bit interface + lcdPins = 0x20; + //SET_RS; + SET_E; + SENDlcdPins(); + //CLR_RS; + CLR_E; + SENDlcdPins(); + delayMicroseconds(10000); + // finally, set # lines, font size, etc. + command(LCD_FUNCTIONSET | _displayfunction); + + // turn the display on with no cursor or blinking default + _displaycontrol = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF; + display(); + + // clear it off + clear(); + + // Initialize to default text direction (for romance languages) + _displaymode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT; + // set the entry mode + command(LCD_ENTRYMODESET | _displaymode); +} + +/********** high level commands, for the user! */ +void Max_LCD::clear() { + command(LCD_CLEARDISPLAY); // clear display, set cursor position to zero + delayMicroseconds(2000); // this command takes a long time! +} + +void Max_LCD::home() { + command(LCD_RETURNHOME); // set cursor position to zero + delayMicroseconds(2000); // this command takes a long time! +} + +void Max_LCD::setCursor(uint8_t col, uint8_t row) { + int row_offsets[] = {0x00, 0x40, 0x14, 0x54}; + if (row > _numlines) { + row = _numlines - 1; // we count rows starting w/0 + } + + command(LCD_SETDDRAMADDR | (col + row_offsets[row])); +} + +// Turn the display on/off (quickly) + +void Max_LCD::noDisplay() { + _displaycontrol &= ~LCD_DISPLAYON; + command(LCD_DISPLAYCONTROL | _displaycontrol); +} + +void Max_LCD::display() { + _displaycontrol |= LCD_DISPLAYON; + command(LCD_DISPLAYCONTROL | _displaycontrol); +} + +// Turns the underline cursor on/off + +void Max_LCD::noCursor() { + _displaycontrol &= ~LCD_CURSORON; + command(LCD_DISPLAYCONTROL | _displaycontrol); +} + +void Max_LCD::cursor() { + _displaycontrol |= LCD_CURSORON; + command(LCD_DISPLAYCONTROL | _displaycontrol); +} + + +// Turn on and off the blinking cursor + +void Max_LCD::noBlink() { + _displaycontrol &= ~LCD_BLINKON; + command(LCD_DISPLAYCONTROL | _displaycontrol); +} + +void Max_LCD::blink() { + _displaycontrol |= LCD_BLINKON; + command(LCD_DISPLAYCONTROL | _displaycontrol); +} + +// These commands scroll the display without changing the RAM + +void Max_LCD::scrollDisplayLeft(void) { + command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVELEFT); +} + +void Max_LCD::scrollDisplayRight(void) { + command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVERIGHT); +} + +// This is for text that flows Left to Right + +void Max_LCD::leftToRight(void) { + _displaymode |= LCD_ENTRYLEFT; + command(LCD_ENTRYMODESET | _displaymode); +} + +// This is for text that flows Right to Left + +void Max_LCD::rightToLeft(void) { + _displaymode &= ~LCD_ENTRYLEFT; + command(LCD_ENTRYMODESET | _displaymode); +} + +// This will 'right justify' text from the cursor + +void Max_LCD::autoscroll(void) { + _displaymode |= LCD_ENTRYSHIFTINCREMENT; + command(LCD_ENTRYMODESET | _displaymode); +} + +// This will 'left justify' text from the cursor + +void Max_LCD::noAutoscroll(void) { + _displaymode &= ~LCD_ENTRYSHIFTINCREMENT; + command(LCD_ENTRYMODESET | _displaymode); +} + +// Allows us to fill the first 8 CGRAM locations +// with custom characters + +void Max_LCD::createChar(uint8_t location, uint8_t charmap[]) { + location &= 0x7; // we only have 8 locations 0-7 + command(LCD_SETCGRAMADDR | (location << 3)); + for (int i = 0; i < 8; i++) { + write(charmap[i]); + } +} + +/*********** mid level commands, for sending data/cmds */ + +inline void Max_LCD::command(uint8_t value) { + LCD_sendcmd(value); + delayMicroseconds(100); +} + +inline void Max_LCD::write(uint8_t value) { + LCD_sendchar(value); +} + +void Max_LCD::sendbyte(uint8_t val) { + lcdPins &= 0x0f; //prepare place for the upper nibble + lcdPins |= (val & 0xf0); //copy upper nibble to LCD variable + SET_E; //send + SENDlcdPins(); + delayMicroseconds(2); + CLR_E; + delayMicroseconds(2); + SENDlcdPins(); + lcdPins &= 0x0f; //prepare place for the lower nibble + lcdPins |= (val << 4) & 0xf0; //copy lower nibble to LCD variable + SET_E; //send + SENDlcdPins(); + CLR_E; + SENDlcdPins(); + delayMicroseconds(100); +} diff --git a/max_LCD.h b/max_LCD.h index c42d78e3..1cce6fc5 100644 --- a/max_LCD.h +++ b/max_LCD.h @@ -1,102 +1,102 @@ -/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. - -This software may be distributed and modified under the terms of the GNU -General Public License version 2 (GPL2) as published by the Free Software -Foundation and appearing in the file GPL2.TXT included in the packaging of -this file. Please note that GPL2 Section 2[b] requires that all works based -on this software must also be made publicly available under the terms of -the GPL2 ("Copyleft"). - -Contact information -------------------- - -Circuits At Home, LTD -Web : http://www.circuitsathome.com -e-mail : support@circuitsathome.com -*/ -//HD44780 compatible LCD display via MAX3421E GPOUT support header -//pinout: D[4-7] -> GPOUT[4-7], RS-> GPOUT[2], E ->GPOUT[3] -// - -#ifndef _Max_LCD_h_ -#define _Max_LCD_h_ - -#include -#include "Print.h" -#include "Usb.h" - -// commands -#define LCD_CLEARDISPLAY 0x01 -#define LCD_RETURNHOME 0x02 -#define LCD_ENTRYMODESET 0x04 -#define LCD_DISPLAYCONTROL 0x08 -#define LCD_CURSORSHIFT 0x10 -#define LCD_FUNCTIONSET 0x20 -#define LCD_SETCGRAMADDR 0x40 -#define LCD_SETDDRAMADDR 0x80 - -// flags for display entry mode -#define LCD_ENTRYRIGHT 0x00 -#define LCD_ENTRYLEFT 0x02 -#define LCD_ENTRYSHIFTINCREMENT 0x01 -#define LCD_ENTRYSHIFTDECREMENT 0x00 - -// flags for display on/off control -#define LCD_DISPLAYON 0x04 -#define LCD_DISPLAYOFF 0x00 -#define LCD_CURSORON 0x02 -#define LCD_CURSOROFF 0x00 -#define LCD_BLINKON 0x01 -#define LCD_BLINKOFF 0x00 - -// flags for display/cursor shift -#define LCD_DISPLAYMOVE 0x08 -#define LCD_CURSORMOVE 0x00 -#define LCD_MOVERIGHT 0x04 -#define LCD_MOVELEFT 0x00 - -// flags for function set -#define LCD_8BITMODE 0x10 -#define LCD_4BITMODE 0x00 -#define LCD_2LINE 0x08 -#define LCD_1LINE 0x00 -#define LCD_5x10DOTS 0x04 -#define LCD_5x8DOTS 0x00 - -class Max_LCD //: public Print -{ - USB *pUsb; - -public: - Max_LCD(USB *pusb); - void init(); - void begin(uint8_t cols, uint8_t rows, uint8_t charsize = LCD_5x8DOTS); - void clear(); - void home(); - void noDisplay(); - void display(); - void noBlink(); - void blink(); - void noCursor(); - void cursor(); - void scrollDisplayLeft(); - void scrollDisplayRight(); - void leftToRight(); - void rightToLeft(); - void autoscroll(); - void noAutoscroll(); - void createChar(uint8_t, uint8_t[]); - void setCursor(uint8_t, uint8_t); - virtual void write(uint8_t); - void command(uint8_t); - -private: - void sendbyte( uint8_t val ); - uint8_t _displayfunction; //tokill - uint8_t _displaycontrol; - uint8_t _displaymode; - uint8_t _initialized; - uint8_t _numlines,_currline; -}; - +/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. + +This software may be distributed and modified under the terms of the GNU +General Public License version 2 (GPL2) as published by the Free Software +Foundation and appearing in the file GPL2.TXT included in the packaging of +this file. Please note that GPL2 Section 2[b] requires that all works based +on this software must also be made publicly available under the terms of +the GPL2 ("Copyleft"). + +Contact information +------------------- + +Circuits At Home, LTD +Web : http://www.circuitsathome.com +e-mail : support@circuitsathome.com + */ +//HD44780 compatible LCD display via MAX3421E GPOUT support header +//pinout: D[4-7] -> GPOUT[4-7], RS-> GPOUT[2], E ->GPOUT[3] +// + +#ifndef _Max_LCD_h_ +#define _Max_LCD_h_ + +#include +#include "Print.h" +#include "Usb.h" + +// commands +#define LCD_CLEARDISPLAY 0x01 +#define LCD_RETURNHOME 0x02 +#define LCD_ENTRYMODESET 0x04 +#define LCD_DISPLAYCONTROL 0x08 +#define LCD_CURSORSHIFT 0x10 +#define LCD_FUNCTIONSET 0x20 +#define LCD_SETCGRAMADDR 0x40 +#define LCD_SETDDRAMADDR 0x80 + +// flags for display entry mode +#define LCD_ENTRYRIGHT 0x00 +#define LCD_ENTRYLEFT 0x02 +#define LCD_ENTRYSHIFTINCREMENT 0x01 +#define LCD_ENTRYSHIFTDECREMENT 0x00 + +// flags for display on/off control +#define LCD_DISPLAYON 0x04 +#define LCD_DISPLAYOFF 0x00 +#define LCD_CURSORON 0x02 +#define LCD_CURSOROFF 0x00 +#define LCD_BLINKON 0x01 +#define LCD_BLINKOFF 0x00 + +// flags for display/cursor shift +#define LCD_DISPLAYMOVE 0x08 +#define LCD_CURSORMOVE 0x00 +#define LCD_MOVERIGHT 0x04 +#define LCD_MOVELEFT 0x00 + +// flags for function set +#define LCD_8BITMODE 0x10 +#define LCD_4BITMODE 0x00 +#define LCD_2LINE 0x08 +#define LCD_1LINE 0x00 +#define LCD_5x10DOTS 0x04 +#define LCD_5x8DOTS 0x00 + +class Max_LCD //: public Print +{ + USB *pUsb; + +public: + Max_LCD(USB *pusb); + void init(); + void begin(uint8_t cols, uint8_t rows, uint8_t charsize = LCD_5x8DOTS); + void clear(); + void home(); + void noDisplay(); + void display(); + void noBlink(); + void blink(); + void noCursor(); + void cursor(); + void scrollDisplayLeft(); + void scrollDisplayRight(); + void leftToRight(); + void rightToLeft(); + void autoscroll(); + void noAutoscroll(); + void createChar(uint8_t, uint8_t[]); + void setCursor(uint8_t, uint8_t); + virtual void write(uint8_t); + void command(uint8_t); + +private: + void sendbyte(uint8_t val); + uint8_t _displayfunction; //tokill + uint8_t _displaycontrol; + uint8_t _displaymode; + uint8_t _initialized; + uint8_t _numlines, _currline; +}; + #endif \ No newline at end of file diff --git a/message.cpp b/message.cpp index edb1b5b4..47268b48 100644 --- a/message.cpp +++ b/message.cpp @@ -1,31 +1,47 @@ -/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. - -This software may be distributed and modified under the terms of the GNU -General Public License version 2 (GPL2) as published by the Free Software -Foundation and appearing in the file GPL2.TXT included in the packaging of -this file. Please note that GPL2 Section 2[b] requires that all works based -on this software must also be made publicly available under the terms of -the GPL2 ("Copyleft"). - -Contact information -------------------- - -Circuits At Home, LTD -Web : http://www.circuitsathome.com -e-mail : support@circuitsathome.com -*/ -#include "message.h" - -void Notify(char const * msg) -//void Notify(const char* msg) -{ - if(!msg) return; - char c; - - while((c = pgm_read_byte(msg++))) -#if defined(ARDUINO) && ARDUINO >=100 - Serial.print(c); -#else - Serial.print(c,BYTE); -#endif -} +/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. + +This software may be distributed and modified under the terms of the GNU +General Public License version 2 (GPL2) as published by the Free Software +Foundation and appearing in the file GPL2.TXT included in the packaging of +this file. Please note that GPL2 Section 2[b] requires that all works based +on this software must also be made publicly available under the terms of +the GPL2 ("Copyleft"). + +Contact information +------------------- + +Circuits At Home, LTD +Web : http://www.circuitsathome.com +e-mail : support@circuitsathome.com + */ +#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 Notifyc(char c, int lvl) { + if (UsbDEBUGlvl < lvl) return; +#if defined(ARDUINO) && ARDUINO >=100 + Serial.print(c); +#else + Serial.print(c, BYTE); +#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); +} diff --git a/message.h b/message.h index e276a275..fa339487 100644 --- a/message.h +++ b/message.h @@ -1,37 +1,39 @@ -/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. - -This software may be distributed and modified under the terms of the GNU -General Public License version 2 (GPL2) as published by the Free Software -Foundation and appearing in the file GPL2.TXT included in the packaging of -this file. Please note that GPL2 Section 2[b] requires that all works based -on this software must also be made publicly available under the terms of -the GPL2 ("Copyleft"). - -Contact information -------------------- - -Circuits At Home, LTD -Web : http://www.circuitsathome.com -e-mail : support@circuitsathome.com -*/ -#if !defined(__MESSAGE_H__) -#define __MESSAGE_H__ - -#include -#include -#include "printhex.h" - -void Notify(char const * msg); -//void Notify(const char* msg); - -template -void ErrorMessage(char const * msg, ERROR_TYPE rcode = 0) -{ - Notify(msg); - Notify(PSTR(": ")); - PrintHex(rcode); - Notify(PSTR("\r\n")); -} - - -#endif // __MESSAGE_H__ +/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. + +This software may be distributed and modified under the terms of the GNU +General Public License version 2 (GPL2) as published by the Free Software +Foundation and appearing in the file GPL2.TXT included in the packaging of +this file. Please note that GPL2 Section 2[b] requires that all works based +on this software must also be made publicly available under the terms of +the GPL2 ("Copyleft"). + +Contact information +------------------- + +Circuits At Home, LTD +Web : http://www.circuitsathome.com +e-mail : support@circuitsathome.com + */ +#if !defined(__MESSAGE_H__) +#define __MESSAGE_H__ + +#include +#include + +void Notify(char const * msg, int lvl); +void NotifyStr(char const * msg, int lvl); + +#include "printhex.h" + +//void Notify(const char* msg); + +template +void ErrorMessage(char const * msg, ERROR_TYPE rcode = 0) { + Notify(msg, 0x80); + Notify(PSTR(": "), 0x80); + PrintHex (rcode, 0x80); + Notify(PSTR("\r\n"), 0x80); +} + + +#endif // __MESSAGE_H__ diff --git a/parsetools.cpp b/parsetools.cpp index bbcca772..469c3c8e 100644 --- a/parsetools.cpp +++ b/parsetools.cpp @@ -1,72 +1,67 @@ -/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. - -This software may be distributed and modified under the terms of the GNU -General Public License version 2 (GPL2) as published by the Free Software -Foundation and appearing in the file GPL2.TXT included in the packaging of -this file. Please note that GPL2 Section 2[b] requires that all works based -on this software must also be made publicly available under the terms of -the GPL2 ("Copyleft"). - -Contact information -------------------- - -Circuits At Home, LTD -Web : http://www.circuitsathome.com -e-mail : support@circuitsathome.com -*/ -#include "parsetools.h" - -bool MultiByteValueParser::Parse(uint8_t **pp, uint16_t *pcntdn) -{ - if (!pBuf) - { - Notify(PSTR("Buffer pointer is NULL!\r\n")); - return false; - } - for (; countDown && (*pcntdn); countDown--, (*pcntdn)--, (*pp)++) - pBuf[valueSize-countDown] = (**pp); - - if (countDown) - return false; - - countDown = valueSize; - return true; -} - -bool PTPListParser::Parse(uint8_t **pp, uint16_t *pcntdn, PTP_ARRAY_EL_FUNC pf, const void *me) -{ - switch (nStage) - { - case 0: - pBuf->valueSize = lenSize; - theParser.Initialize(pBuf); - nStage = 1; - - case 1: - if (!theParser.Parse(pp, pcntdn)) - return false; - - arLen = 0; - arLen = (pBuf->valueSize >= 4) ? *((uint32_t*)pBuf->pValue) : (uint32_t)(*((uint16_t*)pBuf->pValue)); - arLenCntdn = arLen; - nStage = 2; - - case 2: - pBuf->valueSize = valSize; - theParser.Initialize(pBuf); - nStage = 3; - - case 3: - for (; arLenCntdn; arLenCntdn--) - { - if (!theParser.Parse(pp, pcntdn)) - return false; - - if (pf) - pf(pBuf, (arLen - arLenCntdn), me); - } - - nStage = 0; - } - return true; -} +/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. + +This software may be distributed and modified under the terms of the GNU +General Public License version 2 (GPL2) as published by the Free Software +Foundation and appearing in the file GPL2.TXT included in the packaging of +this file. Please note that GPL2 Section 2[b] requires that all works based +on this software must also be made publicly available under the terms of +the GPL2 ("Copyleft"). + +Contact information +------------------- + +Circuits At Home, LTD +Web : http://www.circuitsathome.com +e-mail : support@circuitsathome.com + */ +#include "parsetools.h" + +bool MultiByteValueParser::Parse(uint8_t **pp, uint16_t *pcntdn) { + if (!pBuf) { + Notify(PSTR("Buffer pointer is NULL!\r\n"), 0x80); + return false; + } + for (; countDown && (*pcntdn); countDown--, (*pcntdn)--, (*pp)++) + pBuf[valueSize - countDown] = (**pp); + + if (countDown) + return false; + + countDown = valueSize; + return true; +} + +bool PTPListParser::Parse(uint8_t **pp, uint16_t *pcntdn, PTP_ARRAY_EL_FUNC pf, const void *me) { + switch (nStage) { + case 0: + pBuf->valueSize = lenSize; + theParser.Initialize(pBuf); + nStage = 1; + + case 1: + if (!theParser.Parse(pp, pcntdn)) + return false; + + arLen = 0; + arLen = (pBuf->valueSize >= 4) ? *((uint32_t*) pBuf->pValue) : (uint32_t) (*((uint16_t*) pBuf->pValue)); + arLenCntdn = arLen; + nStage = 2; + + case 2: + pBuf->valueSize = valSize; + theParser.Initialize(pBuf); + nStage = 3; + + case 3: + for (; arLenCntdn; arLenCntdn--) { + if (!theParser.Parse(pp, pcntdn)) + return false; + + if (pf) + pf(pBuf, (arLen - arLenCntdn), me); + } + + nStage = 0; + } + return true; +} diff --git a/parsetools.h b/parsetools.h index d19b8dac..9fc9568c 100644 --- a/parsetools.h +++ b/parsetools.h @@ -1,151 +1,149 @@ -/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. - -This software may be distributed and modified under the terms of the GNU -General Public License version 2 (GPL2) as published by the Free Software -Foundation and appearing in the file GPL2.TXT included in the packaging of -this file. Please note that GPL2 Section 2[b] requires that all works based -on this software must also be made publicly available under the terms of -the GPL2 ("Copyleft"). - -Contact information -------------------- - -Circuits At Home, LTD -Web : http://www.circuitsathome.com -e-mail : support@circuitsathome.com -*/ -#if !defined(__PARSETOOLS_H__) -#define __PARSETOOLS_H__ - -#include -#include -#include "printhex.h" -#include "hexdump.h" -#include "message.h" - -#if defined(ARDUINO) && ARDUINO >=100 -#include "Arduino.h" -#else -#include -#endif - -struct MultiValueBuffer -{ - uint8_t valueSize; - void *pValue; -}; - -class MultiByteValueParser -{ - uint8_t * pBuf; - uint8_t countDown; - uint8_t valueSize; - -public: - MultiByteValueParser() : pBuf(NULL), countDown(0), valueSize(0) {}; - - const uint8_t* GetBuffer() { return pBuf; }; - - void Initialize(MultiValueBuffer * const pbuf) - { - pBuf = (uint8_t*)pbuf->pValue; - countDown = valueSize = pbuf->valueSize; - }; - - bool Parse(uint8_t **pp, uint16_t *pcntdn); -}; - -class ByteSkipper -{ - uint8_t *pBuf; - uint8_t nStage; - uint16_t countDown; - -public: - ByteSkipper() : pBuf(NULL), nStage(0), countDown(0) {}; - - void Initialize(MultiValueBuffer *pbuf) - { - pBuf = (uint8_t*)pbuf->pValue; - countDown = 0; - }; - - bool Skip(uint8_t **pp, uint16_t *pcntdn, uint16_t bytes_to_skip) - { - switch (nStage) - { - case 0: - countDown = bytes_to_skip; - nStage ++; - case 1: - for (; countDown && (*pcntdn); countDown--, (*pp)++, (*pcntdn)--); - - if (!countDown) - nStage = 0; - }; - return (!countDown); - }; -}; - -// 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); - -class PTPListParser -{ -public: - enum ParseMode { modeArray, modeRange/*, modeEnum*/ }; - -private: - uint8_t nStage; - uint8_t enStage; - - uint32_t arLen; - uint32_t arLenCntdn; - - uint8_t lenSize; // size of the array length field in bytes - uint8_t valSize; // size of the array element in bytes - - MultiValueBuffer *pBuf; - - // The only parser for both size and array element parsing - MultiByteValueParser theParser; - - uint8_t /*ParseMode*/ prsMode; - -public: - PTPListParser() : - pBuf(NULL), - nStage(0), - enStage(0), - arLenCntdn(0), - arLen(0), - lenSize(0), - valSize(0), - prsMode(modeArray) - {}; - - void Initialize(const uint8_t len_size, const uint8_t val_size, MultiValueBuffer * const p, const uint8_t mode = modeArray) - { - pBuf = p; - lenSize = len_size; - valSize = val_size; - prsMode = mode; - - if (prsMode == modeRange) - { - arLenCntdn = arLen = 3; - nStage = 2; - } - else - { - arLenCntdn = arLen = 0; - nStage = 0; - } - enStage = 0; - theParser.Initialize(p); - }; - - bool Parse(uint8_t **pp, uint16_t *pcntdn, PTP_ARRAY_EL_FUNC pf, const void *me = NULL); -}; - -#endif // __PARSETOOLS_H__ \ No newline at end of file +/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. + +This software may be distributed and modified under the terms of the GNU +General Public License version 2 (GPL2) as published by the Free Software +Foundation and appearing in the file GPL2.TXT included in the packaging of +this file. Please note that GPL2 Section 2[b] requires that all works based +on this software must also be made publicly available under the terms of +the GPL2 ("Copyleft"). + +Contact information +------------------- + +Circuits At Home, LTD +Web : http://www.circuitsathome.com +e-mail : support@circuitsathome.com + */ +#if !defined(__PARSETOOLS_H__) +#define __PARSETOOLS_H__ + +#include +#include +#include "printhex.h" +#include "hexdump.h" +#include "message.h" + +#if defined(ARDUINO) && ARDUINO >=100 +#include "Arduino.h" +#else +#include +#endif + +struct MultiValueBuffer { + uint8_t valueSize; + void *pValue; +}__attribute__((packed)); + +class MultiByteValueParser { + uint8_t * pBuf; + uint8_t countDown; + uint8_t valueSize; + +public: + + MultiByteValueParser() : pBuf(NULL), countDown(0), valueSize(0) { + }; + + const uint8_t* GetBuffer() { + return pBuf; + }; + + void Initialize(MultiValueBuffer * const pbuf) { + pBuf = (uint8_t*) pbuf->pValue; + countDown = valueSize = pbuf->valueSize; + }; + + bool Parse(uint8_t **pp, uint16_t *pcntdn); +}; + +class ByteSkipper { + uint8_t *pBuf; + uint8_t nStage; + uint16_t countDown; + +public: + + ByteSkipper() : pBuf(NULL), nStage(0), countDown(0) { + }; + + void Initialize(MultiValueBuffer *pbuf) { + pBuf = (uint8_t*) pbuf->pValue; + countDown = 0; + }; + + bool Skip(uint8_t **pp, uint16_t *pcntdn, uint16_t bytes_to_skip) { + switch (nStage) { + case 0: + countDown = bytes_to_skip; + nStage++; + case 1: + for (; countDown && (*pcntdn); countDown--, (*pp)++, (*pcntdn)--); + + if (!countDown) + nStage = 0; + }; + return (!countDown); + }; +}; + +// 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); + +class PTPListParser { +public: + + enum ParseMode { + modeArray, modeRange/*, modeEnum*/ + }; + +private: + uint8_t nStage; + uint8_t enStage; + + uint32_t arLen; + uint32_t arLenCntdn; + + uint8_t lenSize; // size of the array length field in bytes + uint8_t valSize; // size of the array element in bytes + + MultiValueBuffer *pBuf; + + // The only parser for both size and array element parsing + MultiByteValueParser theParser; + + uint8_t /*ParseMode*/ prsMode; + +public: + + PTPListParser() : + nStage(0), + enStage(0), + arLen(0), + arLenCntdn(0), + lenSize(0), + valSize(0), + pBuf(NULL), + prsMode(modeArray) { + }; + + void Initialize(const uint8_t len_size, const uint8_t val_size, MultiValueBuffer * const p, const uint8_t mode = modeArray) { + pBuf = p; + lenSize = len_size; + valSize = val_size; + prsMode = mode; + + if (prsMode == modeRange) { + arLenCntdn = arLen = 3; + nStage = 2; + } else { + arLenCntdn = arLen = 0; + nStage = 0; + } + enStage = 0; + theParser.Initialize(p); + }; + + bool Parse(uint8_t **pp, uint16_t *pcntdn, PTP_ARRAY_EL_FUNC pf, const void *me = NULL); +}; + +#endif // __PARSETOOLS_H__ diff --git a/printhex.h b/printhex.h index 7a3b3d9b..262286c0 100644 --- a/printhex.h +++ b/printhex.h @@ -1,66 +1,71 @@ -/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. - -This software may be distributed and modified under the terms of the GNU -General Public License version 2 (GPL2) as published by the Free Software -Foundation and appearing in the file GPL2.TXT included in the packaging of -this file. Please note that GPL2 Section 2[b] requires that all works based -on this software must also be made publicly available under the terms of -the GPL2 ("Copyleft"). - -Contact information -------------------- - -Circuits At Home, LTD -Web : http://www.circuitsathome.com -e-mail : support@circuitsathome.com -*/ -#if !defined(__PRINTHEX_H__) -#define __PRINTHEX_H__ - -#if defined(ARDUINO) && ARDUINO >=100 -#include "Arduino.h" -#else -#include -#endif - -template -void PrintHex(T val) -{ - T mask = (((T)1) << (((sizeof(T) << 1) - 1) << 2)); - - while (mask > 1) - { - if (val < mask) - Serial.print("0"); - - mask >>= 4; - } - Serial.print((T)val, HEX); -} - -template -void PrintHex2(Print *prn, T val) -{ - T mask = (((T)1) << (((sizeof(T) << 1) - 1) << 2)); - - while (mask > 1) - { - if (val < mask) - prn->print("0"); - - mask >>= 4; - } - prn->print((T)val, HEX); -} - -template -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__ \ No newline at end of file +/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. + +This software may be distributed and modified under the terms of the GNU +General Public License version 2 (GPL2) as published by the Free Software +Foundation and appearing in the file GPL2.TXT included in the packaging of +this file. Please note that GPL2 Section 2[b] requires that all works based +on this software must also be made publicly available under the terms of +the GPL2 ("Copyleft"). + +Contact information +------------------- + +Circuits At Home, LTD +Web : http://www.circuitsathome.com +e-mail : support@circuitsathome.com + */ +#if !defined(__PRINTHEX_H__) +#define __PRINTHEX_H__ + +#if defined(ARDUINO) && ARDUINO >=100 +#include "Arduino.h" +#else +#include +#endif +void Notifyc(char c, int lvl); + +template +void PrintHex(T val, int lvl) { + int num_nibbles = sizeof (T) * 2; + + do { + char v = 48 + (((val >> (num_nibbles - 1) * 4)) & 0x0f); + if (v > 57) v += 7; + Notifyc(v, lvl); + } while (--num_nibbles); +} + +template +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 +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 +void PrintHex2(Print *prn, T val) { + T mask = (((T) 1) << (((sizeof (T) << 1) - 1) << 2)); + + while (mask > 1) { + if (val < mask) + prn->print("0"); + + mask >>= 4; + } + prn->print((T) val, HEX); +} + +#endif // __PRINTHEX_H__ diff --git a/usb_ch9.h b/usb_ch9.h index 12501aff..9a8d3c99 100644 --- a/usb_ch9.h +++ b/usb_ch9.h @@ -13,7 +13,7 @@ Contact information Circuits At Home, LTD Web : http://www.circuitsathome.com e-mail : support@circuitsathome.com -*/ + */ /* USB chapter 9 structures */ #ifndef _ch9_h_ #define _ch9_h_ @@ -94,77 +94,71 @@ e-mail : support@circuitsathome.com /* Device descriptor structure */ typedef struct { - uint8_t bLength; // Length of this descriptor. - uint8_t bDescriptorType; // DEVICE descriptor type (USB_DESCRIPTOR_DEVICE). - uint16_t bcdUSB; // USB Spec Release Number (BCD). - uint8_t bDeviceClass; // Class code (assigned by the USB-IF). 0xFF-Vendor specific. - uint8_t bDeviceSubClass; // Subclass code (assigned by the USB-IF). - uint8_t bDeviceProtocol; // Protocol code (assigned by the USB-IF). 0xFF-Vendor specific. - uint8_t bMaxPacketSize0; // Maximum packet size for endpoint 0. - uint16_t idVendor; // Vendor ID (assigned by the USB-IF). - uint16_t idProduct; // Product ID (assigned by the manufacturer). - uint16_t bcdDevice; // Device release number (BCD). - uint8_t iManufacturer; // Index of String Descriptor describing the manufacturer. - 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 bNumConfigurations; // Number of possible configurations. -} USB_DEVICE_DESCRIPTOR; + uint8_t bLength; // Length of this descriptor. + uint8_t bDescriptorType; // DEVICE descriptor type (USB_DESCRIPTOR_DEVICE). + uint16_t bcdUSB; // USB Spec Release Number (BCD). + uint8_t bDeviceClass; // Class code (assigned by the USB-IF). 0xFF-Vendor specific. + uint8_t bDeviceSubClass; // Subclass code (assigned by the USB-IF). + uint8_t bDeviceProtocol; // Protocol code (assigned by the USB-IF). 0xFF-Vendor specific. + uint8_t bMaxPacketSize0; // Maximum packet size for endpoint 0. + uint16_t idVendor; // Vendor ID (assigned by the USB-IF). + uint16_t idProduct; // Product ID (assigned by the manufacturer). + uint16_t bcdDevice; // Device release number (BCD). + uint8_t iManufacturer; // Index of String Descriptor describing the manufacturer. + 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 bNumConfigurations; // Number of possible configurations. +}__attribute__((packed)) USB_DEVICE_DESCRIPTOR; /* Configuration descriptor structure */ -typedef struct -{ - uint8_t bLength; // Length of this descriptor. - uint8_t bDescriptorType; // CONFIGURATION descriptor type (USB_DESCRIPTOR_CONFIGURATION). - uint16_t wTotalLength; // Total length of all descriptors for this configuration. - uint8_t bNumInterfaces; // Number of interfaces in this configuration. - uint8_t bConfigurationValue; // Value of this configuration (1 based). - uint8_t iConfiguration; // Index of String Descriptor describing the configuration. - uint8_t bmAttributes; // Configuration characteristics. - uint8_t bMaxPower; // Maximum power consumed by this configuration. -} USB_CONFIGURATION_DESCRIPTOR; +typedef struct { + uint8_t bLength; // Length of this descriptor. + uint8_t bDescriptorType; // CONFIGURATION descriptor type (USB_DESCRIPTOR_CONFIGURATION). + uint16_t wTotalLength; // Total length of all descriptors for this configuration. + uint8_t bNumInterfaces; // Number of interfaces in this configuration. + uint8_t bConfigurationValue; // Value of this configuration (1 based). + uint8_t iConfiguration; // Index of String Descriptor describing the configuration. + uint8_t bmAttributes; // Configuration characteristics. + uint8_t bMaxPower; // Maximum power consumed by this configuration. +}__attribute__((packed)) USB_CONFIGURATION_DESCRIPTOR; /* Interface descriptor structure */ -typedef struct -{ - uint8_t bLength; // Length of this descriptor. - uint8_t bDescriptorType; // INTERFACE descriptor type (USB_DESCRIPTOR_INTERFACE). - uint8_t bInterfaceNumber; // Number of this interface (0 based). - uint8_t bAlternateSetting; // Value of this alternate interface setting. - uint8_t bNumEndpoints; // Number of endpoints in this interface. - uint8_t bInterfaceClass; // Class code (assigned by the USB-IF). 0xFF-Vendor specific. - 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 iInterface; // Index of String Descriptor describing the interface. -} USB_INTERFACE_DESCRIPTOR; +typedef struct { + uint8_t bLength; // Length of this descriptor. + uint8_t bDescriptorType; // INTERFACE descriptor type (USB_DESCRIPTOR_INTERFACE). + uint8_t bInterfaceNumber; // Number of this interface (0 based). + uint8_t bAlternateSetting; // Value of this alternate interface setting. + uint8_t bNumEndpoints; // Number of endpoints in this interface. + uint8_t bInterfaceClass; // Class code (assigned by the USB-IF). 0xFF-Vendor specific. + 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 iInterface; // Index of String Descriptor describing the interface. +}__attribute__((packed)) USB_INTERFACE_DESCRIPTOR; /* Endpoint descriptor structure */ -typedef struct -{ - uint8_t bLength; // Length of this descriptor. - uint8_t bDescriptorType; // ENDPOINT descriptor type (USB_DESCRIPTOR_ENDPOINT). - uint8_t bEndpointAddress; // Endpoint address. Bit 7 indicates direction (0=OUT, 1=IN). - uint8_t bmAttributes; // Endpoint transfer type. - uint16_t wMaxPacketSize; // Maximum packet size. - uint8_t bInterval; // Polling interval in frames. -} USB_ENDPOINT_DESCRIPTOR; - +typedef struct { + uint8_t bLength; // Length of this descriptor. + uint8_t bDescriptorType; // ENDPOINT descriptor type (USB_DESCRIPTOR_ENDPOINT). + uint8_t bEndpointAddress; // Endpoint address. Bit 7 indicates direction (0=OUT, 1=IN). + uint8_t bmAttributes; // Endpoint transfer type. + uint16_t wMaxPacketSize; // Maximum packet size. + uint8_t bInterval; // Polling interval in frames. +}__attribute__((packed)) USB_ENDPOINT_DESCRIPTOR; /* HID descriptor */ -typedef struct -{ - uint8_t bLength; - uint8_t bDescriptorType; - uint16_t bcdHID; // HID class specification release - uint8_t bCountryCode; - uint8_t bNumDescriptors; // Number of additional class specific descriptors - uint8_t bDescrType; // Type of class descriptor - uint16_t wDescriptorLength; // Total size of the Report descriptor -} USB_HID_DESCRIPTOR; +typedef struct { + uint8_t bLength; + uint8_t bDescriptorType; + uint16_t bcdHID; // HID class specification release + uint8_t bCountryCode; + uint8_t bNumDescriptors; // Number of additional class specific descriptors + uint8_t bDescrType; // Type of class descriptor + uint16_t wDescriptorLength; // Total size of the Report descriptor +}__attribute__((packed)) USB_HID_DESCRIPTOR; -typedef struct -{ - uint8_t bDescrType; // Type of class descriptor - uint16_t wDescriptorLength; // Total size of the Report descriptor -} HID_CLASS_DESCRIPTOR_LEN_AND_TYPE; +typedef struct { + uint8_t bDescrType; // Type of class descriptor + uint16_t wDescriptorLength; // Total size of the Report descriptor +}__attribute__((packed)) HID_CLASS_DESCRIPTOR_LEN_AND_TYPE; #endif // _ch9_h_ diff --git a/usbhost.h b/usbhost.h index 6efe9793..95b87a48 100644 --- a/usbhost.h +++ b/usbhost.h @@ -13,7 +13,7 @@ Contact information Circuits At Home, LTD Web : http://www.circuitsathome.com e-mail : support@circuitsathome.com -*/ + */ /* MAX3421E-based USB Host Library header file */ #ifndef _USBHOST_H_ #define _USBHOST_H_ @@ -22,25 +22,24 @@ e-mail : support@circuitsathome.com #include "max3421e.h" #include "usb_ch9.h" - /* SPI initialization */ -template< typename CLK, typename MOSI, typename MISO, typename SPI_SS > class SPi -{ - public: - static void init() { - uint8_t tmp; - CLK::SetDirWrite(); - MOSI::SetDirWrite(); - MISO::SetDirRead(); - SPI_SS::SetDirWrite(); - /* mode 00 (CPOL=0, CPHA=0) master, fclk/2. Mode 11 (CPOL=11, CPHA=11) is also supported by MAX3421E */ - SPCR = 0x50; - SPSR = 0x01; - /**/ - tmp = SPSR; - tmp = SPDR; - } -}; +template< typename CLK, typename MOSI, typename MISO, typename SPI_SS > class SPi { +public: + + static void init() { + //uint8_t tmp; + CLK::SetDirWrite(); + MOSI::SetDirWrite(); + MISO::SetDirRead(); + SPI_SS::SetDirWrite(); + /* mode 00 (CPOL=0, CPHA=0) master, fclk/2. Mode 11 (CPOL=11, CPHA=11) is also supported by MAX3421E */ + SPCR = 0x50; + SPSR = 0x01; + /**/ + //tmp = SPSR; + //tmp = SPDR; + } +}; /* SPI pin definitions. see avrpins.h */ #if defined(__AVR_ATmega1280__) || (__AVR_ATmega2560__) || defined(__AVR_ATmega32U4__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__) @@ -53,143 +52,138 @@ typedef SPi< Pb5, Pb3, Pb4, Pb2 > spi; typedef SPi< Pb7, Pb5, Pb6, Pb4 > spi; #endif -template< typename SS, typename INTR > class MAX3421e /* : public spi */ -{ - static uint8_t vbusState; +template< typename SS, typename INTR > class MAX3421e /* : public spi */ { + static uint8_t vbusState; - public: - MAX3421e(); - void regWr( uint8_t reg, uint8_t data ); - uint8_t* bytesWr( uint8_t reg, uint8_t nbytes, uint8_t* data_p ); - void gpioWr( uint8_t data ); - uint8_t regRd( uint8_t reg ); - uint8_t* bytesRd( uint8_t reg, uint8_t nbytes, uint8_t* data_p ); - uint8_t gpioRd(); - uint16_t reset(); - int8_t Init(); - uint8_t getVbusState( void ) { return vbusState; }; - void busprobe(); - uint8_t GpxHandler(); - uint8_t IntHandler(); - uint8_t Task(); +public: + MAX3421e(); + void regWr(uint8_t reg, uint8_t data); + uint8_t* bytesWr(uint8_t reg, uint8_t nbytes, uint8_t* data_p); + void gpioWr(uint8_t data); + uint8_t regRd(uint8_t reg); + uint8_t* bytesRd(uint8_t reg, uint8_t nbytes, uint8_t* data_p); + uint8_t gpioRd(); + uint16_t reset(); + int8_t Init(); + + uint8_t getVbusState(void) { + return vbusState; + }; + void busprobe(); + uint8_t GpxHandler(); + uint8_t IntHandler(); + uint8_t Task(); }; template< typename SS, typename INTR > -uint8_t MAX3421e< SS, INTR >::vbusState = 0; + uint8_t MAX3421e< SS, INTR >::vbusState = 0; /* constructor */ template< typename SS, typename INTR > -MAX3421e< SS, INTR >::MAX3421e() -{ - /* pin and peripheral setup */ - SS::SetDirWrite(); - SS::Set(); - spi::init(); - 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< SS, INTR >::MAX3421e() { + /* pin and peripheral setup */ + SS::SetDirWrite(); + SS::Set(); + spi::init(); + INTR::SetDirRead(); - /* MAX3421E - full-duplex SPI, level interrupt */ - regWr( rPINCTL,( bmFDUPSPI + bmINTLEVEL )); + /* MAX3421E - full-duplex SPI, level interrupt */ + regWr(rPINCTL, (bmFDUPSPI + bmINTLEVEL)); }; + /* write single byte into MAX3421 register */ template< typename SS, typename INTR > -void MAX3421e< SS, INTR >::regWr( uint8_t reg, uint8_t data ) -{ - SS::Clear(); - SPDR = ( reg | 0x02 ); - while(!( SPSR & ( 1 << SPIF ))); - SPDR = data; - while(!( SPSR & ( 1 << SPIF ))); - SS::Set(); - return; +void MAX3421e< SS, INTR >::regWr(uint8_t reg, uint8_t data) { + SS::Clear(); + SPDR = (reg | 0x02); + while (!(SPSR & (1 << SPIF))); + SPDR = data; + while (!(SPSR & (1 << SPIF))); + SS::Set(); + return; }; /* multiple-byte write */ + /* returns a pointer to memory position after last written */ template< typename SS, typename INTR > -uint8_t* MAX3421e< SS, INTR >::bytesWr( uint8_t reg, uint8_t nbytes, uint8_t* data_p ) -{ - SS::Clear(); - SPDR = ( reg | 0x02 ); //set WR bit and send register number - while( nbytes-- ) { - while(!( SPSR & ( 1 << SPIF ))); //check if previous byte was sent - SPDR = ( *data_p ); // send next data byte - data_p++; // advance data pointer - } - while(!( SPSR & ( 1 << SPIF ))); - SS::Set(); - return( data_p ); +uint8_t* MAX3421e< SS, INTR >::bytesWr(uint8_t reg, uint8_t nbytes, uint8_t* data_p) { + SS::Clear(); + SPDR = (reg | 0x02); //set WR bit and send register number + while (nbytes--) { + while (!(SPSR & (1 << SPIF))); //check if previous byte was sent + SPDR = (*data_p); // send next data byte + data_p++; // advance data pointer + } + while (!(SPSR & (1 << SPIF))); + SS::Set(); + return ( data_p); } /* GPIO write */ /*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 */ template< typename SS, typename INTR > -void MAX3421e< SS, INTR >::gpioWr( uint8_t data ) -{ - regWr( rIOPINS1, data ); - data >>= 4; - regWr( rIOPINS2, data ); - return; +void MAX3421e< SS, INTR >::gpioWr(uint8_t data) { + regWr(rIOPINS1, data); + data >>= 4; + regWr(rIOPINS2, data); + return; } + /* single host register read */ template< typename SS, typename INTR > -uint8_t MAX3421e< SS, INTR >::regRd( uint8_t reg ) -{ - SS::Clear(); - SPDR = reg; - while(!( SPSR & ( 1 << SPIF ))); - SPDR = 0; //send empty byte - while(!( SPSR & ( 1 << SPIF ))); - SS::Set(); - return( SPDR ); +uint8_t MAX3421e< SS, INTR >::regRd(uint8_t reg) { + SS::Clear(); + SPDR = reg; + while (!(SPSR & (1 << SPIF))); + SPDR = 0; //send empty byte + while (!(SPSR & (1 << SPIF))); + SS::Set(); + return ( SPDR); } /* multiple-byte register read */ + /* returns a pointer to a memory position after last read */ template< typename SS, typename INTR > -uint8_t* MAX3421e< SS, INTR >::bytesRd( uint8_t reg, uint8_t nbytes, uint8_t* data_p ) -{ - SS::Clear(); - SPDR = reg; - while(!( SPSR & ( 1 << SPIF ))); //wait - while( nbytes ) { - SPDR = 0; //send empty byte - nbytes--; - while(!( SPSR & ( 1 << SPIF ))); - *data_p = SPDR; - data_p++; - } - SS::Set(); - return( data_p ); +uint8_t* MAX3421e< SS, INTR >::bytesRd(uint8_t reg, uint8_t nbytes, uint8_t* data_p) { + SS::Clear(); + SPDR = reg; + while (!(SPSR & (1 << SPIF))); //wait + while (nbytes) { + SPDR = 0; //send empty byte + nbytes--; + while (!(SPSR & (1 << SPIF))); + *data_p = SPDR; + data_p++; + } + SS::Set(); + return ( data_p); } /* GPIO read. See gpioWr for explanation */ + /* GPIN pins are in high nibbles of IOPINS1, IOPINS2 */ template< typename SS, typename INTR > -uint8_t MAX3421e< SS, INTR >::gpioRd() -{ - uint8_t gpin = 0; - gpin = regRd( rIOPINS2 ); //pins 4-7 - gpin &= 0xf0; //clean lower nibble - gpin |= ( regRd( rIOPINS1 ) >>4 ) ; //shift low bits and OR with upper from previous operation. - return( gpin ); +uint8_t MAX3421e< SS, INTR >::gpioRd() { + uint8_t gpin = 0; + gpin = regRd(rIOPINS2); //pins 4-7 + gpin &= 0xf0; //clean lower nibble + gpin |= (regRd(rIOPINS1) >> 4); //shift low bits and OR with upper from previous operation. + return ( gpin); } + /* reset MAX3421E. Returns number of cycles it took for PLL to stabilize after reset or zero if PLL haven't stabilized in 65535 cycles */ template< typename SS, typename INTR > -uint16_t MAX3421e< SS, INTR >::reset() -{ - uint16_t i = 0; - regWr( rUSBCTL, bmCHIPRES ); - regWr( rUSBCTL, 0x00 ); - while( ++i ) { - if(( regRd( rUSBIRQ ) & bmOSCOKIRQ )) { - break; - } - } - return( i ); +uint16_t MAX3421e< SS, INTR >::reset() { + uint16_t i = 0; + regWr(rUSBCTL, bmCHIPRES); + regWr(rUSBCTL, 0x00); + while (++i) { + if ((regRd(rUSBIRQ) & bmOSCOKIRQ)) { + break; + } + } + return ( i); } ///* initialize MAX3421E. Set Host mode, pullups, and stuff. Returns 0 if success, -1 if not */ //template< typename SS, typename INTR > @@ -199,105 +193,101 @@ uint16_t MAX3421e< SS, INTR >::reset() // return ( -1 ); // } // regWr( rMODE, bmDPPULLDN|bmDMPULLDN|bmHOST ); // set pull-downs, Host -// +// // return( 0 ); //} + /* initialize MAX3421E. Set Host mode, pullups, and stuff. Returns 0 if success, -1 if not */ template< typename SS, typename INTR > -int8_t MAX3421e< SS, INTR >::Init() -{ - if( reset() == 0 ) - { //OSCOKIRQ hasn't asserted in time - return ( -1 ); - } - regWr( rMODE, bmDPPULLDN|bmDMPULLDN|bmHOST ); // set pull-downs, Host - - regWr( rHIEN, bmCONDETIE|bmFRAMEIE ); //connection detection +int8_t MAX3421e< SS, INTR >::Init() { + if (reset() == 0) { //OSCOKIRQ hasn't asserted in time + return ( -1); + } + regWr(rMODE, bmDPPULLDN | bmDMPULLDN | bmHOST); // set pull-downs, Host - /* check if device is connected */ - regWr( rHCTL,bmSAMPLEBUS ); // sample USB bus - while(!(regRd( rHCTL ) & bmSAMPLEBUS )); //wait for sample operation to finish + regWr(rHIEN, bmCONDETIE | bmFRAMEIE); //connection detection - busprobe(); //check if anything is connected + /* check if device is connected */ + regWr(rHCTL, bmSAMPLEBUS); // sample USB bus + while (!(regRd(rHCTL) & bmSAMPLEBUS)); //wait for sample operation to finish - regWr( rHIRQ, bmCONDETIRQ ); //clear connection detect interrupt - regWr( rCPUCTL, 0x01 ); //enable interrupt pin - return( 0 ); + busprobe(); //check if anything is connected + + regWr(rHIRQ, bmCONDETIRQ); //clear connection detect interrupt + regWr(rCPUCTL, 0x01); //enable interrupt pin + 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 > -void MAX3421e< SS, INTR >::busprobe() -{ - uint8_t bus_sample; - bus_sample = regRd( rHRSL ); //Get J,K status - bus_sample &= ( bmJSTATUS|bmKSTATUS ); //zero the rest of the byte - switch( bus_sample ) { //start full-speed or low-speed host - case( bmJSTATUS ): - if(( regRd( rMODE ) & bmLOWSPEED ) == 0 ) { - regWr( rMODE, MODE_FS_HOST ); //start full-speed host - vbusState = FSHOST; - } - else { - regWr( rMODE, MODE_LS_HOST); //start low-speed host - vbusState = LSHOST; - } - break; - case( bmKSTATUS ): - if(( regRd( rMODE ) & bmLOWSPEED ) == 0 ) { - regWr( rMODE, MODE_LS_HOST ); //start low-speed host - vbusState = LSHOST; - } - else { - regWr( rMODE, MODE_FS_HOST ); //start full-speed host - vbusState = FSHOST; - } - break; - case( bmSE1 ): //illegal state - vbusState = SE1; - break; - case( bmSE0 ): //disconnected state - regWr( rMODE, bmDPPULLDN|bmDMPULLDN|bmHOST|bmSEPIRQ); - vbusState = SE0; - break; +void MAX3421e< SS, INTR >::busprobe() { + uint8_t bus_sample; + bus_sample = regRd(rHRSL); //Get J,K status + bus_sample &= (bmJSTATUS | bmKSTATUS); //zero the rest of the byte + switch (bus_sample) { //start full-speed or low-speed host + case( bmJSTATUS): + if ((regRd(rMODE) & bmLOWSPEED) == 0) { + regWr(rMODE, MODE_FS_HOST); //start full-speed host + vbusState = FSHOST; + } else { + regWr(rMODE, MODE_LS_HOST); //start low-speed host + vbusState = LSHOST; + } + break; + case( bmKSTATUS): + if ((regRd(rMODE) & bmLOWSPEED) == 0) { + regWr(rMODE, MODE_LS_HOST); //start low-speed host + vbusState = LSHOST; + } else { + regWr(rMODE, MODE_FS_HOST); //start full-speed host + vbusState = FSHOST; + } + break; + case( bmSE1): //illegal state + vbusState = SE1; + break; + case( bmSE0): //disconnected state + regWr(rMODE, bmDPPULLDN | bmDMPULLDN | bmHOST | bmSEPIRQ); + vbusState = SE0; + break; }//end switch( bus_sample ) } + /* MAX3421 state change task and interrupt handler */ template< typename SS, typename INTR > -uint8_t MAX3421e< SS, INTR >::Task( void ) -{ - uint8_t rcode = 0; - uint8_t pinvalue; - //Serial.print("Vbus state: "); - //Serial.println( vbusState, HEX ); - pinvalue = INTR::IsSet(); //Read(); - //pinvalue = digitalRead( MAX_INT ); - if( pinvalue == 0 ) { - rcode = IntHandler(); - } -// pinvalue = digitalRead( MAX_GPX ); -// if( pinvalue == LOW ) { -// GpxHandler(); -// } -// usbSM(); //USB state machine - return( rcode ); -} +uint8_t MAX3421e< SS, INTR >::Task(void) { + uint8_t rcode = 0; + uint8_t pinvalue; + //Serial.print("Vbus state: "); + //Serial.println( vbusState, HEX ); + pinvalue = INTR::IsSet(); //Read(); + //pinvalue = digitalRead( MAX_INT ); + if (pinvalue == 0) { + rcode = IntHandler(); + } + // pinvalue = digitalRead( MAX_GPX ); + // if( pinvalue == LOW ) { + // GpxHandler(); + // } + // usbSM(); //USB state machine + return ( rcode); +} + template< typename SS, typename INTR > -uint8_t MAX3421e< SS, INTR >::IntHandler() -{ - uint8_t HIRQ; - uint8_t HIRQ_sendback = 0x00; - HIRQ = regRd( rHIRQ ); //determine interrupt source - //if( HIRQ & bmFRAMEIRQ ) { //->1ms SOF interrupt handler - // HIRQ_sendback |= bmFRAMEIRQ; - //}//end FRAMEIRQ handling - if( HIRQ & bmCONDETIRQ ) { - busprobe(); - HIRQ_sendback |= bmCONDETIRQ; - } - /* End HIRQ interrupts handling, clear serviced IRQs */ - regWr( rHIRQ, HIRQ_sendback ); - return( HIRQ_sendback ); +uint8_t MAX3421e< SS, INTR >::IntHandler() { + uint8_t HIRQ; + uint8_t HIRQ_sendback = 0x00; + HIRQ = regRd(rHIRQ); //determine interrupt source + //if( HIRQ & bmFRAMEIRQ ) { //->1ms SOF interrupt handler + // HIRQ_sendback |= bmFRAMEIRQ; + //}//end FRAMEIRQ handling + if (HIRQ & bmCONDETIRQ) { + busprobe(); + HIRQ_sendback |= bmCONDETIRQ; + } + /* End HIRQ interrupts handling, clear serviced IRQs */ + regWr(rHIRQ, HIRQ_sendback); + return ( HIRQ_sendback); } //template< typename SS, typename INTR > //uint8_t MAX3421e< SS, INTR >::GpxHandler() @@ -308,7 +298,7 @@ uint8_t MAX3421e< SS, INTR >::IntHandler() //// delay( 1000 ); //// vbusPwr( ON ); //// regWr( rGPINIRQ, bmGPINIRQ7 ); -//// } +//// } // return( GPINIRQ ); //} diff --git a/usbhub.cpp b/usbhub.cpp index 761b3a37..7693c2c7 100644 --- a/usbhub.cpp +++ b/usbhub.cpp @@ -13,402 +13,382 @@ Contact information Circuits At Home, LTD Web : http://www.circuitsathome.com e-mail : support@circuitsathome.com -*/ + */ #include "usbhub.h" bool USBHub::bResetInitiated = false; -USBHub::USBHub(USB *p) : - pUsb(p), - bAddress(0), - bNbrPorts(0), - bInitState(0), - qNextPollTime(0), - bPollEnable(false) -{ - epInfo[0].epAddr = 0; - epInfo[0].maxPktSize = 8; - epInfo[0].epAttribs = 0; - epInfo[0].bmNakPower = USB_NAK_MAX_POWER; +USBHub::USBHub(USB *p) : +pUsb(p), +bAddress(0), +bNbrPorts(0), +bInitState(0), +qNextPollTime(0), +bPollEnable(false) { + epInfo[0].epAddr = 0; + epInfo[0].maxPktSize = 8; + epInfo[0].epAttribs = 0; + epInfo[0].bmNakPower = USB_NAK_MAX_POWER; - epInfo[1].epAddr = 1; - epInfo[1].maxPktSize = 8; //kludge - epInfo[1].epAttribs = 0; - epInfo[1].bmNakPower = USB_NAK_NOWAIT; + epInfo[1].epAddr = 1; + epInfo[1].maxPktSize = 8; //kludge + epInfo[1].epAttribs = 0; + epInfo[1].bmNakPower = USB_NAK_NOWAIT; - if (pUsb) - pUsb->RegisterDeviceClass(this); + if (pUsb) + pUsb->RegisterDeviceClass(this); } -uint8_t USBHub::Init(uint8_t parent, uint8_t port, bool lowspeed) -{ - uint8_t buf[32]; - uint8_t rcode; - UsbDevice *p = NULL; - EpInfo *oldep_ptr = NULL; - uint8_t len = 0; - uint16_t cd_len = 0; - - //USBTRACE("\r\nHub Init Start"); +uint8_t USBHub::Init(uint8_t parent, uint8_t port, bool lowspeed) { + uint8_t buf[32]; + uint8_t rcode; + UsbDevice *p = NULL; + EpInfo *oldep_ptr = NULL; + uint8_t len = 0; + uint16_t cd_len = 0; - AddressPool &addrPool = pUsb->GetAddressPool(); - - switch (bInitState) - { - case 0: - if (bAddress) - return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE; + //USBTRACE("\r\nHub Init Start"); - // Get pointer to pseudo device with address 0 assigned - p = addrPool.GetUsbDevicePtr(0); + AddressPool &addrPool = pUsb->GetAddressPool(); - if (!p) - return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; + switch (bInitState) { + case 0: + if (bAddress) + return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE; - if (!p->epinfo) - return USB_ERROR_EPINFO_IS_NULL; + // Get pointer to pseudo device with address 0 assigned + p = addrPool.GetUsbDevicePtr(0); - // Save old pointer to EP_RECORD of address 0 - oldep_ptr = p->epinfo; + if (!p) + return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; - // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence - p->epinfo = epInfo; + if (!p->epinfo) + return USB_ERROR_EPINFO_IS_NULL; - p->lowspeed = lowspeed; + // Save old pointer to EP_RECORD of address 0 + oldep_ptr = p->epinfo; - // Get device descriptor - rcode = pUsb->getDevDescr( 0, 0, 8, (uint8_t*)buf ); + // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence + p->epinfo = epInfo; - p->lowspeed = false; + p->lowspeed = lowspeed; - if (!rcode) - len = (buf[0] > 32) ? 32 : buf[0]; + // Get device descriptor + rcode = pUsb->getDevDescr(0, 0, 8, (uint8_t*) buf); - if( rcode ) - { - // Restore p->epinfo - p->epinfo = oldep_ptr; - return rcode; - } + p->lowspeed = false; - // Extract device class from device descriptor - // If device class is not a hub return - if (((USB_DEVICE_DESCRIPTOR*)buf)->bDeviceClass != 0x09) - return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; + if (!rcode) + len = (buf[0] > 32) ? 32 : buf[0]; - // Allocate new address according to device class - bAddress = addrPool.AllocAddress(parent, (((USB_DEVICE_DESCRIPTOR*)buf)->bDeviceClass == 0x09) ? true : false, port); + if (rcode) { + // Restore p->epinfo + p->epinfo = oldep_ptr; + return rcode; + } - if (!bAddress) - return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; + // Extract device class from device descriptor + // If device class is not a hub return + if (((USB_DEVICE_DESCRIPTOR*) buf)->bDeviceClass != 0x09) + return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; - // Extract Max Packet Size from the device descriptor - epInfo[0].maxPktSize = ((USB_DEVICE_DESCRIPTOR*)buf)->bMaxPacketSize0; + // Allocate new address according to device class + bAddress = addrPool.AllocAddress(parent, (((USB_DEVICE_DESCRIPTOR*) buf)->bDeviceClass == 0x09) ? true : false, port); - // Assign new address to the device - rcode = pUsb->setAddr( 0, 0, bAddress ); + if (!bAddress) + return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; - if (rcode) - { - // Restore p->epinfo - p->epinfo = oldep_ptr; - addrPool.FreeAddress(bAddress); - bAddress = 0; - return rcode; - } - - //USBTRACE2("\r\nHub address: ", bAddress ); - - // Restore p->epinfo - p->epinfo = oldep_ptr; + // Extract Max Packet Size from the device descriptor + epInfo[0].maxPktSize = ((USB_DEVICE_DESCRIPTOR*) buf)->bMaxPacketSize0; - if (len) - rcode = pUsb->getDevDescr( bAddress, 0, len, (uint8_t*)buf ); + // Assign new address to the device + rcode = pUsb->setAddr(0, 0, bAddress); - if(rcode) - goto FailGetDevDescr; + if (rcode) { + // Restore p->epinfo + p->epinfo = oldep_ptr; + addrPool.FreeAddress(bAddress); + bAddress = 0; + return rcode; + } - // Assign epInfo to epinfo pointer - rcode = pUsb->setEpInfoEntry(bAddress, 2, epInfo); + //USBTRACE2("\r\nHub address: ", bAddress ); - if (rcode) - goto FailSetDevTblEntry; + // Restore p->epinfo + p->epinfo = oldep_ptr; - bInitState = 1; + if (len) + rcode = pUsb->getDevDescr(bAddress, 0, len, (uint8_t*) buf); - case 1: - // Get hub descriptor - rcode = GetHubDescriptor(0, 8, buf); + if (rcode) + goto FailGetDevDescr; - if (rcode) - goto FailGetHubDescr; + // Assign epInfo to epinfo pointer + rcode = pUsb->setEpInfoEntry(bAddress, 2, epInfo); - // Save number of ports for future use - bNbrPorts = ((HubDescriptor*)buf)->bNbrPorts; + if (rcode) + goto FailSetDevTblEntry; - bInitState = 2; + bInitState = 1; - case 2: - // Read configuration Descriptor in Order To Obtain Proper Configuration Value - rcode = pUsb->getConfDescr(bAddress, 0, 8, 0, buf); + case 1: + // Get hub descriptor + rcode = GetHubDescriptor(0, 8, buf); - if (!rcode) - { - cd_len = ((USB_CONFIGURATION_DESCRIPTOR*)buf)->wTotalLength; - rcode = pUsb->getConfDescr(bAddress, 0, cd_len, 0, buf); - } - if (rcode) - goto FailGetConfDescr; + if (rcode) + goto FailGetHubDescr; - // The following code is of no practical use in real life applications. - // It only intended for the usb protocol sniffer to properly parse hub-class requests. - { - uint8_t buf2[24]; + // Save number of ports for future use + bNbrPorts = ((HubDescriptor*) buf)->bNbrPorts; - rcode = pUsb->getConfDescr(bAddress, 0, buf[0], 0, buf2); + bInitState = 2; - if (rcode) - goto FailGetConfDescr; - } + case 2: + // Read configuration Descriptor in Order To Obtain Proper Configuration Value + rcode = pUsb->getConfDescr(bAddress, 0, 8, 0, buf); - // Set Configuration Value - rcode = pUsb->setConf(bAddress, 0, buf[5]); + if (!rcode) { + cd_len = ((USB_CONFIGURATION_DESCRIPTOR*) buf)->wTotalLength; + rcode = pUsb->getConfDescr(bAddress, 0, cd_len, 0, buf); + } + if (rcode) + goto FailGetConfDescr; - if (rcode) - goto FailSetConfDescr; + // The following code is of no practical use in real life applications. + // It only intended for the usb protocol sniffer to properly parse hub-class requests. + { + uint8_t buf2[24]; - bInitState = 3; + rcode = pUsb->getConfDescr(bAddress, 0, buf[0], 0, buf2); - case 3: - // Power on all ports - for (uint8_t j=1; j<=bNbrPorts; j++) - SetPortFeature(HUB_FEATURE_PORT_POWER, j, 0); //HubPortPowerOn(j); + if (rcode) + goto FailGetConfDescr; + } - pUsb->SetHubPreMask(); - bPollEnable = true; - bInitState = 0; - } - bInitState = 0; - return 0; + // Set Configuration Value + rcode = pUsb->setConf(bAddress, 0, buf[5]); + + if (rcode) + goto FailSetConfDescr; + + bInitState = 3; + + case 3: + // Power on all ports + for (uint8_t j = 1; j <= bNbrPorts; j++) + SetPortFeature(HUB_FEATURE_PORT_POWER, j, 0); //HubPortPowerOn(j); + + pUsb->SetHubPreMask(); + bPollEnable = true; + bInitState = 0; + } + bInitState = 0; + return 0; FailGetDevDescr: - goto Fail; + goto Fail; FailSetDevTblEntry: - goto Fail; + goto Fail; FailGetHubDescr: - goto Fail; + goto Fail; FailGetConfDescr: - goto Fail; + goto Fail; FailSetConfDescr: - goto Fail; - -FailGetPortStatus: - goto Fail; + goto Fail; Fail: - return rcode; + return rcode; } -uint8_t USBHub::Release() -{ - pUsb->GetAddressPool().FreeAddress(bAddress); +uint8_t USBHub::Release() { + pUsb->GetAddressPool().FreeAddress(bAddress); - if (bAddress == 0x41) - pUsb->SetHubPreMask(); + if (bAddress == 0x41) + pUsb->SetHubPreMask(); - bAddress = 0; - bNbrPorts = 0; - qNextPollTime = 0; - bPollEnable = false; - return 0; + bAddress = 0; + bNbrPorts = 0; + qNextPollTime = 0; + bPollEnable = false; + return 0; } -uint8_t USBHub::Poll() -{ - uint8_t rcode = 0; +uint8_t USBHub::Poll() { + uint8_t rcode = 0; - if (!bPollEnable) - return 0; + if (!bPollEnable) + return 0; - if (qNextPollTime <= millis()) - { - rcode = CheckHubStatus(); - qNextPollTime = millis() + 100; - } - return rcode; + if (qNextPollTime <= millis()) { + rcode = CheckHubStatus(); + qNextPollTime = millis() + 100; + } + return rcode; } -uint8_t USBHub::CheckHubStatus() -{ - uint8_t rcode; - uint8_t buf[8]; - uint16_t read = 1; +uint8_t USBHub::CheckHubStatus() { + uint8_t rcode; + uint8_t buf[8]; + uint16_t read = 1; - rcode = pUsb->inTransfer(bAddress, 1, &read, buf); + rcode = pUsb->inTransfer(bAddress, 1, &read, buf); - if (rcode) - return rcode; + if (rcode) + return rcode; - if (buf[0] & 0x01) // Hub Status Change - { - //pUsb->PrintHubStatus(addr); - //rcode = GetHubStatus(1, 0, 1, 4, buf); - //if (rcode) - //{ - // Serial.print("GetHubStatus Error"); - // Serial.println(rcode, HEX); - // return rcode; - //} - } - for (uint8_t port=1,mask=0x02; port<8; mask<<=1, port++) - { - if (buf[0] & mask) - { - HubEvent evt; - evt.bmEvent = 0; + if (buf[0] & 0x01) // Hub Status Change + { + //pUsb->PrintHubStatus(addr); + //rcode = GetHubStatus(1, 0, 1, 4, buf); + //if (rcode) + //{ + // Serial.print("GetHubStatus Error"); + // Serial.println(rcode, HEX); + // return rcode; + //} + } + for (uint8_t port = 1, mask = 0x02; port < 8; mask <<= 1, port++) { + if (buf[0] & mask) { + HubEvent evt; + evt.bmEvent = 0; - rcode = GetPortStatus(port, 4, evt.evtBuff); + rcode = GetPortStatus(port, 4, evt.evtBuff); - if (rcode) - continue; + if (rcode) + continue; - rcode = PortStatusChange(port, evt); + rcode = PortStatusChange(port, evt); - if (rcode == HUB_ERROR_PORT_HAS_BEEN_RESET) - return 0; + if (rcode == HUB_ERROR_PORT_HAS_BEEN_RESET) + return 0; - if (rcode) - return rcode; - } - } // for + if (rcode) + return rcode; + } + } // for - for (uint8_t port=1; port<=bNbrPorts; port++) - { - HubEvent evt; - evt.bmEvent = 0; + for (uint8_t port = 1; port <= bNbrPorts; port++) { + HubEvent evt; + evt.bmEvent = 0; - rcode = GetPortStatus(port, 4, evt.evtBuff); + rcode = GetPortStatus(port, 4, evt.evtBuff); - if (rcode) - continue; + if (rcode) + continue; - if ((evt.bmStatus & bmHUB_PORT_STATE_CHECK_DISABLED) != bmHUB_PORT_STATE_DISABLED) - continue; + if ((evt.bmStatus & bmHUB_PORT_STATE_CHECK_DISABLED) != bmHUB_PORT_STATE_DISABLED) + continue; - // Emulate connection event for the port - evt.bmChange |= bmHUB_PORT_STATUS_C_PORT_CONNECTION; + // Emulate connection event for the port + evt.bmChange |= bmHUB_PORT_STATUS_C_PORT_CONNECTION; - rcode = PortStatusChange(port, evt); + rcode = PortStatusChange(port, evt); - if (rcode == HUB_ERROR_PORT_HAS_BEEN_RESET) - return 0; + if (rcode == HUB_ERROR_PORT_HAS_BEEN_RESET) + return 0; - if (rcode) - return rcode; - } // for - return 0; + if (rcode) + return rcode; + } // for + return 0; } -uint8_t USBHub::PortStatusChange(uint8_t port, HubEvent &evt) -{ - switch (evt.bmEvent) - { - // Device connected event - case bmHUB_PORT_EVENT_CONNECT: - case bmHUB_PORT_EVENT_LS_CONNECT: - if (bResetInitiated) - return 0; +uint8_t USBHub::PortStatusChange(uint8_t port, HubEvent &evt) { + switch (evt.bmEvent) { + // Device connected event + case bmHUB_PORT_EVENT_CONNECT: + case bmHUB_PORT_EVENT_LS_CONNECT: + if (bResetInitiated) + return 0; - ClearPortFeature(HUB_FEATURE_C_PORT_ENABLE, port, 0); - ClearPortFeature(HUB_FEATURE_C_PORT_CONNECTION, port, 0); - SetPortFeature(HUB_FEATURE_PORT_RESET, port, 0); - bResetInitiated = true; - return HUB_ERROR_PORT_HAS_BEEN_RESET; + ClearPortFeature(HUB_FEATURE_C_PORT_ENABLE, port, 0); + ClearPortFeature(HUB_FEATURE_C_PORT_CONNECTION, port, 0); + SetPortFeature(HUB_FEATURE_PORT_RESET, port, 0); + bResetInitiated = true; + return HUB_ERROR_PORT_HAS_BEEN_RESET; - // Device disconnected event - case bmHUB_PORT_EVENT_DISCONNECT: - ClearPortFeature(HUB_FEATURE_C_PORT_ENABLE, port, 0); - ClearPortFeature(HUB_FEATURE_C_PORT_CONNECTION, port, 0); - bResetInitiated = false; + // Device disconnected event + case bmHUB_PORT_EVENT_DISCONNECT: + ClearPortFeature(HUB_FEATURE_C_PORT_ENABLE, port, 0); + ClearPortFeature(HUB_FEATURE_C_PORT_CONNECTION, port, 0); + bResetInitiated = false; - UsbDeviceAddress a; - a.bmHub = 0; - a.bmParent = bAddress; - a.bmAddress = port; - pUsb->ReleaseDevice(a.devAddress); - return 0; + UsbDeviceAddress a; + a.bmHub = 0; + a.bmParent = bAddress; + a.bmAddress = port; + pUsb->ReleaseDevice(a.devAddress); + return 0; - // Reset complete event - case bmHUB_PORT_EVENT_RESET_COMPLETE: - case bmHUB_PORT_EVENT_LS_RESET_COMPLETE: - ClearPortFeature(HUB_FEATURE_C_PORT_RESET, port, 0); - ClearPortFeature(HUB_FEATURE_C_PORT_CONNECTION, port, 0); + // Reset complete event + case bmHUB_PORT_EVENT_RESET_COMPLETE: + case bmHUB_PORT_EVENT_LS_RESET_COMPLETE: + ClearPortFeature(HUB_FEATURE_C_PORT_RESET, port, 0); + ClearPortFeature(HUB_FEATURE_C_PORT_CONNECTION, port, 0); - delay(20); + delay(20); - a.devAddress = bAddress; + a.devAddress = bAddress; - pUsb->Configuring(a.bmAddress, port, (evt.bmStatus & bmHUB_PORT_STATUS_PORT_LOW_SPEED) ); - bResetInitiated = false; - break; + pUsb->Configuring(a.bmAddress, port, (evt.bmStatus & bmHUB_PORT_STATUS_PORT_LOW_SPEED)); + bResetInitiated = false; + break; - } // switch (evt.bmEvent) - return 0; + } // switch (evt.bmEvent) + return 0; } -void PrintHubPortStatus(USBHub *hubptr, uint8_t addr, uint8_t port, bool print_changes) -{ - uint8_t rcode = 0; - HubEvent evt; +void PrintHubPortStatus(USBHub *hubptr, uint8_t addr, uint8_t port, bool print_changes) { + uint8_t rcode = 0; + HubEvent evt; - rcode = hubptr->GetPortStatus(port, 4, evt.evtBuff); + rcode = hubptr->GetPortStatus(port, 4, evt.evtBuff); - if (rcode) - { - Serial.println("ERROR!"); - return; - } - Serial.print("\r\nPort "); - Serial.println(port, DEC); + if (rcode) { + Serial.println("ERROR!"); + return; + } + Serial.print("\r\nPort "); + Serial.println(port, DEC); - Serial.println("Status"); - Serial.print("CONNECTION:\t"); - Serial.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_CONNECTION) > 0, DEC); - Serial.print("ENABLE:\t\t"); - Serial.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_ENABLE) > 0, DEC); - Serial.print("SUSPEND:\t"); - Serial.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_SUSPEND) > 0, DEC); - Serial.print("OVER_CURRENT:\t"); - Serial.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_OVER_CURRENT) > 0, DEC); - Serial.print("RESET:\t\t"); - Serial.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_RESET) > 0, DEC); - Serial.print("POWER:\t\t"); - Serial.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_POWER) > 0, DEC); - Serial.print("LOW_SPEED:\t"); - Serial.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_LOW_SPEED) > 0, DEC); - Serial.print("HIGH_SPEED:\t"); - Serial.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_HIGH_SPEED) > 0, DEC); - Serial.print("TEST:\t\t"); - Serial.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_TEST) > 0, DEC); - Serial.print("INDICATOR:\t"); - Serial.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_INDICATOR) > 0, DEC); + Serial.println("Status"); + Serial.print("CONNECTION:\t"); + Serial.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_CONNECTION) > 0, DEC); + Serial.print("ENABLE:\t\t"); + Serial.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_ENABLE) > 0, DEC); + Serial.print("SUSPEND:\t"); + Serial.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_SUSPEND) > 0, DEC); + Serial.print("OVER_CURRENT:\t"); + Serial.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_OVER_CURRENT) > 0, DEC); + Serial.print("RESET:\t\t"); + Serial.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_RESET) > 0, DEC); + Serial.print("POWER:\t\t"); + Serial.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_POWER) > 0, DEC); + Serial.print("LOW_SPEED:\t"); + Serial.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_LOW_SPEED) > 0, DEC); + Serial.print("HIGH_SPEED:\t"); + Serial.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_HIGH_SPEED) > 0, DEC); + Serial.print("TEST:\t\t"); + Serial.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_TEST) > 0, DEC); + Serial.print("INDICATOR:\t"); + Serial.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_INDICATOR) > 0, DEC); - if (!print_changes) - return; + if (!print_changes) + return; - Serial.println("\nChange"); - Serial.print("CONNECTION:\t"); - Serial.println((evt.bmChange & bmHUB_PORT_STATUS_C_PORT_CONNECTION) > 0, DEC); - Serial.print("ENABLE:\t\t"); - Serial.println((evt.bmChange & bmHUB_PORT_STATUS_C_PORT_ENABLE) > 0, DEC); - Serial.print("SUSPEND:\t"); - Serial.println((evt.bmChange & bmHUB_PORT_STATUS_C_PORT_SUSPEND) > 0, DEC); - Serial.print("OVER_CURRENT:\t"); - Serial.println((evt.bmChange & bmHUB_PORT_STATUS_C_PORT_OVER_CURRENT) > 0, DEC); - Serial.print("RESET:\t\t"); - Serial.println((evt.bmChange & bmHUB_PORT_STATUS_C_PORT_RESET) > 0, DEC); + Serial.println("\r\nChange"); + Serial.print("CONNECTION:\t"); + Serial.println((evt.bmChange & bmHUB_PORT_STATUS_C_PORT_CONNECTION) > 0, DEC); + Serial.print("ENABLE:\t\t"); + Serial.println((evt.bmChange & bmHUB_PORT_STATUS_C_PORT_ENABLE) > 0, DEC); + Serial.print("SUSPEND:\t"); + Serial.println((evt.bmChange & bmHUB_PORT_STATUS_C_PORT_SUSPEND) > 0, DEC); + Serial.print("OVER_CURRENT:\t"); + Serial.println((evt.bmChange & bmHUB_PORT_STATUS_C_PORT_OVER_CURRENT) > 0, DEC); + Serial.print("RESET:\t\t"); + Serial.println((evt.bmChange & bmHUB_PORT_STATUS_C_PORT_RESET) > 0, DEC); } diff --git a/usbhub.h b/usbhub.h index d34afa43..98a8ed7a 100644 --- a/usbhub.h +++ b/usbhub.h @@ -13,7 +13,7 @@ Contact information Circuits At Home, LTD Web : http://www.circuitsathome.com e-mail : support@circuitsathome.com -*/ + */ #if !defined(__USBHUB_H__) #define __USBHUB_H__ @@ -25,6 +25,7 @@ e-mail : support@circuitsathome.com #include "usb_ch9.h" #include "Usb.h" + #if defined(ARDUINO) && ARDUINO >=100 #include "Arduino.h" #else @@ -76,7 +77,7 @@ e-mail : support@circuitsathome.com #define HUB_PORT_TEST_MODE_K 2 #define HUB_PORT_TEST_MODE_SE0_NAK 3 #define HUB_PORT_TEST_MODE_PACKET 4 -#define HUB_PORT_TEST_MODE_FORCE_ENABLE 5 +#define HUB_PORT_TEST_MODE_FORCE_ENABLE 5 // Hub Port Indicator Color #define HUB_PORT_INDICATOR_AUTO 0 @@ -84,7 +85,7 @@ e-mail : support@circuitsathome.com #define HUB_PORT_INDICATOR_GREEN 2 #define HUB_PORT_INDICATOR_OFF 3 -// Hub Port Status Bitmasks +// Hub Port Status Bitmasks #define bmHUB_PORT_STATUS_PORT_CONNECTION 0x0001 #define bmHUB_PORT_STATUS_PORT_ENABLE 0x0002 #define bmHUB_PORT_STATUS_PORT_SUSPEND 0x0004 @@ -127,7 +128,7 @@ e-mail : support@circuitsathome.com // The bit mask to check for all necessary state bits #define bmHUB_PORT_STATUS_ALL_MAIN ((0UL | bmHUB_PORT_STATUS_C_PORT_CONNECTION | bmHUB_PORT_STATUS_C_PORT_ENABLE | bmHUB_PORT_STATUS_C_PORT_SUSPEND | 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_SUSPEND) -// Bit mask to check for DISABLED state in HubEvent::bmStatus field +// Bit mask to check for DISABLED state in HubEvent::bmStatus field #define bmHUB_PORT_STATE_CHECK_DISABLED (0x0000 | bmHUB_PORT_STATUS_PORT_POWER | bmHUB_PORT_STATUS_PORT_ENABLE | bmHUB_PORT_STATUS_PORT_CONNECTION | bmHUB_PORT_STATUS_PORT_SUSPEND) // Hub Port States @@ -142,118 +143,117 @@ 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_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 -{ - uint8_t bDescLength; // descriptor length - uint8_t bDescriptorType; // descriptor type - uint8_t bNbrPorts; // number of ports a hub equiped with - - struct - { - uint16_t LogPwrSwitchMode : 2; - uint16_t CompoundDevice : 1; - uint16_t OverCurrentProtectMode : 2; - uint16_t TTThinkTime : 2; - uint16_t PortIndicatorsSupported : 1; - uint16_t Reserved : 8; - }; +struct HubDescriptor { + uint8_t bDescLength; // descriptor length + uint8_t bDescriptorType; // descriptor type + uint8_t bNbrPorts; // number of ports a hub equiped with - uint8_t bPwrOn2PwrGood; - uint8_t bHubContrCurrent; -}; + struct { + uint16_t LogPwrSwitchMode : 2; + uint16_t CompoundDevice : 1; + uint16_t OverCurrentProtectMode : 2; + uint16_t TTThinkTime : 2; + uint16_t PortIndicatorsSupported : 1; + uint16_t Reserved : 8; + }__attribute__((packed)); -struct HubEvent -{ - union - { - struct - { - uint16_t bmStatus; // port status bits - uint16_t bmChange; // port status change bits - }; - uint32_t bmEvent; - uint8_t evtBuff[4]; - }; -}; + uint8_t bPwrOn2PwrGood; + uint8_t bHubContrCurrent; +}__attribute__((packed)); -class USBHub : USBDeviceConfig -{ - static bool bResetInitiated; // True when reset is triggered +struct HubEvent { - USB *pUsb; // USB class instance pointer + union { - EpInfo epInfo[2]; // interrupt endpoint info structure + struct { + uint16_t bmStatus; // port status bits + uint16_t bmChange; // port status change bits + }__attribute__((packed)); + uint32_t bmEvent; + uint8_t evtBuff[4]; + }; +}__attribute__((packed)); - uint8_t bAddress; // address - uint8_t bNbrPorts; // number of ports - uint8_t bInitState; // initialization state variable - uint32_t qNextPollTime; // next poll time - bool bPollEnable; // poll enable flag +class USBHub : USBDeviceConfig { + static bool bResetInitiated; // True when reset is triggered - uint8_t CheckHubStatus(); - uint8_t PortStatusChange(uint8_t port, HubEvent &evt); + USB *pUsb; // USB class instance pointer + + EpInfo epInfo[2]; // interrupt endpoint info structure + + uint8_t bAddress; // address + uint8_t bNbrPorts; // number of ports + uint8_t bInitState; // initialization state variable + uint32_t qNextPollTime; // next poll time + bool bPollEnable; // poll enable flag + + uint8_t CheckHubStatus(); + uint8_t PortStatusChange(uint8_t port, HubEvent &evt); public: - USBHub(USB *p); + USBHub(USB *p); - uint8_t ClearHubFeature( uint8_t fid ); - uint8_t ClearPortFeature( uint8_t fid, uint8_t port, uint8_t sel = 0 ); - uint8_t GetHubDescriptor( uint8_t index, uint16_t nbytes, uint8_t *dataptr ); - uint8_t GetHubStatus( uint16_t nbytes, uint8_t* dataptr ); - uint8_t GetPortStatus( uint8_t port, uint16_t nbytes, uint8_t* dataptr ); - uint8_t SetHubDescriptor( uint8_t port, uint16_t nbytes, uint8_t* dataptr ); - uint8_t SetHubFeature( uint8_t fid ); - uint8_t SetPortFeature( uint8_t fid, uint8_t port, uint8_t sel = 0 ); + uint8_t ClearHubFeature(uint8_t fid); + uint8_t ClearPortFeature(uint8_t fid, uint8_t port, uint8_t sel = 0); + uint8_t GetHubDescriptor(uint8_t index, uint16_t nbytes, uint8_t *dataptr); + uint8_t GetHubStatus(uint16_t nbytes, uint8_t* dataptr); + uint8_t GetPortStatus(uint8_t port, uint16_t nbytes, uint8_t* dataptr); + uint8_t SetHubDescriptor(uint8_t port, uint16_t nbytes, uint8_t* dataptr); + uint8_t SetHubFeature(uint8_t fid); + uint8_t SetPortFeature(uint8_t fid, uint8_t port, uint8_t sel = 0); - void PrintHubStatus(); + void PrintHubStatus(); - virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed); - virtual uint8_t Release(); - virtual uint8_t Poll(); - virtual uint8_t GetAddress() { return bAddress; }; + virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed); + virtual uint8_t Release(); + virtual uint8_t Poll(); + + virtual uint8_t GetAddress() { + return bAddress; + }; }; // Clear Hub Feature -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 )); + +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)); } // Clear Port Feature -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 )); + +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)); } // Get Hub Descriptor -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 )); + +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)); } // Get Hub Status -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 )); + +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)); } // Get Port Status -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 )); + +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)); } // Set Hub Descriptor -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 )); + +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)); } // Set Hub Feature -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 )); + +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)); } // Set Port Feature -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 )); + +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)); } void PrintHubPortStatus(USB *usbptr, uint8_t addr, uint8_t port, bool print_changes = false); -#endif // __USBHUB_H__ \ No newline at end of file +#endif // __USBHUB_H__ From 9b224b9899a801e36232c29091d5efb08c1da0fb Mon Sep 17 00:00:00 2001 From: "Andrew J. Kroll" Date: Thu, 28 Mar 2013 04:37:09 -0400 Subject: [PATCH 2/7] port debugging of new files, need to eliminate all serial.print yet. --- BTD.cpp | 2047 +++++++++++++++++++++++++------------------------- PS3BT.cpp | 216 +++--- PS3USB.cpp | 270 +++---- SPP.cpp | 262 +++---- Wii.cpp | 326 ++++---- XBOXRECV.cpp | 178 ++--- XBOXUSB.cpp | 150 ++-- 7 files changed, 1736 insertions(+), 1713 deletions(-) diff --git a/BTD.cpp b/BTD.cpp index e30be250..79a4b6cd 100755 --- a/BTD.cpp +++ b/BTD.cpp @@ -1,15 +1,15 @@ /* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved. - + This software may be distributed and modified under the terms of the GNU General Public License version 2 (GPL2) as published by the Free Software Foundation and appearing in the file GPL2.TXT included in the packaging of this file. Please note that GPL2 Section 2[b] requires that all works based on this software must also be made publicly available under the terms of the GPL2 ("Copyleft"). - + Contact information ------------------- - + Kristian Lauszus, TKJ Electronics Web : http://www.tkjelectronics.com e-mail : kristianl@tkjelectronics.com @@ -20,990 +20,1004 @@ //#define EXTRADEBUG // Uncomment to get even more debugging data const uint8_t BTD::BTD_CONTROL_PIPE = 0; -const uint8_t BTD::BTD_EVENT_PIPE = 1; +const uint8_t BTD::BTD_EVENT_PIPE = 1; const uint8_t BTD::BTD_DATAIN_PIPE = 2; const uint8_t BTD::BTD_DATAOUT_PIPE = 3; -BTD::BTD(USB *p): +BTD::BTD(USB *p) : pUsb(p), // Pointer to USB class instance - mandatory bAddress(0), // Device address - mandatory bNumEP(1), // If config descriptor needs to be parsed qNextPollTime(0), // Reset NextPollTime bPollEnable(false) // Don't start polling before dongle is connected { - for(uint8_t i=0; iRegisterDeviceClass(this); //set devConfig[] entry + for (uint8_t i = 0; i < BTD_MAX_ENDPOINTS; i++) { + epInfo[i].epAddr = 0; + epInfo[i].maxPktSize = (i) ? 0 : 8; + epInfo[i].epAttribs = 0; + epInfo[i].bmNakPower = (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER; + } + + if (pUsb) // register in USB subsystem + pUsb->RegisterDeviceClass(this); //set devConfig[] entry } uint8_t BTD::Init(uint8_t parent, uint8_t port, bool lowspeed) { - uint8_t buf[sizeof(USB_DEVICE_DESCRIPTOR)]; - uint8_t rcode; - UsbDevice *p = NULL; - EpInfo *oldep_ptr = NULL; - uint8_t num_of_conf; // number of configurations - uint16_t PID; - uint16_t VID; - - // get memory address of USB device address pool - AddressPool &addrPool = pUsb->GetAddressPool(); + uint8_t buf[sizeof (USB_DEVICE_DESCRIPTOR)]; + uint8_t rcode; + UsbDevice *p = NULL; + EpInfo *oldep_ptr = NULL; + uint8_t num_of_conf; // number of configurations + uint16_t PID; + uint16_t VID; + + // get memory address of USB device address pool + AddressPool &addrPool = pUsb->GetAddressPool(); #ifdef EXTRADEBUG - Notify(PSTR("\r\nBTD Init")); + Notify(PSTR("\r\nBTD Init"), 0x80); #endif - // check if address has already been assigned to an instance - if (bAddress) { + // check if address has already been assigned to an instance + if (bAddress) { #ifdef DEBUG - Notify(PSTR("\r\nAddress in use")); + Notify(PSTR("\r\nAddress in use"), 0x80); #endif - return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE; - } - - // Get pointer to pseudo device with address 0 assigned - p = addrPool.GetUsbDevicePtr(0); - - if (!p) { + return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE; + } + + // Get pointer to pseudo device with address 0 assigned + p = addrPool.GetUsbDevicePtr(0); + + if (!p) { #ifdef DEBUG - Notify(PSTR("\r\nAddress not found")); + Notify(PSTR("\r\nAddress not found"), 0x80); #endif - return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; - } - - if (!p->epinfo) { + return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; + } + + if (!p->epinfo) { #ifdef DEBUG - Notify(PSTR("\r\nepinfo is null")); + Notify(PSTR("\r\nepinfo is null"), 0x80); +#endif + return USB_ERROR_EPINFO_IS_NULL; + } + + // Save old pointer to EP_RECORD of address 0 + oldep_ptr = p->epinfo; + + // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence + p->epinfo = epInfo; + + p->lowspeed = lowspeed; + + // Get device descriptor + rcode = pUsb->getDevDescr(0, 0, sizeof (USB_DEVICE_DESCRIPTOR), (uint8_t*)buf); // Get device descriptor - addr, ep, nbytes, data + + // Restore p->epinfo + p->epinfo = oldep_ptr; + + if (rcode) + goto FailGetDevDescr; + + // Allocate new address according to device class + bAddress = addrPool.AllocAddress(parent, false, port); + + if (!bAddress) + return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; + + // Extract Max Packet Size from device descriptor + epInfo[0].maxPktSize = (uint8_t)((USB_DEVICE_DESCRIPTOR*)buf)->bMaxPacketSize0; + + // Assign new address to the device + rcode = pUsb->setAddr(0, 0, bAddress); + if (rcode) { + p->lowspeed = false; + addrPool.FreeAddress(bAddress); + bAddress = 0; +#ifdef DEBUG + Notify(PSTR("\r\nsetAddr: "), 0x80); +#endif + PrintHex (rcode, 0x80); + return rcode; + } +#ifdef EXTRADEBUG + Notify(PSTR("\r\nAddr: "), 0x80); + PrintHex (bAddress, 0x80); #endif - return USB_ERROR_EPINFO_IS_NULL; - } - - // Save old pointer to EP_RECORD of address 0 - oldep_ptr = p->epinfo; - - // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence - p->epinfo = epInfo; - - p->lowspeed = lowspeed; - - // Get device descriptor - rcode = pUsb->getDevDescr(0, 0, sizeof(USB_DEVICE_DESCRIPTOR), (uint8_t*)buf);// Get device descriptor - addr, ep, nbytes, data - - // Restore p->epinfo - p->epinfo = oldep_ptr; - - if(rcode) - goto FailGetDevDescr; - - // Allocate new address according to device class - bAddress = addrPool.AllocAddress(parent, false, port); - - if (!bAddress) - return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; - - // Extract Max Packet Size from device descriptor - epInfo[0].maxPktSize = (uint8_t)((USB_DEVICE_DESCRIPTOR*)buf)->bMaxPacketSize0; - - // Assign new address to the device - rcode = pUsb->setAddr( 0, 0, bAddress ); - if (rcode) { p->lowspeed = false; - addrPool.FreeAddress(bAddress); - bAddress = 0; -#ifdef DEBUG - Notify(PSTR("\r\nsetAddr: ")); -#endif - PrintHex(rcode); - return rcode; - } -#ifdef EXTRADEBUG - Notify(PSTR("\r\nAddr: ")); - PrintHex(bAddress); -#endif - p->lowspeed = false; - - //get pointer to assigned address record - p = addrPool.GetUsbDevicePtr(bAddress); - if (!p) - return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; - - p->lowspeed = lowspeed; - - // Assign epInfo to epinfo pointer - only EP0 is known - rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); - if (rcode) - goto FailSetDevTblEntry; - VID = ((USB_DEVICE_DESCRIPTOR*)buf)->idVendor; - PID = ((USB_DEVICE_DESCRIPTOR*)buf)->idProduct; - - if(VID == PS3_VID && (PID == PS3_PID || PID == PS3NAVIGATION_PID || PID == PS3MOVE_PID)) { - /* We only need the Control endpoint, so we don't have to initialize the other endpoints of device */ - rcode = pUsb->setConf(bAddress, epInfo[ BTD_CONTROL_PIPE ].epAddr, 1); - if( rcode ) - goto FailSetConf; - - if(PID == PS3_PID || PID == PS3NAVIGATION_PID) { -#ifdef DEBUG - if(PID == PS3_PID) - Notify(PSTR("\r\nDualshock 3 Controller Connected")); - else // must be a navigation controller - Notify(PSTR("\r\nNavigation Controller Connected")); -#endif - /* Set internal bluetooth address */ - setBdaddr(my_bdaddr); - } - else { // must be a Motion controller -#ifdef DEBUG - Notify(PSTR("\r\nMotion Controller Connected")); -#endif - setMoveBdaddr(my_bdaddr); - } - rcode = pUsb->setConf(bAddress, epInfo[ BTD_CONTROL_PIPE ].epAddr, 0); // Reset configuration value - pUsb->setAddr(bAddress, 0, 0); // Reset address - Release(); // Release device - return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; // return - } - else { - num_of_conf = ((USB_DEVICE_DESCRIPTOR*)buf)->bNumConfigurations; - // check if attached device is a Bluetooth dongle and fill endpoint data structure - // first interface in the configuration must have Bluetooth assigned Class/Subclass/Protocol - // and 3 endpoints - interrupt-IN, bulk-IN, bulk-OUT, - // not necessarily in this order - for (uint8_t i=0; i confDescrParser(this); - rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser); - if(rcode) - goto FailGetConfDescr; - if(bNumEP >= BTD_MAX_ENDPOINTS) // All endpoints extracted - break; - } - - if (bNumEP < BTD_MAX_ENDPOINTS) - goto FailUnknownDevice; - - // Assign epInfo to epinfo pointer - this time all 3 endpoins - rcode = pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo); - if(rcode) - goto FailSetDevTblEntry; - - delay(200); // Give time for address change - - // Set Configuration Value - rcode = pUsb->setConf(bAddress, epInfo[ BTD_CONTROL_PIPE ].epAddr, bConfNum); - if(rcode) - goto FailSetConf; - - hci_num_reset_loops = 100; // only loop 100 times before trying to send the hci reset command - hci_counter = 0; - hci_state = HCI_INIT_STATE; - watingForConnection = false; - bPollEnable = true; + //get pointer to assigned address record + p = addrPool.GetUsbDevicePtr(bAddress); + if (!p) + return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; + + p->lowspeed = lowspeed; + + // Assign epInfo to epinfo pointer - only EP0 is known + rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); + if (rcode) + goto FailSetDevTblEntry; + VID = ((USB_DEVICE_DESCRIPTOR*)buf)->idVendor; + PID = ((USB_DEVICE_DESCRIPTOR*)buf)->idProduct; + + if (VID == PS3_VID && (PID == PS3_PID || PID == PS3NAVIGATION_PID || PID == PS3MOVE_PID)) { + /* We only need the Control endpoint, so we don't have to initialize the other endpoints of device */ + rcode = pUsb->setConf(bAddress, epInfo[ BTD_CONTROL_PIPE ].epAddr, 1); + if (rcode) + goto FailSetConf; + + if (PID == PS3_PID || PID == PS3NAVIGATION_PID) { +#ifdef DEBUG + if (PID == PS3_PID) + Notify(PSTR("\r\nDualshock 3 Controller Connected"), 0x80); + else // must be a navigation controller + Notify(PSTR("\r\nNavigation Controller Connected"), 0x80); +#endif + /* Set internal bluetooth address */ + setBdaddr(my_bdaddr); + } else { // must be a Motion controller +#ifdef DEBUG + Notify(PSTR("\r\nMotion Controller Connected"), 0x80); +#endif + setMoveBdaddr(my_bdaddr); + } + rcode = pUsb->setConf(bAddress, epInfo[ BTD_CONTROL_PIPE ].epAddr, 0); // Reset configuration value + pUsb->setAddr(bAddress, 0, 0); // Reset address + Release(); // Release device + return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; // return + } else { + num_of_conf = ((USB_DEVICE_DESCRIPTOR*)buf)->bNumConfigurations; + + // check if attached device is a Bluetooth dongle and fill endpoint data structure + // first interface in the configuration must have Bluetooth assigned Class/Subclass/Protocol + // and 3 endpoints - interrupt-IN, bulk-IN, bulk-OUT, + // not necessarily in this order + for (uint8_t i = 0; i < num_of_conf; i++) { + ConfigDescParser confDescrParser(this); + rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser); + if (rcode) + goto FailGetConfDescr; + if (bNumEP >= BTD_MAX_ENDPOINTS) // All endpoints extracted + break; + } + + if (bNumEP < BTD_MAX_ENDPOINTS) + goto FailUnknownDevice; + + // Assign epInfo to epinfo pointer - this time all 3 endpoins + rcode = pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo); + if (rcode) + goto FailSetDevTblEntry; + + delay(200); // Give time for address change + + // Set Configuration Value + rcode = pUsb->setConf(bAddress, epInfo[ BTD_CONTROL_PIPE ].epAddr, bConfNum); + if (rcode) + goto FailSetConf; + + hci_num_reset_loops = 100; // only loop 100 times before trying to send the hci reset command + hci_counter = 0; + hci_state = HCI_INIT_STATE; + watingForConnection = false; + bPollEnable = true; #ifdef DEBUG - Notify(PSTR("\r\nBluetooth Dongle Initialized")); + Notify(PSTR("\r\nBluetooth Dongle Initialized"), 0x80); #endif - } - return 0; // Successful configuration - - /* diagnostic messages */ + } + return 0; // Successful configuration + + /* diagnostic messages */ FailGetDevDescr: #ifdef DEBUG - Notify(PSTR("\r\ngetDevDescr")); + Notify(PSTR("\r\ngetDevDescr"), 0x80); #endif - goto Fail; + goto Fail; FailSetDevTblEntry: #ifdef DEBUG - Notify(PSTR("\r\nsetDevTblEn")); + Notify(PSTR("\r\nsetDevTblEn"), 0x80); #endif - goto Fail; + goto Fail; FailGetConfDescr: #ifdef DEBUG - Notify(PSTR("\r\ngetConf")); + Notify(PSTR("\r\ngetConf"), 0x80); #endif - goto Fail; + goto Fail; FailSetConf: #ifdef DEBUG - Notify(PSTR("\r\nsetConf")); + Notify(PSTR("\r\nsetConf"), 0x80); #endif - goto Fail; + goto Fail; FailUnknownDevice: #ifdef DEBUG - Notify(PSTR("\r\nUnknown Device Connected - VID: ")); - PrintHex(VID); - Notify(PSTR(" PID: ")); - PrintHex(PID); + Notify(PSTR("\r\nUnknown Device Connected - VID: "), 0x80); + PrintHex (VID, 0x80); + Notify(PSTR(" PID: "), 0x80); + PrintHex (PID, 0x80); #endif - pUsb->setAddr(bAddress, 0, 0); // Reset address - rcode = USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; - goto Fail; + pUsb->setAddr(bAddress, 0, 0); // Reset address + rcode = USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; + goto Fail; Fail: #ifdef DEBUG - Notify(PSTR("\r\nBTD Init Failed, error code: ")); - Serial.print(rcode); -#endif - Release(); - return rcode; + Notify(PSTR("\r\nBTD Init Failed, error code: "), 0x80); + Serial.print(rcode); +#endif + Release(); + return rcode; } + /* Extracts interrupt-IN, bulk-IN, bulk-OUT endpoint information from config descriptor */ void BTD::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *pep) { - //ErrorMessage(PSTR("Conf.Val"),conf); - //ErrorMessage(PSTR("Iface Num"),iface); - //ErrorMessage(PSTR("Alt.Set"),alt); - - if(alt) // wrong interface - by BT spec, no alt setting - return; - - bConfNum = conf; - uint8_t index; - - if ((pep->bmAttributes & 0x03) == 3 && (pep->bEndpointAddress & 0x80) == 0x80) // Interrupt In endpoint found - index = BTD_EVENT_PIPE; - - else { - if ((pep->bmAttributes & 0x02) == 2) // bulk endpoint found - index = ((pep->bEndpointAddress & 0x80) == 0x80) ? BTD_DATAIN_PIPE : BTD_DATAOUT_PIPE; - else - return; - } - - // Fill the rest of endpoint data structure - epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F); - epInfo[index].maxPktSize = (uint8_t)pep->wMaxPacketSize; + //ErrorMessage(PSTR("Conf.Val"),conf); + //ErrorMessage(PSTR("Iface Num"),iface); + //ErrorMessage(PSTR("Alt.Set"),alt); + + if (alt) // wrong interface - by BT spec, no alt setting + return; + + bConfNum = conf; + uint8_t index; + + if ((pep->bmAttributes & 0x03) == 3 && (pep->bEndpointAddress & 0x80) == 0x80) // Interrupt In endpoint found + index = BTD_EVENT_PIPE; + + else { + if ((pep->bmAttributes & 0x02) == 2) // bulk endpoint found + index = ((pep->bEndpointAddress & 0x80) == 0x80) ? BTD_DATAIN_PIPE : BTD_DATAOUT_PIPE; + else + return; + } + + // Fill the rest of endpoint data structure + epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F); + epInfo[index].maxPktSize = (uint8_t)pep->wMaxPacketSize; #ifdef EXTRADEBUG - PrintEndpointDescriptor(pep); + PrintEndpointDescriptor(pep); #endif - if(pollInterval < pep->bInterval) // Set the polling interval as the largest polling interval obtained from endpoints - pollInterval = pep->bInterval; - bNumEP++; + if (pollInterval < pep->bInterval) // Set the polling interval as the largest polling interval obtained from endpoints + pollInterval = pep->bInterval; + bNumEP++; } + void BTD::PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr) { #ifdef EXTRADEBUG - Notify(PSTR("\r\nEndpoint descriptor:")); - Notify(PSTR("\r\nLength:\t\t")); - PrintHex(ep_ptr->bLength); - Notify(PSTR("\r\nType:\t\t")); - PrintHex(ep_ptr->bDescriptorType); - Notify(PSTR("\r\nAddress:\t")); - PrintHex(ep_ptr->bEndpointAddress); - Notify(PSTR("\r\nAttributes:\t")); - PrintHex(ep_ptr->bmAttributes); - Notify(PSTR("\r\nMaxPktSize:\t")); - PrintHex(ep_ptr->wMaxPacketSize); - Notify(PSTR("\r\nPoll Intrv:\t")); - PrintHex(ep_ptr->bInterval); + Notify(PSTR("\r\nEndpoint descriptor:"), 0x80); + Notify(PSTR("\r\nLength:\t\t"), 0x80); + PrintHex (ep_ptr->bLength, 0x80); + Notify(PSTR("\r\nType:\t\t"), 0x80); + PrintHex (ep_ptr->bDescriptorType, 0x80); + Notify(PSTR("\r\nAddress:\t"), 0x80); + PrintHex (ep_ptr->bEndpointAddress, 0x80); + Notify(PSTR("\r\nAttributes:\t"), 0x80); + PrintHex (ep_ptr->bmAttributes, 0x80); + Notify(PSTR("\r\nMaxPktSize:\t"), 0x80); + PrintHex (ep_ptr->wMaxPacketSize, 0x80); + Notify(PSTR("\r\nPoll Intrv:\t"), 0x80); + PrintHex (ep_ptr->bInterval, 0x80); #endif } /* Performs a cleanup after failed Init() attempt */ uint8_t BTD::Release() { - for (uint8_t i=0; iReset(); // Reset all Bluetooth services - pUsb->GetAddressPool().FreeAddress(bAddress); - bAddress = 0; - bPollEnable = false; - bNumEP = 1; // must have to be reset to 1 - return 0; + for (uint8_t i = 0; i < BTD_NUMSERVICES; i++) + if (btService[i]) + btService[i]->Reset(); // Reset all Bluetooth services + pUsb->GetAddressPool().FreeAddress(bAddress); + bAddress = 0; + bPollEnable = false; + bNumEP = 1; // must have to be reset to 1 + return 0; } + uint8_t BTD::Poll() { - if (!bPollEnable) - return 0; - if (qNextPollTime <= millis()) { // Don't poll if shorter than polling interval - qNextPollTime = millis() + pollInterval; // Set new poll time - HCI_event_task(); // poll the HCI event pipe - ACL_event_task(); // start polling the ACL input pipe too, though discard data until connected - } - return 0; + if (!bPollEnable) + return 0; + if (qNextPollTime <= millis()) { // Don't poll if shorter than polling interval + qNextPollTime = millis() + pollInterval; // Set new poll time + HCI_event_task(); // poll the HCI event pipe + ACL_event_task(); // start polling the ACL input pipe too, though discard data until connected + } + return 0; } void BTD::HCI_event_task() { - /* check the event pipe*/ - uint16_t MAX_BUFFER_SIZE = BULK_MAXPKTSIZE; // Request more than 16 bytes anyway, the inTransfer routine will take care of this - uint8_t rcode = pUsb->inTransfer(bAddress, epInfo[ BTD_EVENT_PIPE ].epAddr, &MAX_BUFFER_SIZE, hcibuf); // input on endpoint 1 - if(!rcode || rcode == hrNAK) // Check for errors - { - switch (hcibuf[0]) //switch on event type + /* check the event pipe*/ + uint16_t MAX_BUFFER_SIZE = BULK_MAXPKTSIZE; // Request more than 16 bytes anyway, the inTransfer routine will take care of this + uint8_t rcode = pUsb->inTransfer(bAddress, epInfo[ BTD_EVENT_PIPE ].epAddr, &MAX_BUFFER_SIZE, hcibuf); // input on endpoint 1 + if (!rcode || rcode == hrNAK) // Check for errors { - case EV_COMMAND_COMPLETE: - if (!hcibuf[5]) { // Check if command succeeded - hci_event_flag |= HCI_FLAG_CMD_COMPLETE; // set command complete flag - if((hcibuf[3] == 0x01) && (hcibuf[4] == 0x10)) { // parameters from read local version information - hci_version = hcibuf[6]; // Used to check if it supports 2.0+EDR - see http://www.bluetooth.org/Technical/AssignedNumbers/hci.htm - hci_event_flag |= HCI_FLAG_READ_VERSION; - } else if((hcibuf[3] == 0x09) && (hcibuf[4] == 0x10)) { // parameters from read local bluetooth address - for (uint8_t i = 0; i < 6; i++) - my_bdaddr[i] = hcibuf[6 + i]; - hci_event_flag |= HCI_FLAG_READ_BDADDR; - } - } - break; - - case EV_COMMAND_STATUS: - if(hcibuf[2]) { // show status on serial if not OK + switch (hcibuf[0]) //switch on event type + { + case EV_COMMAND_COMPLETE: + if (!hcibuf[5]) { // Check if command succeeded + hci_event_flag |= HCI_FLAG_CMD_COMPLETE; // set command complete flag + if ((hcibuf[3] == 0x01) && (hcibuf[4] == 0x10)) { // parameters from read local version information + hci_version = hcibuf[6]; // Used to check if it supports 2.0+EDR - see http://www.bluetooth.org/Technical/AssignedNumbers/hci.htm + hci_event_flag |= HCI_FLAG_READ_VERSION; + } else if ((hcibuf[3] == 0x09) && (hcibuf[4] == 0x10)) { // parameters from read local bluetooth address + for (uint8_t i = 0; i < 6; i++) + my_bdaddr[i] = hcibuf[6 + i]; + hci_event_flag |= HCI_FLAG_READ_BDADDR; + } + } + break; + + case EV_COMMAND_STATUS: + if (hcibuf[2]) { // show status on serial if not OK #ifdef DEBUG - Notify(PSTR("\r\nHCI Command Failed: ")); - PrintHex(hcibuf[2]); - Notify(PSTR(" ")); - PrintHex(hcibuf[4]); - Notify(PSTR(" ")); - PrintHex(hcibuf[5]); + Notify(PSTR("\r\nHCI Command Failed: "), 0x80); + PrintHex (hcibuf[2], 0x80); + Notify(PSTR(" "), 0x80); + PrintHex (hcibuf[4], 0x80); + Notify(PSTR(" "), 0x80); + PrintHex (hcibuf[5], 0x80); #endif - } - break; - - case EV_INQUIRY_COMPLETE: - if(inquiry_counter >= 5) { - inquiry_counter = 0; + } + break; + + case EV_INQUIRY_COMPLETE: + if (inquiry_counter >= 5) { + inquiry_counter = 0; #ifdef DEBUG - Notify(PSTR("\r\nCouldn't find Wiimote")); + Notify(PSTR("\r\nCouldn't find Wiimote"), 0x80); #endif - connectToWii = false; - pairWithWii = false; - hci_state = HCI_SCANNING_STATE; - } - inquiry_counter++; - break; - - case EV_INQUIRY_RESULT: - if (hcibuf[2]) { // Check that there is more than zero responses + connectToWii = false; + pairWithWii = false; + hci_state = HCI_SCANNING_STATE; + } + inquiry_counter++; + break; + + case EV_INQUIRY_RESULT: + if (hcibuf[2]) { // Check that there is more than zero responses #ifdef EXTRADEBUG - Notify(PSTR("\r\nNumber of responses: ")); - Serial.print(hcibuf[2]); + Notify(PSTR("\r\nNumber of responses: "), 0x80); + Serial.print(hcibuf[2]); #endif - for(uint8_t i = 0; i < hcibuf[2]; i++) { - if((hcibuf[4+8*hcibuf[2]+3*i] == 0x04 && hcibuf[5+8*hcibuf[2]+3*i] == 0x25 && hcibuf[6+8*hcibuf[2]+3*i] == 0x00) || (hcibuf[4+8*hcibuf[2]+3*i] == 0x08 && hcibuf[5+8*hcibuf[2]+3*i] == 0x05 && hcibuf[6+8*hcibuf[2]+3*i] == 0x00)) { // See http://bluetooth-pentest.narod.ru/software/bluetooth_class_of_device-service_generator.html and http://wiibrew.org/wiki/Wiimote#SDP_information - if(hcibuf[4+8*hcibuf[2]+3*i] == 0x08) // Check if it's the new Wiimote with motion plus inside that was detected - motionPlusInside = true; - else - motionPlusInside = false; - disc_bdaddr[0] = hcibuf[3+6*i]; - disc_bdaddr[1] = hcibuf[4+6*i]; - disc_bdaddr[2] = hcibuf[5+6*i]; - disc_bdaddr[3] = hcibuf[6+6*i]; - disc_bdaddr[4] = hcibuf[7+6*i]; - disc_bdaddr[5] = hcibuf[8+6*i]; - hci_event_flag |= HCI_FLAG_WII_FOUND; - break; - } + for (uint8_t i = 0; i < hcibuf[2]; i++) { + if ((hcibuf[4 + 8 * hcibuf[2] + 3 * i] == 0x04 && hcibuf[5 + 8 * hcibuf[2] + 3 * i] == 0x25 && hcibuf[6 + 8 * hcibuf[2] + 3 * i] == 0x00) || (hcibuf[4 + 8 * hcibuf[2] + 3 * i] == 0x08 && hcibuf[5 + 8 * hcibuf[2] + 3 * i] == 0x05 && hcibuf[6 + 8 * hcibuf[2] + 3 * i] == 0x00)) { // See http://bluetooth-pentest.narod.ru/software/bluetooth_class_of_device-service_generator.html and http://wiibrew.org/wiki/Wiimote#SDP_information + if (hcibuf[4 + 8 * hcibuf[2] + 3 * i] == 0x08) // Check if it's the new Wiimote with motion plus inside that was detected + motionPlusInside = true; + else + motionPlusInside = false; + disc_bdaddr[0] = hcibuf[3 + 6 * i]; + disc_bdaddr[1] = hcibuf[4 + 6 * i]; + disc_bdaddr[2] = hcibuf[5 + 6 * i]; + disc_bdaddr[3] = hcibuf[6 + 6 * i]; + disc_bdaddr[4] = hcibuf[7 + 6 * i]; + disc_bdaddr[5] = hcibuf[8 + 6 * i]; + hci_event_flag |= HCI_FLAG_WII_FOUND; + break; + } #ifdef EXTRADEBUG - else { - Notify(PSTR("\r\nClass of device: ")); - PrintHex(hcibuf[6+8*hcibuf[2]+3*i]); - Notify(PSTR(" ")); - PrintHex(hcibuf[5+8*hcibuf[2]+3*i]); - Notify(PSTR(" ")); - PrintHex(hcibuf[4+8*hcibuf[2]+3*i]); - } + else { + Notify(PSTR("\r\nClass of device: "), 0x80); + PrintHex (hcibuf[6 + 8 * hcibuf[2] + 3 * i], 0x80); + Notify(PSTR(" "), 0x80); + PrintHex (hcibuf[5 + 8 * hcibuf[2] + 3 * i], 0x80); + Notify(PSTR(" "), 0x80); + PrintHex (hcibuf[4 + 8 * hcibuf[2] + 3 * i], 0x80); + } #endif - } - } - break; - - case EV_CONNECT_COMPLETE: - hci_event_flag |= HCI_FLAG_CONNECT_EVENT; - if (!hcibuf[2]) { // check if connected OK - hci_handle = hcibuf[3] | ((hcibuf[4] & 0x0F) << 8); // store the handle for the ACL connection - hci_event_flag |= HCI_FLAG_CONN_COMPLETE; // set connection complete flag - } + } + } + break; + + case EV_CONNECT_COMPLETE: + hci_event_flag |= HCI_FLAG_CONNECT_EVENT; + if (!hcibuf[2]) { // check if connected OK + hci_handle = hcibuf[3] | ((hcibuf[4] & 0x0F) << 8); // store the handle for the ACL connection + hci_event_flag |= HCI_FLAG_CONN_COMPLETE; // set connection complete flag + } #ifdef EXTRADEBUG - else { - Notify(PSTR("\r\nConnection Failed")); - } + else { + Notify(PSTR("\r\nConnection Failed"), 0x80); + } #endif - break; - - case EV_DISCONNECT_COMPLETE: - if (!hcibuf[2]) { // check if disconnected OK - hci_event_flag |= HCI_FLAG_DISCONN_COMPLETE; // set disconnect command complete flag - hci_event_flag &= ~HCI_FLAG_CONN_COMPLETE; // clear connection complete flag - } - break; - - case EV_REMOTE_NAME_COMPLETE: - if (!hcibuf[2]) { // check if reading is OK - for (uint8_t i = 0; i < 30; i++) - remote_name[i] = hcibuf[9 + i]; //store first 30 bytes - hci_event_flag |= HCI_FLAG_REMOTE_NAME_COMPLETE; - } - break; - - case EV_INCOMING_CONNECT: - disc_bdaddr[0] = hcibuf[2]; - disc_bdaddr[1] = hcibuf[3]; - disc_bdaddr[2] = hcibuf[4]; - disc_bdaddr[3] = hcibuf[5]; - disc_bdaddr[4] = hcibuf[6]; - disc_bdaddr[5] = hcibuf[7]; - hci_event_flag |= HCI_FLAG_INCOMING_REQUEST; - break; - - case EV_PIN_CODE_REQUEST: - if(pairWithWii) { + break; + + case EV_DISCONNECT_COMPLETE: + if (!hcibuf[2]) { // check if disconnected OK + hci_event_flag |= HCI_FLAG_DISCONN_COMPLETE; // set disconnect command complete flag + hci_event_flag &= ~HCI_FLAG_CONN_COMPLETE; // clear connection complete flag + } + break; + + case EV_REMOTE_NAME_COMPLETE: + if (!hcibuf[2]) { // check if reading is OK + for (uint8_t i = 0; i < 30; i++) + remote_name[i] = hcibuf[9 + i]; //store first 30 bytes + hci_event_flag |= HCI_FLAG_REMOTE_NAME_COMPLETE; + } + break; + + case EV_INCOMING_CONNECT: + disc_bdaddr[0] = hcibuf[2]; + disc_bdaddr[1] = hcibuf[3]; + disc_bdaddr[2] = hcibuf[4]; + disc_bdaddr[3] = hcibuf[5]; + disc_bdaddr[4] = hcibuf[6]; + disc_bdaddr[5] = hcibuf[7]; + hci_event_flag |= HCI_FLAG_INCOMING_REQUEST; + break; + + case EV_PIN_CODE_REQUEST: + if (pairWithWii) { #ifdef DEBUG - Notify(PSTR("\r\nPairing with wiimote")); + Notify(PSTR("\r\nPairing with wiimote"), 0x80); #endif - hci_pin_code_request_reply(); - } - else if(btdPin != NULL) { + hci_pin_code_request_reply(); + } else if (btdPin != NULL) { #ifdef DEBUG - Notify(PSTR("\r\nBluetooth pin is set too: ")); - Serial.print(btdPin); + Notify(PSTR("\r\nBluetooth pin is set too: "), 0x80); + Serial.print(btdPin); #endif - hci_pin_code_request_reply(); - } - else { + hci_pin_code_request_reply(); + } else { #ifdef DEBUG - Notify(PSTR("\r\nNo pin was set")); + Notify(PSTR("\r\nNo pin was set"), 0x80); #endif - hci_pin_code_negative_request_reply(); - } - break; - - case EV_LINK_KEY_REQUEST: + hci_pin_code_negative_request_reply(); + } + break; + + case EV_LINK_KEY_REQUEST: #ifdef DEBUG - Notify(PSTR("\r\nReceived Key Request")); + Notify(PSTR("\r\nReceived Key Request"), 0x80); #endif - hci_link_key_request_negative_reply(); - break; - - case EV_AUTHENTICATION_COMPLETE: - if(pairWithWii && !connectToWii) { + hci_link_key_request_negative_reply(); + break; + + case EV_AUTHENTICATION_COMPLETE: + if (pairWithWii && !connectToWii) { #ifdef DEBUG - Notify(PSTR("\r\nPairing successful")); + Notify(PSTR("\r\nPairing successful"), 0x80); #endif - connectToWii = true; // Only send the ACL data to the Wii service - } - break; - /* We will just ignore the following events */ - case EV_NUM_COMPLETE_PKT: - case EV_ROLE_CHANGED: - case EV_PAGE_SCAN_REP_MODE: - case EV_LOOPBACK_COMMAND: - case EV_DATA_BUFFER_OVERFLOW: - case EV_CHANGE_CONNECTION_LINK: - case EV_MAX_SLOTS_CHANGE: - case EV_QOS_SETUP_COMPLETE: - case EV_LINK_KEY_NOTIFICATION: - case EV_ENCRYPTION_CHANGE: - case EV_READ_REMOTE_VERSION_INFORMATION_COMPLETE: - break; + connectToWii = true; // Only send the ACL data to the Wii service + } + break; + /* We will just ignore the following events */ + case EV_NUM_COMPLETE_PKT: + case EV_ROLE_CHANGED: + case EV_PAGE_SCAN_REP_MODE: + case EV_LOOPBACK_COMMAND: + case EV_DATA_BUFFER_OVERFLOW: + case EV_CHANGE_CONNECTION_LINK: + case EV_MAX_SLOTS_CHANGE: + case EV_QOS_SETUP_COMPLETE: + case EV_LINK_KEY_NOTIFICATION: + case EV_ENCRYPTION_CHANGE: + case EV_READ_REMOTE_VERSION_INFORMATION_COMPLETE: + break; #ifdef EXTRADEBUG - default: - if(hcibuf[0] != 0x00) { - Notify(PSTR("\r\nUnmanaged HCI Event: ")); - PrintHex(hcibuf[0]); - } - break; + default: + if (hcibuf[0] != 0x00) { + Notify(PSTR("\r\nUnmanaged HCI Event: "), 0x80); + PrintHex (hcibuf[0], 0x80); + } + break; #endif - } // switch - HCI_task(); - } + } // switch + HCI_task(); + } #ifdef EXTRADEBUG - else { - Notify(PSTR("\r\nHCI event error: ")); - PrintHex(rcode); - } + else { + Notify(PSTR("\r\nHCI event error: "), 0x80); + PrintHex (rcode, 0x80); + } #endif } /* Poll Bluetooth and print result */ void BTD::HCI_task() { - switch (hci_state){ - case HCI_INIT_STATE: - hci_counter++; - if (hci_counter > hci_num_reset_loops) { // wait until we have looped x times to clear any old events - hci_reset(); - hci_state = HCI_RESET_STATE; - hci_counter = 0; - } - break; - - case HCI_RESET_STATE: - hci_counter++; - if (hci_cmd_complete) { - hci_counter = 0; -#ifdef DEBUG - Notify(PSTR("\r\nHCI Reset complete")); -#endif - hci_state = HCI_CLASS_STATE; - hci_write_class_of_device(); - } - else if (hci_counter > hci_num_reset_loops) { - hci_num_reset_loops *= 10; - if(hci_num_reset_loops > 2000) - hci_num_reset_loops = 2000; -#ifdef DEBUG - Notify(PSTR("\r\nNo response to HCI Reset")); -#endif - hci_state = HCI_INIT_STATE; - hci_counter = 0; - } - break; - - case HCI_CLASS_STATE: - if(hci_cmd_complete) { -#ifdef DEBUG - Notify(PSTR("\r\nWrite class of device")); -#endif - hci_state = HCI_BDADDR_STATE; - hci_read_bdaddr(); - } - break; - - case HCI_BDADDR_STATE: - if (hci_read_bdaddr_complete) { -#ifdef DEBUG - Notify(PSTR("\r\nLocal Bluetooth Address: ")); - for(int8_t i = 5; i > 0;i--) { - PrintHex(my_bdaddr[i]); - Notify(PSTR(":")); - } - PrintHex(my_bdaddr[0]); -#endif - hci_read_local_version_information(); - hci_state = HCI_LOCAL_VERSION_STATE; - } - break; - - case HCI_LOCAL_VERSION_STATE: // The local version is used by the PS3BT class - if (hci_read_version_complete) { - if(btdName != NULL) { - hci_set_local_name(btdName); - hci_state = HCI_SET_NAME_STATE; - } else - hci_state = HCI_CHECK_WII_SERVICE; - } - break; - - case HCI_SET_NAME_STATE: - if (hci_cmd_complete) { -#ifdef DEBUG - Notify(PSTR("\r\nThe name is set to: ")); - Serial.print(btdName); -#endif - hci_state = HCI_CHECK_WII_SERVICE; - } - break; - - case HCI_CHECK_WII_SERVICE: - if(pairWithWii) { // Check if it should try to connect to a wiimote -#ifdef DEBUG - Notify(PSTR("\r\nStarting inquiry\r\nPress 1 & 2 on the Wiimote\r\nOr press sync if you are using a Wii U Pro Controller")); -#endif - hci_inquiry(); - hci_state = HCI_INQUIRY_STATE; - } - else - hci_state = HCI_SCANNING_STATE; // Don't try to connect to a Wiimote - break; - - case HCI_INQUIRY_STATE: - if(hci_wii_found) { - hci_inquiry_cancel(); // Stop inquiry -#ifdef DEBUG - Notify(PSTR("\r\nWiimote found")); - Notify(PSTR("\r\nNow just create the instance like so:")); - Notify(PSTR("\r\nWII Wii(&Btd);")); - Notify(PSTR("\r\nAnd then press any button on the Wiimote")); -#endif - if(motionPlusInside) { - hci_remote_name(); // We need to know the name to distinguish between a Wiimote and a Wii U Pro Controller - hci_state = HCI_REMOTE_NAME_STATE; - } else - hci_state = HCI_CONNECT_WII_STATE; - } - break; - - case HCI_CONNECT_WII_STATE: - if(hci_cmd_complete) { -#ifdef DEBUG - Notify(PSTR("\r\nConnecting to Wiimote")); -#endif - hci_connect(); - hci_state = HCI_CONNECTED_WII_STATE; - } - break; - - case HCI_CONNECTED_WII_STATE: - if(hci_connect_event) { - if(hci_connect_complete) { -#ifdef DEBUG - Notify(PSTR("\r\nConnected to Wiimote")); -#endif - hci_authentication_request(); // This will start the pairing with the wiimote - hci_state = HCI_SCANNING_STATE; - } else { -#ifdef DEBUG - Notify(PSTR("\r\nTrying to connect one more time...")); -#endif - hci_connect(); // Try to connect one more time - } - } - break; - - case HCI_SCANNING_STATE: - if(!connectToWii && !pairWithWii) { -#ifdef DEBUG - Notify(PSTR("\r\nWait For Incoming Connection Request")); -#endif - hci_write_scan_enable(); - watingForConnection = true; - hci_state = HCI_CONNECT_IN_STATE; - } - break; - - case HCI_CONNECT_IN_STATE: - if(hci_incoming_connect_request) { - watingForConnection = false; -#ifdef DEBUG - Notify(PSTR("\r\nIncoming Connection Request")); -#endif - hci_remote_name(); - hci_state = HCI_REMOTE_NAME_STATE; - } else if (hci_disconnect_complete) - hci_state = HCI_DISCONNECT_STATE; - break; - - case HCI_REMOTE_NAME_STATE: - if(hci_remote_name_complete) { -#ifdef DEBUG - Notify(PSTR("\r\nRemote Name: ")); - for (uint8_t i = 0; i < 30; i++) { - if(remote_name[i] == NULL) + switch (hci_state) { + case HCI_INIT_STATE: + hci_counter++; + if (hci_counter > hci_num_reset_loops) { // wait until we have looped x times to clear any old events + hci_reset(); + hci_state = HCI_RESET_STATE; + hci_counter = 0; + } break; - Serial.write(remote_name[i]); - } -#endif - if(strncmp((const char*)remote_name, "Nintendo", 8) == 0) { -#ifdef DEBUG - Notify(PSTR("\r\nWiimote is connecting")); -#endif - if(strncmp((const char*)remote_name, "Nintendo RVL-CNT-01-TR", 22) == 0) { -#ifdef DEBUG - Notify(PSTR(" with Motion Plus Inside")); -#endif - motionPlusInside = true; - } - else if(strncmp((const char*)remote_name, "Nintendo RVL-CNT-01-UC", 22) == 0) { -#ifdef DEBUG - Notify(PSTR(" - Wii U Pro Controller")); -#endif - motionPlusInside = true; - wiiUProController = true; - } else { - motionPlusInside = false; - wiiUProController = false; - } - incomingWii = true; - } - if(pairWithWii && motionPlusInside) - hci_state = HCI_CONNECT_WII_STATE; - else { - hci_accept_connection(); - hci_state = HCI_CONNECTED_STATE; - } - } - break; - - case HCI_CONNECTED_STATE: - if (hci_connect_complete) { -#ifdef DEBUG - Notify(PSTR("\r\nConnected to Device: ")); - for(int8_t i = 5; i>0;i--) { - PrintHex(disc_bdaddr[i]); - Notify(PSTR(":")); - } - PrintHex(disc_bdaddr[0]); -#endif - // Clear these flags for a new connection - l2capConnectionClaimed = false; - sdpConnectionClaimed = false; - rfcommConnectionClaimed = false; - - hci_event_flag = 0; - hci_state = HCI_DONE_STATE; - } - break; - case HCI_DONE_STATE: - hci_counter++; - if (hci_counter > 1000) { // Wait until we have looped 1000 times to make sure that the L2CAP connection has been started - hci_counter = 0; - hci_state = HCI_SCANNING_STATE; - } - break; - - case HCI_DISCONNECT_STATE: - if (hci_disconnect_complete) { + case HCI_RESET_STATE: + hci_counter++; + if (hci_cmd_complete) { + hci_counter = 0; #ifdef DEBUG - Notify(PSTR("\r\nHCI Disconnected from Device")); + Notify(PSTR("\r\nHCI Reset complete"), 0x80); #endif - hci_event_flag = 0; // Clear all flags - - // Reset all buffers - for (uint8_t i = 0; i < BULK_MAXPKTSIZE; i++) - hcibuf[i] = 0; - for (uint8_t i = 0; i < BULK_MAXPKTSIZE; i++) - l2capinbuf[i] = 0; - - hci_state = HCI_SCANNING_STATE; - } - break; - default: - break; - } + hci_state = HCI_CLASS_STATE; + hci_write_class_of_device(); + } else if (hci_counter > hci_num_reset_loops) { + hci_num_reset_loops *= 10; + if (hci_num_reset_loops > 2000) + hci_num_reset_loops = 2000; +#ifdef DEBUG + Notify(PSTR("\r\nNo response to HCI Reset"), 0x80); +#endif + hci_state = HCI_INIT_STATE; + hci_counter = 0; + } + break; + + case HCI_CLASS_STATE: + if (hci_cmd_complete) { +#ifdef DEBUG + Notify(PSTR("\r\nWrite class of device"), 0x80); +#endif + hci_state = HCI_BDADDR_STATE; + hci_read_bdaddr(); + } + break; + + case HCI_BDADDR_STATE: + if (hci_read_bdaddr_complete) { +#ifdef DEBUG + Notify(PSTR("\r\nLocal Bluetooth Address: "), 0x80); + for (int8_t i = 5; i > 0; i--) { + PrintHex (my_bdaddr[i], 0x80); + Notify(PSTR(":"), 0x80); + } + PrintHex (my_bdaddr[0], 0x80); +#endif + hci_read_local_version_information(); + hci_state = HCI_LOCAL_VERSION_STATE; + } + break; + + case HCI_LOCAL_VERSION_STATE: // The local version is used by the PS3BT class + if (hci_read_version_complete) { + if (btdName != NULL) { + hci_set_local_name(btdName); + hci_state = HCI_SET_NAME_STATE; + } else + hci_state = HCI_CHECK_WII_SERVICE; + } + break; + + case HCI_SET_NAME_STATE: + if (hci_cmd_complete) { +#ifdef DEBUG + Notify(PSTR("\r\nThe name is set to: "), 0x80); + Serial.print(btdName); +#endif + hci_state = HCI_CHECK_WII_SERVICE; + } + break; + + case HCI_CHECK_WII_SERVICE: + if (pairWithWii) { // Check if it should try to connect to a wiimote +#ifdef DEBUG + Notify(PSTR("\r\nStarting inquiry\r\nPress 1 & 2 on the Wiimote\r\nOr press sync if you are using a Wii U Pro Controller"), 0x80); +#endif + hci_inquiry(); + hci_state = HCI_INQUIRY_STATE; + } else + hci_state = HCI_SCANNING_STATE; // Don't try to connect to a Wiimote + break; + + case HCI_INQUIRY_STATE: + if (hci_wii_found) { + hci_inquiry_cancel(); // Stop inquiry +#ifdef DEBUG + Notify(PSTR("\r\nWiimote found"), 0x80); + Notify(PSTR("\r\nNow just create the instance like so:"), 0x80); + Notify(PSTR("\r\nWII Wii(&Btd);"), 0x80); + Notify(PSTR("\r\nAnd then press any button on the Wiimote"), 0x80); +#endif + if (motionPlusInside) { + hci_remote_name(); // We need to know the name to distinguish between a Wiimote and a Wii U Pro Controller + hci_state = HCI_REMOTE_NAME_STATE; + } else + hci_state = HCI_CONNECT_WII_STATE; + } + break; + + case HCI_CONNECT_WII_STATE: + if (hci_cmd_complete) { +#ifdef DEBUG + Notify(PSTR("\r\nConnecting to Wiimote"), 0x80); +#endif + hci_connect(); + hci_state = HCI_CONNECTED_WII_STATE; + } + break; + + case HCI_CONNECTED_WII_STATE: + if (hci_connect_event) { + if (hci_connect_complete) { +#ifdef DEBUG + Notify(PSTR("\r\nConnected to Wiimote"), 0x80); +#endif + hci_authentication_request(); // This will start the pairing with the wiimote + hci_state = HCI_SCANNING_STATE; + } else { +#ifdef DEBUG + Notify(PSTR("\r\nTrying to connect one more time..."), 0x80); +#endif + hci_connect(); // Try to connect one more time + } + } + break; + + case HCI_SCANNING_STATE: + if (!connectToWii && !pairWithWii) { +#ifdef DEBUG + Notify(PSTR("\r\nWait For Incoming Connection Request"), 0x80); +#endif + hci_write_scan_enable(); + watingForConnection = true; + hci_state = HCI_CONNECT_IN_STATE; + } + break; + + case HCI_CONNECT_IN_STATE: + if (hci_incoming_connect_request) { + watingForConnection = false; +#ifdef DEBUG + Notify(PSTR("\r\nIncoming Connection Request"), 0x80); +#endif + hci_remote_name(); + hci_state = HCI_REMOTE_NAME_STATE; + } else if (hci_disconnect_complete) + hci_state = HCI_DISCONNECT_STATE; + break; + + case HCI_REMOTE_NAME_STATE: + if (hci_remote_name_complete) { +#ifdef DEBUG + Notify(PSTR("\r\nRemote Name: "), 0x80); + for (uint8_t i = 0; i < 30; i++) { + if (remote_name[i] == NULL) + break; + Serial.write(remote_name[i]); + } +#endif + if (strncmp((const char*)remote_name, "Nintendo", 8) == 0) { +#ifdef DEBUG + Notify(PSTR("\r\nWiimote is connecting"), 0x80); +#endif + if (strncmp((const char*)remote_name, "Nintendo RVL-CNT-01-TR", 22) == 0) { +#ifdef DEBUG + Notify(PSTR(" with Motion Plus Inside"), 0x80); +#endif + motionPlusInside = true; + } else if (strncmp((const char*)remote_name, "Nintendo RVL-CNT-01-UC", 22) == 0) { +#ifdef DEBUG + Notify(PSTR(" - Wii U Pro Controller"), 0x80); +#endif + motionPlusInside = true; + wiiUProController = true; + } else { + motionPlusInside = false; + wiiUProController = false; + } + incomingWii = true; + } + if (pairWithWii && motionPlusInside) + hci_state = HCI_CONNECT_WII_STATE; + else { + hci_accept_connection(); + hci_state = HCI_CONNECTED_STATE; + } + } + break; + + case HCI_CONNECTED_STATE: + if (hci_connect_complete) { +#ifdef DEBUG + Notify(PSTR("\r\nConnected to Device: "), 0x80); + for (int8_t i = 5; i > 0; i--) { + PrintHex (disc_bdaddr[i], 0x80); + Notify(PSTR(":"), 0x80); + } + PrintHex (disc_bdaddr[0], 0x80); +#endif + // Clear these flags for a new connection + l2capConnectionClaimed = false; + sdpConnectionClaimed = false; + rfcommConnectionClaimed = false; + + hci_event_flag = 0; + hci_state = HCI_DONE_STATE; + } + break; + + case HCI_DONE_STATE: + hci_counter++; + if (hci_counter > 1000) { // Wait until we have looped 1000 times to make sure that the L2CAP connection has been started + hci_counter = 0; + hci_state = HCI_SCANNING_STATE; + } + break; + + case HCI_DISCONNECT_STATE: + if (hci_disconnect_complete) { +#ifdef DEBUG + Notify(PSTR("\r\nHCI Disconnected from Device"), 0x80); +#endif + hci_event_flag = 0; // Clear all flags + + // Reset all buffers + for (uint8_t i = 0; i < BULK_MAXPKTSIZE; i++) + hcibuf[i] = 0; + for (uint8_t i = 0; i < BULK_MAXPKTSIZE; i++) + l2capinbuf[i] = 0; + + hci_state = HCI_SCANNING_STATE; + } + break; + default: + break; + } } void BTD::ACL_event_task() { - uint16_t MAX_BUFFER_SIZE = BULK_MAXPKTSIZE; - uint8_t rcode = pUsb->inTransfer(bAddress, epInfo[ BTD_DATAIN_PIPE ].epAddr, &MAX_BUFFER_SIZE, l2capinbuf); // input on endpoint 2 - if(!rcode) { // Check for errors - for (uint8_t i=0; iACLData(l2capinbuf); - } + uint16_t MAX_BUFFER_SIZE = BULK_MAXPKTSIZE; + uint8_t rcode = pUsb->inTransfer(bAddress, epInfo[ BTD_DATAIN_PIPE ].epAddr, &MAX_BUFFER_SIZE, l2capinbuf); // input on endpoint 2 + if (!rcode) { // Check for errors + for (uint8_t i = 0; i < BTD_NUMSERVICES; i++) + if (btService[i]) + btService[i]->ACLData(l2capinbuf); + } #ifdef EXTRADEBUG - else if (rcode != hrNAK) { - Notify(PSTR("\r\nACL data in error: ")); - PrintHex(rcode); - } + else if (rcode != hrNAK) { + Notify(PSTR("\r\nACL data in error: "), 0x80); + PrintHex (rcode, 0x80); + } #endif - for (uint8_t i=0; iRun(); + for (uint8_t i = 0; i < BTD_NUMSERVICES; i++) + if (btService[i]) + btService[i]->Run(); } /************************************************************/ /* HCI Commands */ + /************************************************************/ void BTD::HCI_Command(uint8_t* data, uint16_t nbytes) { - hci_event_flag &= ~HCI_FLAG_CMD_COMPLETE; - pUsb->ctrlReq(bAddress, epInfo[ BTD_CONTROL_PIPE ].epAddr, bmREQ_HCI_OUT, 0x00, 0x00, 0x00 ,0x00, nbytes, nbytes, data, NULL); + hci_event_flag &= ~HCI_FLAG_CMD_COMPLETE; + pUsb->ctrlReq(bAddress, epInfo[ BTD_CONTROL_PIPE ].epAddr, bmREQ_HCI_OUT, 0x00, 0x00, 0x00, 0x00, nbytes, nbytes, data, NULL); } -void BTD::hci_reset() { - hci_event_flag = 0; // Clear all the flags - hcibuf[0] = 0x03; // HCI OCF = 3 - hcibuf[1] = 0x03 << 2; // HCI OGF = 3 - hcibuf[2] = 0x00; - HCI_Command(hcibuf, 3); -} -void BTD::hci_write_scan_enable() { - hci_event_flag &= ~HCI_FLAG_INCOMING_REQUEST; - hcibuf[0] = 0x1A; // HCI OCF = 1A - hcibuf[1] = 0x03 << 2; // HCI OGF = 3 - hcibuf[2] = 0x01; // parameter length = 1 - if(btdName != NULL) - hcibuf[3] = 0x03; // Inquiry Scan enabled. Page Scan enabled. - else - hcibuf[3] = 0x02; // Inquiry Scan disabled. Page Scan enabled. - HCI_Command(hcibuf, 4); -} -void BTD::hci_write_scan_disable() { - hcibuf[0] = 0x1A; // HCI OCF = 1A - hcibuf[1] = 0x03 << 2; // HCI OGF = 3 - hcibuf[2] = 0x01; // parameter length = 1 - hcibuf[3] = 0x00; // Inquiry Scan disabled. Page Scan disabled. - HCI_Command(hcibuf, 4); -} -void BTD::hci_read_bdaddr() { - hcibuf[0] = 0x09; // HCI OCF = 9 - hcibuf[1] = 0x04 << 2; // HCI OGF = 4 - hcibuf[2] = 0x00; - HCI_Command(hcibuf, 3); -} -void BTD::hci_read_local_version_information() { - hcibuf[0] = 0x01; // HCI OCF = 1 - hcibuf[1] = 0x04 << 2; // HCI OGF = 4 - hcibuf[2] = 0x00; - HCI_Command(hcibuf, 3); -} -void BTD::hci_accept_connection() { - hci_event_flag &= ~HCI_FLAG_CONN_COMPLETE; - hcibuf[0] = 0x09; // HCI OCF = 9 - hcibuf[1] = 0x01 << 2; // HCI OGF = 1 - hcibuf[2] = 0x07; // parameter length 7 - hcibuf[3] = disc_bdaddr[0]; // 6 octet bdaddr - hcibuf[4] = disc_bdaddr[1]; - hcibuf[5] = disc_bdaddr[2]; - hcibuf[6] = disc_bdaddr[3]; - hcibuf[7] = disc_bdaddr[4]; - hcibuf[8] = disc_bdaddr[5]; - hcibuf[9] = 0x00; //switch role to master - - HCI_Command(hcibuf, 10); -} -void BTD::hci_remote_name() { - hci_event_flag &= ~HCI_FLAG_REMOTE_NAME_COMPLETE; - hcibuf[0] = 0x19; // HCI OCF = 19 - hcibuf[1] = 0x01 << 2; // HCI OGF = 1 - hcibuf[2] = 0x0A; // parameter length = 10 - hcibuf[3] = disc_bdaddr[0]; // 6 octet bdaddr - hcibuf[4] = disc_bdaddr[1]; - hcibuf[5] = disc_bdaddr[2]; - hcibuf[6] = disc_bdaddr[3]; - hcibuf[7] = disc_bdaddr[4]; - hcibuf[8] = disc_bdaddr[5]; - hcibuf[9] = 0x01; //Page Scan Repetition Mode - hcibuf[10] = 0x00; //Reserved - hcibuf[11] = 0x00; //Clock offset - low byte - hcibuf[12] = 0x00; //Clock offset - high byte - - HCI_Command(hcibuf, 13); -} -void BTD::hci_set_local_name(const char* name) { - hcibuf[0] = 0x13; // HCI OCF = 13 - hcibuf[1] = 0x03 << 2; // HCI OGF = 3 - hcibuf[2] = strlen(name)+1; // parameter length = the length of the string + end byte - uint8_t i; - for(i = 0; i < strlen(name); i++) - hcibuf[i+3] = name[i]; - hcibuf[i+3] = 0x00; // End of string - HCI_Command(hcibuf, 4+strlen(name)); +void BTD::hci_reset() { + hci_event_flag = 0; // Clear all the flags + hcibuf[0] = 0x03; // HCI OCF = 3 + hcibuf[1] = 0x03 << 2; // HCI OGF = 3 + hcibuf[2] = 0x00; + HCI_Command(hcibuf, 3); } -void BTD::hci_inquiry() { - hci_event_flag &= ~HCI_FLAG_WII_FOUND; - hcibuf[0] = 0x01; - hcibuf[1] = 0x01 << 2; // HCI OGF = 1 - hcibuf[2] = 0x05; // Parameter Total Length = 5 - hcibuf[3] = 0x33; // LAP: Genera/Unlimited Inquiry Access Code (GIAC = 0x9E8B33) - see https://www.bluetooth.org/Technical/AssignedNumbers/baseband.htm - hcibuf[4] = 0x8B; - hcibuf[5] = 0x9E; - hcibuf[6] = 0x30; // Inquiry time = 61.44 sec (maximum) - hcibuf[7] = 0x0A; // 10 number of responses - - HCI_Command(hcibuf, 8); + +void BTD::hci_write_scan_enable() { + hci_event_flag &= ~HCI_FLAG_INCOMING_REQUEST; + hcibuf[0] = 0x1A; // HCI OCF = 1A + hcibuf[1] = 0x03 << 2; // HCI OGF = 3 + hcibuf[2] = 0x01; // parameter length = 1 + if (btdName != NULL) + hcibuf[3] = 0x03; // Inquiry Scan enabled. Page Scan enabled. + else + hcibuf[3] = 0x02; // Inquiry Scan disabled. Page Scan enabled. + HCI_Command(hcibuf, 4); } -void BTD::hci_inquiry_cancel() { - hcibuf[0] = 0x02; - hcibuf[1] = 0x01 << 2; // HCI OGF = 1 - hcibuf[2] = 0x0; // Parameter Total Length = 0 - - HCI_Command(hcibuf, 3); + +void BTD::hci_write_scan_disable() { + hcibuf[0] = 0x1A; // HCI OCF = 1A + hcibuf[1] = 0x03 << 2; // HCI OGF = 3 + hcibuf[2] = 0x01; // parameter length = 1 + hcibuf[3] = 0x00; // Inquiry Scan disabled. Page Scan disabled. + HCI_Command(hcibuf, 4); } -void BTD::hci_connect() { - hci_event_flag &= ~(HCI_FLAG_CONN_COMPLETE | HCI_FLAG_CONNECT_EVENT); - hcibuf[0] = 0x05; - hcibuf[1] = 0x01 << 2; // HCI OGF = 1 - hcibuf[2] = 0x0D; // parameter Total Length = 13 - hcibuf[3] = disc_bdaddr[0]; // 6 octet bdaddr - hcibuf[4] = disc_bdaddr[1]; - hcibuf[5] = disc_bdaddr[2]; - hcibuf[6] = disc_bdaddr[3]; - hcibuf[7] = disc_bdaddr[4]; - hcibuf[8] = disc_bdaddr[5]; - hcibuf[9] = 0x18; // DM1 or DH1 may be used - hcibuf[10] = 0xCC; // DM3, DH3, DM5, DH5 may be used - hcibuf[11] = 0x01; // Page repetition mode R1 - hcibuf[12] = 0x00; // Reserved - hcibuf[13] = 0x00; // Clock offset - hcibuf[14] = 0x00; // Invalid clock offset - hcibuf[15] = 0x00; // Do not allow role switch - - HCI_Command(hcibuf, 16); + +void BTD::hci_read_bdaddr() { + hcibuf[0] = 0x09; // HCI OCF = 9 + hcibuf[1] = 0x04 << 2; // HCI OGF = 4 + hcibuf[2] = 0x00; + HCI_Command(hcibuf, 3); } -void BTD::hci_pin_code_request_reply() { - hcibuf[0] = 0x0D; // HCI OCF = 0D - hcibuf[1] = 0x01 << 2; // HCI OGF = 1 - hcibuf[2] = 0x17; // parameter length 23 - hcibuf[3] = disc_bdaddr[0]; // 6 octet bdaddr - hcibuf[4] = disc_bdaddr[1]; - hcibuf[5] = disc_bdaddr[2]; - hcibuf[6] = disc_bdaddr[3]; - hcibuf[7] = disc_bdaddr[4]; - hcibuf[8] = disc_bdaddr[5]; - if(pairWithWii && !wiiUProController) { - hcibuf[9] = 6; // Pin length is the length of the bt address - hcibuf[10] = disc_bdaddr[0]; // The pin is the Wiimotes bt address backwards - hcibuf[11] = disc_bdaddr[1]; - hcibuf[12] = disc_bdaddr[2]; - hcibuf[13] = disc_bdaddr[3]; - hcibuf[14] = disc_bdaddr[4]; - hcibuf[15] = disc_bdaddr[5]; - for(uint8_t i = 16; i < 26; i++) - hcibuf[i] = 0x00; // The rest should be 0 - } else if(pairWithWii && wiiUProController) { -#ifdef DEBUG - Notify(PSTR("\r\nParing with Wii U Pro Controller")); -#endif - hcibuf[9] = 6; // Pin length is the length of the bt address - hcibuf[10] = my_bdaddr[0]; // The pin is the Bluetooth dongles bt address backwards - hcibuf[11] = my_bdaddr[1]; - hcibuf[12] = my_bdaddr[2]; - hcibuf[13] = my_bdaddr[3]; - hcibuf[14] = my_bdaddr[4]; - hcibuf[15] = my_bdaddr[5]; - for(uint8_t i = 16; i < 26; i++) - hcibuf[i] = 0x00; // The rest should be 0 - } else { - hcibuf[9] = strlen(btdPin); // Length of pin + +void BTD::hci_read_local_version_information() { + hcibuf[0] = 0x01; // HCI OCF = 1 + hcibuf[1] = 0x04 << 2; // HCI OGF = 4 + hcibuf[2] = 0x00; + HCI_Command(hcibuf, 3); +} + +void BTD::hci_accept_connection() { + hci_event_flag &= ~HCI_FLAG_CONN_COMPLETE; + hcibuf[0] = 0x09; // HCI OCF = 9 + hcibuf[1] = 0x01 << 2; // HCI OGF = 1 + hcibuf[2] = 0x07; // parameter length 7 + hcibuf[3] = disc_bdaddr[0]; // 6 octet bdaddr + hcibuf[4] = disc_bdaddr[1]; + hcibuf[5] = disc_bdaddr[2]; + hcibuf[6] = disc_bdaddr[3]; + hcibuf[7] = disc_bdaddr[4]; + hcibuf[8] = disc_bdaddr[5]; + hcibuf[9] = 0x00; //switch role to master + + HCI_Command(hcibuf, 10); +} + +void BTD::hci_remote_name() { + hci_event_flag &= ~HCI_FLAG_REMOTE_NAME_COMPLETE; + hcibuf[0] = 0x19; // HCI OCF = 19 + hcibuf[1] = 0x01 << 2; // HCI OGF = 1 + hcibuf[2] = 0x0A; // parameter length = 10 + hcibuf[3] = disc_bdaddr[0]; // 6 octet bdaddr + hcibuf[4] = disc_bdaddr[1]; + hcibuf[5] = disc_bdaddr[2]; + hcibuf[6] = disc_bdaddr[3]; + hcibuf[7] = disc_bdaddr[4]; + hcibuf[8] = disc_bdaddr[5]; + hcibuf[9] = 0x01; //Page Scan Repetition Mode + hcibuf[10] = 0x00; //Reserved + hcibuf[11] = 0x00; //Clock offset - low byte + hcibuf[12] = 0x00; //Clock offset - high byte + + HCI_Command(hcibuf, 13); +} + +void BTD::hci_set_local_name(const char* name) { + hcibuf[0] = 0x13; // HCI OCF = 13 + hcibuf[1] = 0x03 << 2; // HCI OGF = 3 + hcibuf[2] = strlen(name) + 1; // parameter length = the length of the string + end byte uint8_t i; - for(i = 0; i < strlen(btdPin); i++) // The maximum size of the pin is 16 - hcibuf[i+10] = btdPin[i]; - for(;i < 16; i++) - hcibuf[i+10] = 0x00; // The rest should be 0 - } - - HCI_Command(hcibuf, 26); + for (i = 0; i < strlen(name); i++) + hcibuf[i + 3] = name[i]; + hcibuf[i + 3] = 0x00; // End of string + + HCI_Command(hcibuf, 4 + strlen(name)); } + +void BTD::hci_inquiry() { + hci_event_flag &= ~HCI_FLAG_WII_FOUND; + hcibuf[0] = 0x01; + hcibuf[1] = 0x01 << 2; // HCI OGF = 1 + hcibuf[2] = 0x05; // Parameter Total Length = 5 + hcibuf[3] = 0x33; // LAP: Genera/Unlimited Inquiry Access Code (GIAC = 0x9E8B33) - see https://www.bluetooth.org/Technical/AssignedNumbers/baseband.htm + hcibuf[4] = 0x8B; + hcibuf[5] = 0x9E; + hcibuf[6] = 0x30; // Inquiry time = 61.44 sec (maximum) + hcibuf[7] = 0x0A; // 10 number of responses + + HCI_Command(hcibuf, 8); +} + +void BTD::hci_inquiry_cancel() { + hcibuf[0] = 0x02; + hcibuf[1] = 0x01 << 2; // HCI OGF = 1 + hcibuf[2] = 0x0; // Parameter Total Length = 0 + + HCI_Command(hcibuf, 3); +} + +void BTD::hci_connect() { + hci_event_flag &= ~(HCI_FLAG_CONN_COMPLETE | HCI_FLAG_CONNECT_EVENT); + hcibuf[0] = 0x05; + hcibuf[1] = 0x01 << 2; // HCI OGF = 1 + hcibuf[2] = 0x0D; // parameter Total Length = 13 + hcibuf[3] = disc_bdaddr[0]; // 6 octet bdaddr + hcibuf[4] = disc_bdaddr[1]; + hcibuf[5] = disc_bdaddr[2]; + hcibuf[6] = disc_bdaddr[3]; + hcibuf[7] = disc_bdaddr[4]; + hcibuf[8] = disc_bdaddr[5]; + hcibuf[9] = 0x18; // DM1 or DH1 may be used + hcibuf[10] = 0xCC; // DM3, DH3, DM5, DH5 may be used + hcibuf[11] = 0x01; // Page repetition mode R1 + hcibuf[12] = 0x00; // Reserved + hcibuf[13] = 0x00; // Clock offset + hcibuf[14] = 0x00; // Invalid clock offset + hcibuf[15] = 0x00; // Do not allow role switch + + HCI_Command(hcibuf, 16); +} + +void BTD::hci_pin_code_request_reply() { + hcibuf[0] = 0x0D; // HCI OCF = 0D + hcibuf[1] = 0x01 << 2; // HCI OGF = 1 + hcibuf[2] = 0x17; // parameter length 23 + hcibuf[3] = disc_bdaddr[0]; // 6 octet bdaddr + hcibuf[4] = disc_bdaddr[1]; + hcibuf[5] = disc_bdaddr[2]; + hcibuf[6] = disc_bdaddr[3]; + hcibuf[7] = disc_bdaddr[4]; + hcibuf[8] = disc_bdaddr[5]; + if (pairWithWii && !wiiUProController) { + hcibuf[9] = 6; // Pin length is the length of the bt address + hcibuf[10] = disc_bdaddr[0]; // The pin is the Wiimotes bt address backwards + hcibuf[11] = disc_bdaddr[1]; + hcibuf[12] = disc_bdaddr[2]; + hcibuf[13] = disc_bdaddr[3]; + hcibuf[14] = disc_bdaddr[4]; + hcibuf[15] = disc_bdaddr[5]; + for (uint8_t i = 16; i < 26; i++) + hcibuf[i] = 0x00; // The rest should be 0 + } else if (pairWithWii && wiiUProController) { +#ifdef DEBUG + Notify(PSTR("\r\nParing with Wii U Pro Controller"), 0x80); +#endif + hcibuf[9] = 6; // Pin length is the length of the bt address + hcibuf[10] = my_bdaddr[0]; // The pin is the Bluetooth dongles bt address backwards + hcibuf[11] = my_bdaddr[1]; + hcibuf[12] = my_bdaddr[2]; + hcibuf[13] = my_bdaddr[3]; + hcibuf[14] = my_bdaddr[4]; + hcibuf[15] = my_bdaddr[5]; + for (uint8_t i = 16; i < 26; i++) + hcibuf[i] = 0x00; // The rest should be 0 + } else { + hcibuf[9] = strlen(btdPin); // Length of pin + uint8_t i; + for (i = 0; i < strlen(btdPin); i++) // The maximum size of the pin is 16 + hcibuf[i + 10] = btdPin[i]; + for (; i < 16; i++) + hcibuf[i + 10] = 0x00; // The rest should be 0 + } + + HCI_Command(hcibuf, 26); +} + void BTD::hci_pin_code_negative_request_reply() { - hcibuf[0] = 0x0E; // HCI OCF = 0E - hcibuf[1] = 0x01 << 2; // HCI OGF = 1 - hcibuf[2] = 0x06; // parameter length 6 - hcibuf[3] = disc_bdaddr[0]; // 6 octet bdaddr - hcibuf[4] = disc_bdaddr[1]; - hcibuf[5] = disc_bdaddr[2]; - hcibuf[6] = disc_bdaddr[3]; - hcibuf[7] = disc_bdaddr[4]; - hcibuf[8] = disc_bdaddr[5]; - - HCI_Command(hcibuf, 9); + hcibuf[0] = 0x0E; // HCI OCF = 0E + hcibuf[1] = 0x01 << 2; // HCI OGF = 1 + hcibuf[2] = 0x06; // parameter length 6 + hcibuf[3] = disc_bdaddr[0]; // 6 octet bdaddr + hcibuf[4] = disc_bdaddr[1]; + hcibuf[5] = disc_bdaddr[2]; + hcibuf[6] = disc_bdaddr[3]; + hcibuf[7] = disc_bdaddr[4]; + hcibuf[8] = disc_bdaddr[5]; + + HCI_Command(hcibuf, 9); } + void BTD::hci_link_key_request_negative_reply() { - hcibuf[0] = 0x0C; // HCI OCF = 0C - hcibuf[1] = 0x01 << 2; // HCI OGF = 1 - hcibuf[2] = 0x06; // parameter length 6 - hcibuf[3] = disc_bdaddr[0]; // 6 octet bdaddr - hcibuf[4] = disc_bdaddr[1]; - hcibuf[5] = disc_bdaddr[2]; - hcibuf[6] = disc_bdaddr[3]; - hcibuf[7] = disc_bdaddr[4]; - hcibuf[8] = disc_bdaddr[5]; - - HCI_Command(hcibuf, 9); + hcibuf[0] = 0x0C; // HCI OCF = 0C + hcibuf[1] = 0x01 << 2; // HCI OGF = 1 + hcibuf[2] = 0x06; // parameter length 6 + hcibuf[3] = disc_bdaddr[0]; // 6 octet bdaddr + hcibuf[4] = disc_bdaddr[1]; + hcibuf[5] = disc_bdaddr[2]; + hcibuf[6] = disc_bdaddr[3]; + hcibuf[7] = disc_bdaddr[4]; + hcibuf[8] = disc_bdaddr[5]; + + HCI_Command(hcibuf, 9); } + void BTD::hci_authentication_request() { - hcibuf[0] = 0x11; // HCI OCF = 11 - hcibuf[1] = 0x01 << 2; // HCI OGF = 1 - hcibuf[2] = 0x02; // parameter length = 2 - hcibuf[3] = (uint8_t)(hci_handle & 0xFF);//connection handle - low byte - hcibuf[4] = (uint8_t)((hci_handle >> 8) & 0x0F);//connection handle - high byte - - HCI_Command(hcibuf, 5); + hcibuf[0] = 0x11; // HCI OCF = 11 + hcibuf[1] = 0x01 << 2; // HCI OGF = 1 + hcibuf[2] = 0x02; // parameter length = 2 + hcibuf[3] = (uint8_t)(hci_handle & 0xFF); //connection handle - low byte + hcibuf[4] = (uint8_t)((hci_handle >> 8) & 0x0F); //connection handle - high byte + + HCI_Command(hcibuf, 5); } + void BTD::hci_disconnect(uint16_t handle) { // This is called by the different services - hci_event_flag &= ~HCI_FLAG_DISCONN_COMPLETE; - hcibuf[0] = 0x06; // HCI OCF = 6 - hcibuf[1] = 0x01 << 2; // HCI OGF = 1 - hcibuf[2] = 0x03; // parameter length = 3 - hcibuf[3] = (uint8_t)(handle & 0xFF);//connection handle - low byte - hcibuf[4] = (uint8_t)((handle >> 8) & 0x0F);//connection handle - high byte - hcibuf[5] = 0x13; // reason - - HCI_Command(hcibuf, 6); + hci_event_flag &= ~HCI_FLAG_DISCONN_COMPLETE; + hcibuf[0] = 0x06; // HCI OCF = 6 + hcibuf[1] = 0x01 << 2; // HCI OGF = 1 + hcibuf[2] = 0x03; // parameter length = 3 + hcibuf[3] = (uint8_t)(handle & 0xFF); //connection handle - low byte + hcibuf[4] = (uint8_t)((handle >> 8) & 0x0F); //connection handle - high byte + hcibuf[5] = 0x13; // reason + + HCI_Command(hcibuf, 6); } + void BTD::hci_write_class_of_device() { // See http://bluetooth-pentest.narod.ru/software/bluetooth_class_of_device-service_generator.html - hcibuf[0] = 0x24; // HCI OCF = 3 - hcibuf[1] = 0x03 << 2; // HCI OGF = 3 - hcibuf[2] = 0x03; // parameter length = 3 - hcibuf[3] = 0x04; // Robot - hcibuf[4] = 0x08; // Toy - hcibuf[5] = 0x00; - HCI_Command(hcibuf, 6); + hcibuf[0] = 0x24; // HCI OCF = 3 + hcibuf[1] = 0x03 << 2; // HCI OGF = 3 + hcibuf[2] = 0x03; // parameter length = 3 + hcibuf[3] = 0x04; // Robot + hcibuf[4] = 0x08; // Toy + hcibuf[5] = 0x00; + HCI_Command(hcibuf, 6); } /******************************************************************* * * @@ -1029,174 +1043,183 @@ void BTD::hci_write_class_of_device() { // See http://bluetooth-pentest.narod.ru */ /************************************************************/ /* L2CAP Commands */ + /************************************************************/ void BTD::L2CAP_Command(uint16_t handle, uint8_t* data, uint8_t nbytes, uint8_t channelLow, uint8_t channelHigh) { - uint8_t buf[8+nbytes]; - buf[0] = (uint8_t)(handle & 0xff); // HCI handle with PB,BC flag - buf[1] = (uint8_t)(((handle >> 8) & 0x0f) | 0x20); - buf[2] = (uint8_t)((4 + nbytes) & 0xff); // HCI ACL total data length - buf[3] = (uint8_t)((4 + nbytes) >> 8); - buf[4] = (uint8_t)(nbytes & 0xff); // L2CAP header: Length - buf[5] = (uint8_t)(nbytes >> 8); - buf[6] = channelLow; - buf[7] = channelHigh; - - for (uint16_t i = 0; i < nbytes; i++) // L2CAP C-frame - buf[8 + i] = data[i]; - - uint8_t rcode = pUsb->outTransfer(bAddress, epInfo[ BTD_DATAOUT_PIPE ].epAddr, (8 + nbytes), buf); - if(rcode) { - delay(100); // This small delay prevents it from overflowing if it fails + uint8_t buf[8 + nbytes]; + buf[0] = (uint8_t)(handle & 0xff); // HCI handle with PB,BC flag + buf[1] = (uint8_t)(((handle >> 8) & 0x0f) | 0x20); + buf[2] = (uint8_t)((4 + nbytes) & 0xff); // HCI ACL total data length + buf[3] = (uint8_t)((4 + nbytes) >> 8); + buf[4] = (uint8_t)(nbytes & 0xff); // L2CAP header: Length + buf[5] = (uint8_t)(nbytes >> 8); + buf[6] = channelLow; + buf[7] = channelHigh; + + for (uint16_t i = 0; i < nbytes; i++) // L2CAP C-frame + buf[8 + i] = data[i]; + + uint8_t rcode = pUsb->outTransfer(bAddress, epInfo[ BTD_DATAOUT_PIPE ].epAddr, (8 + nbytes), buf); + if (rcode) { + delay(100); // This small delay prevents it from overflowing if it fails #ifdef DEBUG - Notify(PSTR("\r\nError sending L2CAP message: 0x")); - PrintHex(rcode); - Notify(PSTR(" - Channel ID: ")); - Serial.print(channelHigh); - Notify(PSTR(" ")); - Serial.print(channelLow); -#endif - } + Notify(PSTR("\r\nError sending L2CAP message: 0x"), 0x80); + PrintHex (rcode, 0x80); + Notify(PSTR(" - Channel ID: "), 0x80); + Serial.print(channelHigh); + Notify(PSTR(" "), 0x80); + Serial.print(channelLow); +#endif + } } + void BTD::l2cap_connection_request(uint16_t handle, uint8_t rxid, uint8_t* scid, uint16_t psm) { - l2capoutbuf[0] = L2CAP_CMD_CONNECTION_REQUEST; // Code - l2capoutbuf[1] = rxid; // Identifier - l2capoutbuf[2] = 0x04; // Length - l2capoutbuf[3] = 0x00; - l2capoutbuf[4] = (uint8_t)(psm & 0xff); // PSM - l2capoutbuf[5] = (uint8_t)(psm >> 8); - l2capoutbuf[6] = scid[0]; // Source CID - l2capoutbuf[7] = scid[1]; - - L2CAP_Command(handle, l2capoutbuf, 8); + l2capoutbuf[0] = L2CAP_CMD_CONNECTION_REQUEST; // Code + l2capoutbuf[1] = rxid; // Identifier + l2capoutbuf[2] = 0x04; // Length + l2capoutbuf[3] = 0x00; + l2capoutbuf[4] = (uint8_t)(psm & 0xff); // PSM + l2capoutbuf[5] = (uint8_t)(psm >> 8); + l2capoutbuf[6] = scid[0]; // Source CID + l2capoutbuf[7] = scid[1]; + + L2CAP_Command(handle, l2capoutbuf, 8); } -void BTD::l2cap_connection_response(uint16_t handle, uint8_t rxid, uint8_t* dcid, uint8_t* scid, uint8_t result) { - l2capoutbuf[0] = L2CAP_CMD_CONNECTION_RESPONSE; // Code - l2capoutbuf[1] = rxid; // Identifier - l2capoutbuf[2] = 0x08; // Length - l2capoutbuf[3] = 0x00; - l2capoutbuf[4] = dcid[0]; // Destination CID - l2capoutbuf[5] = dcid[1]; - l2capoutbuf[6] = scid[0]; // Source CID - l2capoutbuf[7] = scid[1]; - l2capoutbuf[8] = result; // Result: Pending or Success - l2capoutbuf[9] = 0x00; - l2capoutbuf[10] = 0x00; // No further information - l2capoutbuf[11] = 0x00; - - L2CAP_Command(handle, l2capoutbuf, 12); -} + +void BTD::l2cap_connection_response(uint16_t handle, uint8_t rxid, uint8_t* dcid, uint8_t* scid, uint8_t result) { + l2capoutbuf[0] = L2CAP_CMD_CONNECTION_RESPONSE; // Code + l2capoutbuf[1] = rxid; // Identifier + l2capoutbuf[2] = 0x08; // Length + l2capoutbuf[3] = 0x00; + l2capoutbuf[4] = dcid[0]; // Destination CID + l2capoutbuf[5] = dcid[1]; + l2capoutbuf[6] = scid[0]; // Source CID + l2capoutbuf[7] = scid[1]; + l2capoutbuf[8] = result; // Result: Pending or Success + l2capoutbuf[9] = 0x00; + l2capoutbuf[10] = 0x00; // No further information + l2capoutbuf[11] = 0x00; + + L2CAP_Command(handle, l2capoutbuf, 12); +} + void BTD::l2cap_config_request(uint16_t handle, uint8_t rxid, uint8_t* dcid) { - l2capoutbuf[0] = L2CAP_CMD_CONFIG_REQUEST; // Code - l2capoutbuf[1] = rxid; // Identifier - l2capoutbuf[2] = 0x08; // Length - l2capoutbuf[3] = 0x00; - l2capoutbuf[4] = dcid[0]; // Destination CID - l2capoutbuf[5] = dcid[1]; - l2capoutbuf[6] = 0x00; // Flags - l2capoutbuf[7] = 0x00; - l2capoutbuf[8] = 0x01; // Config Opt: type = MTU (Maximum Transmission Unit) - Hint - l2capoutbuf[9] = 0x02; // Config Opt: length - l2capoutbuf[10] = 0xFF; // MTU - l2capoutbuf[11] = 0xFF; - - L2CAP_Command(handle, l2capoutbuf, 12); + l2capoutbuf[0] = L2CAP_CMD_CONFIG_REQUEST; // Code + l2capoutbuf[1] = rxid; // Identifier + l2capoutbuf[2] = 0x08; // Length + l2capoutbuf[3] = 0x00; + l2capoutbuf[4] = dcid[0]; // Destination CID + l2capoutbuf[5] = dcid[1]; + l2capoutbuf[6] = 0x00; // Flags + l2capoutbuf[7] = 0x00; + l2capoutbuf[8] = 0x01; // Config Opt: type = MTU (Maximum Transmission Unit) - Hint + l2capoutbuf[9] = 0x02; // Config Opt: length + l2capoutbuf[10] = 0xFF; // MTU + l2capoutbuf[11] = 0xFF; + + L2CAP_Command(handle, l2capoutbuf, 12); } -void BTD::l2cap_config_response(uint16_t handle, uint8_t rxid, uint8_t* scid) { - l2capoutbuf[0] = L2CAP_CMD_CONFIG_RESPONSE; // Code - l2capoutbuf[1] = rxid; // Identifier - l2capoutbuf[2] = 0x0A; // Length - l2capoutbuf[3] = 0x00; - l2capoutbuf[4] = scid[0]; // Source CID - l2capoutbuf[5] = scid[1]; - l2capoutbuf[6] = 0x00; // Flag - l2capoutbuf[7] = 0x00; - l2capoutbuf[8] = 0x00; // Result - l2capoutbuf[9] = 0x00; - l2capoutbuf[10] = 0x01; // Config - l2capoutbuf[11] = 0x02; - l2capoutbuf[12] = 0xA0; - l2capoutbuf[13] = 0x02; - - L2CAP_Command(handle, l2capoutbuf, 14); + +void BTD::l2cap_config_response(uint16_t handle, uint8_t rxid, uint8_t* scid) { + l2capoutbuf[0] = L2CAP_CMD_CONFIG_RESPONSE; // Code + l2capoutbuf[1] = rxid; // Identifier + l2capoutbuf[2] = 0x0A; // Length + l2capoutbuf[3] = 0x00; + l2capoutbuf[4] = scid[0]; // Source CID + l2capoutbuf[5] = scid[1]; + l2capoutbuf[6] = 0x00; // Flag + l2capoutbuf[7] = 0x00; + l2capoutbuf[8] = 0x00; // Result + l2capoutbuf[9] = 0x00; + l2capoutbuf[10] = 0x01; // Config + l2capoutbuf[11] = 0x02; + l2capoutbuf[12] = 0xA0; + l2capoutbuf[13] = 0x02; + + L2CAP_Command(handle, l2capoutbuf, 14); } + void BTD::l2cap_disconnection_request(uint16_t handle, uint8_t rxid, uint8_t* dcid, uint8_t* scid) { - l2capoutbuf[0] = L2CAP_CMD_DISCONNECT_REQUEST; // Code - l2capoutbuf[1] = rxid; // Identifier - l2capoutbuf[2] = 0x04; // Length - l2capoutbuf[3] = 0x00; - l2capoutbuf[4] = dcid[0]; - l2capoutbuf[5] = dcid[1]; - l2capoutbuf[6] = scid[0]; - l2capoutbuf[7] = scid[1]; - L2CAP_Command(handle, l2capoutbuf, 8); + l2capoutbuf[0] = L2CAP_CMD_DISCONNECT_REQUEST; // Code + l2capoutbuf[1] = rxid; // Identifier + l2capoutbuf[2] = 0x04; // Length + l2capoutbuf[3] = 0x00; + l2capoutbuf[4] = dcid[0]; + l2capoutbuf[5] = dcid[1]; + l2capoutbuf[6] = scid[0]; + l2capoutbuf[7] = scid[1]; + L2CAP_Command(handle, l2capoutbuf, 8); } + void BTD::l2cap_disconnection_response(uint16_t handle, uint8_t rxid, uint8_t* dcid, uint8_t* scid) { - l2capoutbuf[0] = L2CAP_CMD_DISCONNECT_RESPONSE; // Code - l2capoutbuf[1] = rxid; // Identifier - l2capoutbuf[2] = 0x04; // Length - l2capoutbuf[3] = 0x00; - l2capoutbuf[4] = dcid[0]; - l2capoutbuf[5] = dcid[1]; - l2capoutbuf[6] = scid[0]; - l2capoutbuf[7] = scid[1]; - L2CAP_Command(handle, l2capoutbuf, 8); + l2capoutbuf[0] = L2CAP_CMD_DISCONNECT_RESPONSE; // Code + l2capoutbuf[1] = rxid; // Identifier + l2capoutbuf[2] = 0x04; // Length + l2capoutbuf[3] = 0x00; + l2capoutbuf[4] = dcid[0]; + l2capoutbuf[5] = dcid[1]; + l2capoutbuf[6] = scid[0]; + l2capoutbuf[7] = scid[1]; + L2CAP_Command(handle, l2capoutbuf, 8); } + void BTD::l2cap_information_response(uint16_t handle, uint8_t rxid, uint8_t infoTypeLow, uint8_t infoTypeHigh) { - l2capoutbuf[0] = L2CAP_CMD_INFORMATION_RESPONSE; // Code - l2capoutbuf[1] = rxid; // Identifier - l2capoutbuf[2] = 0x08; // Length - l2capoutbuf[3] = 0x00; - l2capoutbuf[4] = infoTypeLow; - l2capoutbuf[5] = infoTypeHigh; - l2capoutbuf[6] = 0x00; // Result = success - l2capoutbuf[7] = 0x00; // Result = success - l2capoutbuf[8] = 0x00; - l2capoutbuf[9] = 0x00; - l2capoutbuf[10] = 0x00; - l2capoutbuf[11] = 0x00; - L2CAP_Command(handle, l2capoutbuf, 12); + l2capoutbuf[0] = L2CAP_CMD_INFORMATION_RESPONSE; // Code + l2capoutbuf[1] = rxid; // Identifier + l2capoutbuf[2] = 0x08; // Length + l2capoutbuf[3] = 0x00; + l2capoutbuf[4] = infoTypeLow; + l2capoutbuf[5] = infoTypeHigh; + l2capoutbuf[6] = 0x00; // Result = success + l2capoutbuf[7] = 0x00; // Result = success + l2capoutbuf[8] = 0x00; + l2capoutbuf[9] = 0x00; + l2capoutbuf[10] = 0x00; + l2capoutbuf[11] = 0x00; + L2CAP_Command(handle, l2capoutbuf, 12); } /* PS3 Commands - only set Bluetooth address is implemented */ void BTD::setBdaddr(uint8_t* BDADDR) { - /* Set the internal bluetooth address */ - uint8_t buf[8]; - buf[0] = 0x01; - buf[1] = 0x00; - for (uint8_t i = 0; i < 6; i++) - buf[i+2] = BDADDR[5 - i];//Copy into buffer, has to be written reversed - - //bmRequest = Host to device (0x00) | Class (0x20) | Interface (0x01) = 0x21, bRequest = Set Report (0x09), Report ID (0xF5), Report Type (Feature 0x03), interface (0x00), datalength, datalength, data) - pUsb->ctrlReq(bAddress,epInfo[BTD_CONTROL_PIPE].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0xF5, 0x03, 0x00, 8, 8, buf, NULL); + /* Set the internal bluetooth address */ + uint8_t buf[8]; + buf[0] = 0x01; + buf[1] = 0x00; + for (uint8_t i = 0; i < 6; i++) + buf[i + 2] = BDADDR[5 - i]; //Copy into buffer, has to be written reversed + + //bmRequest = Host to device (0x00) | Class (0x20) | Interface (0x01) = 0x21, bRequest = Set Report (0x09), Report ID (0xF5), Report Type (Feature 0x03), interface (0x00), datalength, datalength, data) + pUsb->ctrlReq(bAddress, epInfo[BTD_CONTROL_PIPE].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0xF5, 0x03, 0x00, 8, 8, buf, NULL); #ifdef DEBUG - Notify(PSTR("\r\nBluetooth Address was set to: ")); - for(int8_t i = 5; i > 0; i--) { - PrintHex(my_bdaddr[i]); - Notify(PSTR(":")); - } - PrintHex(my_bdaddr[0]); + Notify(PSTR("\r\nBluetooth Address was set to: "), 0x80); + for (int8_t i = 5; i > 0; i--) { + PrintHex (my_bdaddr[i], 0x80); + Notify(PSTR(":"), 0x80); + } + PrintHex (my_bdaddr[0], 0x80); #endif } + void BTD::setMoveBdaddr(uint8_t* BDADDR) { - /* Set the internal bluetooth address */ - uint8_t buf[11]; - buf[0] = 0x05; - buf[7] = 0x10; - buf[8] = 0x01; - buf[9] = 0x02; - buf[10] = 0x12; - - for (uint8_t i = 0; i < 6; i++) - buf[i + 1] = BDADDR[i]; - - //bmRequest = Host to device (0x00) | Class (0x20) | Interface (0x01) = 0x21, bRequest = Set Report (0x09), Report ID (0x05), Report Type (Feature 0x03), interface (0x00), datalength, datalength, data) - pUsb->ctrlReq(bAddress,epInfo[BTD_CONTROL_PIPE].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0x05, 0x03, 0x00,11,11, buf, NULL); + /* Set the internal bluetooth address */ + uint8_t buf[11]; + buf[0] = 0x05; + buf[7] = 0x10; + buf[8] = 0x01; + buf[9] = 0x02; + buf[10] = 0x12; + + for (uint8_t i = 0; i < 6; i++) + buf[i + 1] = BDADDR[i]; + + //bmRequest = Host to device (0x00) | Class (0x20) | Interface (0x01) = 0x21, bRequest = Set Report (0x09), Report ID (0x05), Report Type (Feature 0x03), interface (0x00), datalength, datalength, data) + pUsb->ctrlReq(bAddress, epInfo[BTD_CONTROL_PIPE].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0x05, 0x03, 0x00, 11, 11, buf, NULL); #ifdef DEBUG - Notify(PSTR("\r\nBluetooth Address was set to: ")); - for(int8_t i = 5; i > 0; i--) { - PrintHex(my_bdaddr[i]); - Notify(PSTR(":")); - } - PrintHex(my_bdaddr[0]); + Notify(PSTR("\r\nBluetooth Address was set to: "), 0x80); + for (int8_t i = 5; i > 0; i--) { + PrintHex (my_bdaddr[i], 0x80); + Notify(PSTR(":"), 0x80); + } + PrintHex (my_bdaddr[0], 0x80); #endif } \ No newline at end of file diff --git a/PS3BT.cpp b/PS3BT.cpp index cf35a7f4..87214ab3 100644 --- a/PS3BT.cpp +++ b/PS3BT.cpp @@ -1,15 +1,15 @@ /* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved. - + This software may be distributed and modified under the terms of the GNU General Public License version 2 (GPL2) as published by the Free Software Foundation and appearing in the file GPL2.TXT included in the packaging of this file. Please note that GPL2 Section 2[b] requires that all works based on this software must also be made publicly available under the terms of the GPL2 ("Copyleft"). - + Contact information ------------------- - + Kristian Lauszus, TKJ Electronics Web : http://www.tkjelectronics.com e-mail : kristianl@tkjelectronics.com @@ -21,15 +21,15 @@ //#define PRINTREPORT // Uncomment to print the report send by the PS3 Controllers const uint8_t OUTPUT_REPORT_BUFFER[] PROGMEM = { - 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, - 0xff, 0x27, 0x10, 0x00, 0x32, - 0xff, 0x27, 0x10, 0x00, 0x32, - 0xff, 0x27, 0x10, 0x00, 0x32, - 0xff, 0x27, 0x10, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0x27, 0x10, 0x00, 0x32, + 0xff, 0x27, 0x10, 0x00, 0x32, + 0xff, 0x27, 0x10, 0x00, 0x32, + 0xff, 0x27, 0x10, 0x00, 0x32, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; PS3BT::PS3BT(BTD *p, uint8_t btadr5, uint8_t btadr4, uint8_t btadr3, uint8_t btadr2, uint8_t btadr1, uint8_t btadr0): @@ -37,27 +37,27 @@ pBtd(p) // pointer to USB class instance - mandatory { if (pBtd) pBtd->registerServiceClass(this); // Register it as a Bluetooth service - + pBtd->my_bdaddr[5] = btadr5; // Change to your dongle's Bluetooth address instead pBtd->my_bdaddr[4] = btadr4; pBtd->my_bdaddr[3] = btadr3; pBtd->my_bdaddr[2] = btadr2; pBtd->my_bdaddr[1] = btadr1; pBtd->my_bdaddr[0] = btadr0; - + HIDBuffer[0] = 0x52;// HID BT Set_report (0x50) | Report Type (Output 0x02) HIDBuffer[1] = 0x01;// Report ID - + //Needed for PS3 Move Controller commands to work via bluetooth HIDMoveBuffer[0] = 0xA2;// HID BT DATA_request (0xA0) | Report Type (Output 0x02) HIDMoveBuffer[1] = 0x02;// Report ID - + /* Set device cid for the control and intterrupt channelse - LSB */ control_dcid[0] = 0x40;//0x0040 control_dcid[1] = 0x00; interrupt_dcid[0] = 0x41;//0x0041 interrupt_dcid[1] = 0x00; - + Reset(); } bool PS3BT::getButtonPress(Button b) { @@ -76,7 +76,7 @@ uint8_t PS3BT::getAnalogButton(Button a) { } uint8_t PS3BT::getAnalogHat(AnalogHat a) { if (l2capinbuf == NULL) - return 0; + return 0; return (uint8_t)(l2capinbuf[(uint8_t)a+15]); } int16_t PS3BT::getSensor(Sensor a) { @@ -93,7 +93,7 @@ int16_t PS3BT::getSensor(Sensor a) { else if (a == mZmove || a == tempMove) // The tempearature is also 12 bits long return ((l2capinbuf[(uint16_t)a] << 4) | ((l2capinbuf[(uint16_t)a + 1] & 0xF0) >> 4)); else // aXmove, aYmove, aZmove, gXmove, gYmove and gZmove - return (l2capinbuf[(uint16_t)a] | (l2capinbuf[(uint16_t)a + 1] << 8)); + return (l2capinbuf[(uint16_t)a] | (l2capinbuf[(uint16_t)a + 1] << 8)); } else return 0; } @@ -101,7 +101,7 @@ double PS3BT::getAngle(Angle a) { double accXval; double accYval; double accZval; - + if(PS3Connected) { // Data for the Kionix KXPC4 used in the DualShock 3 const double zeroG = 511.5; // 1.65/3.3*1023 (1,65V) @@ -115,7 +115,7 @@ double PS3BT::getAngle(Angle a) { accYval = (int16_t)(getSensor(aYmove)-zeroG); accZval = (int16_t)(getSensor(aZmove)-zeroG); } - + // Convert to 360 degrees resolution // atan2 outputs the value of -π to π (radians) // We are then converting it to 0 to 2π and then to degrees @@ -157,15 +157,15 @@ double PS3BT::get9DOFValues(Sensor a) { // Thanks to Manfred Piendl } String PS3BT::getTemperature() { if(PS3MoveConnected) { - int16_t input = getSensor(tempMove); - + int16_t input = getSensor(tempMove); + String output = String(input/100); output += "."; if(input%100 < 10) output += "0"; output += String(input%100); - - return output; + + return output; } } bool PS3BT::getStatus(Status c) { @@ -178,14 +178,14 @@ bool PS3BT::getStatus(Status c) { String PS3BT::getStatusString() { if (PS3Connected || PS3NavigationConnected) { char statusOutput[100]; - + strcpy(statusOutput,"ConnectionStatus: "); - + if (getStatus(Plugged)) strcat(statusOutput,"Plugged"); else if (getStatus(Unplugged)) strcat(statusOutput,"Unplugged"); else strcat(statusOutput,"Error"); - - + + strcat(statusOutput," - PowerRating: "); if (getStatus(Charging)) strcat(statusOutput,"Charging"); else if (getStatus(NotCharging)) strcat(statusOutput,"Not Charging"); @@ -195,23 +195,23 @@ String PS3BT::getStatusString() { else if (getStatus(High)) strcat(statusOutput,"High"); else if (getStatus(Full)) strcat(statusOutput,"Full"); else strcat(statusOutput,"Error"); - + strcat(statusOutput," - WirelessStatus: "); - + if (getStatus(CableRumble)) strcat(statusOutput,"Cable - Rumble is on"); else if (getStatus(Cable)) strcat(statusOutput,"Cable - Rumble is off"); else if (getStatus(BluetoothRumble)) strcat(statusOutput,"Bluetooth - Rumble is on"); else if (getStatus(Bluetooth)) strcat(statusOutput,"Bluetooth - Rumble is off"); else strcat(statusOutput,"Error"); - + return statusOutput; - + } else if(PS3MoveConnected) { char statusOutput[50]; - + strcpy(statusOutput,"PowerRating: "); - + if (getStatus(MoveCharging)) strcat(statusOutput,"Charging"); else if (getStatus(MoveNotCharging)) strcat(statusOutput,"Not Charging"); else if (getStatus(MoveShutdown)) strcat(statusOutput,"Shutdown"); @@ -220,7 +220,7 @@ String PS3BT::getStatusString() { else if (getStatus(MoveHigh)) strcat(statusOutput,"High"); else if (getStatus(MoveFull)) strcat(statusOutput,"Full"); else strcat(statusOutput,"Error"); - + return statusOutput; } } @@ -231,10 +231,10 @@ void PS3BT::Reset() { activeConnection = false; l2cap_event_flag = 0; // Reset flags l2cap_state = L2CAP_WAIT; - + // Needed for PS3 Dualshock Controller commands to work via bluetooth for (uint8_t i = 0; i < OUTPUT_REPORT_BUFFER_SIZE; i++) - HIDBuffer[i + 2] = pgm_read_byte(&OUTPUT_REPORT_BUFFER[i]); // First two bytes reserved for report type and ID + HIDBuffer[i + 2] = pgm_read_byte(&OUTPUT_REPORT_BUFFER[i]); // First two bytes reserved for report type and ID } void PS3BT::disconnect() { // Use this void to disconnect any of the controllers @@ -256,11 +256,11 @@ void PS3BT::ACLData(uint8_t* ACLData) { remote_name[i] = pBtd->remote_name[i]; // Store the remote name for the connection #ifdef DEBUG if(pBtd->hci_version < 3) { // Check the HCI Version of the Bluetooth dongle - Notify(PSTR("\r\nYour dongle may not support reading the analog buttons, sensors and status\r\nYour HCI Version is: ")); + Notify(PSTR("\r\nYour dongle may not support reading the analog buttons, sensors and status\r\nYour HCI Version is: "), 0x80); Serial.print(pBtd->hci_version); - Notify(PSTR("\r\nBut should be at least 3\r\nThis means that it doesn't support Bluetooth Version 2.0+EDR")); + Notify(PSTR("\r\nBut should be at least 3\r\nThis means that it doesn't support Bluetooth Version 2.0+EDR"), 0x80); } -#endif +#endif } } } @@ -270,34 +270,34 @@ void PS3BT::ACLData(uint8_t* ACLData) { if ((l2capinbuf[6] | (l2capinbuf[7] << 8)) == 0x0001) { //l2cap_control - Channel ID for ACL-U if (l2capinbuf[8] == L2CAP_CMD_COMMAND_REJECT) { #ifdef DEBUG - Notify(PSTR("\r\nL2CAP Command Rejected - Reason: ")); - PrintHex(l2capinbuf[13]); + Notify(PSTR("\r\nL2CAP Command Rejected - Reason: "), 0x80); + PrintHex(l2capinbuf[13], 0x80); Serial.print(" "); - PrintHex(l2capinbuf[12]); + PrintHex(l2capinbuf[12], 0x80); Serial.print(" Data: "); - PrintHex(l2capinbuf[17]); + PrintHex(l2capinbuf[17], 0x80); Serial.print(" "); - PrintHex(l2capinbuf[16]); - Serial.print(" "); - PrintHex(l2capinbuf[15]); + PrintHex(l2capinbuf[16], 0x80); Serial.print(" "); - PrintHex(l2capinbuf[14]); + PrintHex(l2capinbuf[15], 0x80); + Serial.print(" "); + PrintHex(l2capinbuf[14], 0x80); #endif } - else if (l2capinbuf[8] == L2CAP_CMD_CONNECTION_REQUEST) { + else if (l2capinbuf[8] == L2CAP_CMD_CONNECTION_REQUEST) { #ifdef EXTRADEBUG - Notify(PSTR("\r\nL2CAP Connection Request - PSM: ")); - PrintHex(l2capinbuf[13]); - Notify(PSTR(" ")); - PrintHex(l2capinbuf[12]); - Notify(PSTR(" SCID: ")); - PrintHex(l2capinbuf[15]); - Notify(PSTR(" ")); - PrintHex(l2capinbuf[14]); - Notify(PSTR(" Identifier: ")); - PrintHex(l2capinbuf[9]); + Notify(PSTR("\r\nL2CAP Connection Request - PSM: "), 0x80); + PrintHex(l2capinbuf[13], 0x80); + Notify(PSTR(" "), 0x80); + PrintHex(l2capinbuf[12], 0x80); + Notify(PSTR(" SCID: "), 0x80); + PrintHex(l2capinbuf[15], 0x80); + Notify(PSTR(" "), 0x80); + PrintHex(l2capinbuf[14], 0x80); + Notify(PSTR(" Identifier: "), 0x80); + PrintHex(l2capinbuf[9], 0x80); #endif - if ((l2capinbuf[12] | (l2capinbuf[13] << 8)) == HID_CTRL_PSM) { + if ((l2capinbuf[12] | (l2capinbuf[13] << 8)) == HID_CTRL_PSM) { identifier = l2capinbuf[9]; control_scid[0] = l2capinbuf[14]; control_scid[1] = l2capinbuf[15]; @@ -325,7 +325,7 @@ void PS3BT::ACLData(uint8_t* ACLData) { else if (l2capinbuf[8] == L2CAP_CMD_CONFIG_REQUEST) { if (l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) { //Serial.print("\r\nHID Control Configuration Request"); - identifier = l2capinbuf[9]; + identifier = l2capinbuf[9]; l2cap_event_flag |= L2CAP_FLAG_CONFIG_CONTROL_REQUEST; } else if (l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) { @@ -333,11 +333,11 @@ void PS3BT::ACLData(uint8_t* ACLData) { identifier = l2capinbuf[9]; l2cap_event_flag |= L2CAP_FLAG_CONFIG_INTERRUPT_REQUEST; } - } + } else if (l2capinbuf[8] == L2CAP_CMD_DISCONNECT_REQUEST) { if (l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) { #ifdef DEBUG - Notify(PSTR("\r\nDisconnect Request: Control Channel")); + Notify(PSTR("\r\nDisconnect Request: Control Channel"), 0x80); #endif identifier = l2capinbuf[9]; pBtd->l2cap_disconnection_response(hci_handle,identifier,control_dcid,control_scid); @@ -345,7 +345,7 @@ void PS3BT::ACLData(uint8_t* ACLData) { } else if (l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) { #ifdef DEBUG - Notify(PSTR("\r\nDisconnect Request: Interrupt Channel")); + Notify(PSTR("\r\nDisconnect Request: Interrupt Channel"), 0x80); #endif identifier = l2capinbuf[9]; pBtd->l2cap_disconnection_response(hci_handle,identifier,interrupt_dcid,interrupt_scid); @@ -353,12 +353,12 @@ void PS3BT::ACLData(uint8_t* ACLData) { } } else if (l2capinbuf[8] == L2CAP_CMD_DISCONNECT_RESPONSE) { - if (l2capinbuf[12] == control_scid[0] && l2capinbuf[13] == control_scid[1]) { + if (l2capinbuf[12] == control_scid[0] && l2capinbuf[13] == control_scid[1]) { //Serial.print("\r\nDisconnect Response: Control Channel"); identifier = l2capinbuf[9]; l2cap_event_flag |= L2CAP_FLAG_DISCONNECT_CONTROL_RESPONSE; } - else if (l2capinbuf[12] == interrupt_scid[0] && l2capinbuf[13] == interrupt_scid[1]) { + else if (l2capinbuf[12] == interrupt_scid[0] && l2capinbuf[13] == interrupt_scid[1]) { //Serial.print("\r\nDisconnect Response: Interrupt Channel"); identifier = l2capinbuf[9]; l2cap_event_flag |= L2CAP_FLAG_DISCONNECT_INTERRUPT_RESPONSE; @@ -366,8 +366,8 @@ void PS3BT::ACLData(uint8_t* ACLData) { } #ifdef EXTRADEBUG else { - Notify(PSTR("\r\nL2CAP Unknown Signaling Command: ")); - PrintHex(l2capinbuf[8]); + Notify(PSTR("\r\nL2CAP Unknown Signaling Command: "), 0x80); + PrintHex(l2capinbuf[8], 0x80); } #endif } else if (l2capinbuf[6] == interrupt_dcid[0] && l2capinbuf[7] == interrupt_dcid[1]) { // l2cap_interrupt @@ -379,18 +379,18 @@ void PS3BT::ACLData(uint8_t* ACLData) { ButtonState = (uint32_t)(l2capinbuf[11] | ((uint16_t)l2capinbuf[12] << 8) | ((uint32_t)l2capinbuf[13] << 16)); else if(PS3MoveConnected) ButtonState = (uint32_t)(l2capinbuf[10] | ((uint16_t)l2capinbuf[11] << 8) | ((uint32_t)l2capinbuf[12] << 16)); - - //Notify(PSTR("\r\nButtonState"); - //PrintHex(ButtonState); - + + //Notify(PSTR("\r\nButtonState", 0x80); + //PrintHex(ButtonState, 0x80); + if(ButtonState != OldButtonState) { ButtonClickState = ButtonState & ~OldButtonState; // Update click state variable OldButtonState = ButtonState; } - + #ifdef PRINTREPORT // Uncomment "#define PRINTREPORT" to print the report send by the PS3 Controllers for(uint8_t i = 10; i < 58;i++) { - PrintHex(l2capinbuf[i]); + PrintHex(l2capinbuf[i], 0x80); Serial.print(" "); } Serial.println(); @@ -406,7 +406,7 @@ void PS3BT::L2CAP_task() { case L2CAP_WAIT: if (l2cap_connection_request_control_flag) { #ifdef DEBUG - Notify(PSTR("\r\nHID Control Incoming Connection Request")); + Notify(PSTR("\r\nHID Control Incoming Connection Request"), 0x80); #endif pBtd->l2cap_connection_response(hci_handle,identifier, control_dcid, control_scid, PENDING); delay(1); @@ -420,17 +420,17 @@ void PS3BT::L2CAP_task() { case L2CAP_CONTROL_REQUEST: if (l2cap_config_request_control_flag) { #ifdef DEBUG - Notify(PSTR("\r\nHID Control Configuration Request")); + Notify(PSTR("\r\nHID Control Configuration Request"), 0x80); #endif pBtd->l2cap_config_response(hci_handle,identifier, control_scid); l2cap_state = L2CAP_CONTROL_SUCCESS; } break; - + case L2CAP_CONTROL_SUCCESS: if (l2cap_config_success_control_flag) { #ifdef DEBUG - Notify(PSTR("\r\nHID Control Successfully Configured")); + Notify(PSTR("\r\nHID Control Successfully Configured"), 0x80); #endif l2cap_state = L2CAP_INTERRUPT_SETUP; } @@ -438,7 +438,7 @@ void PS3BT::L2CAP_task() { case L2CAP_INTERRUPT_SETUP: if (l2cap_connection_request_interrupt_flag) { #ifdef DEBUG - Notify(PSTR("\r\nHID Interrupt Incoming Connection Request")); + Notify(PSTR("\r\nHID Interrupt Incoming Connection Request"), 0x80); #endif pBtd->l2cap_connection_response(hci_handle,identifier, interrupt_dcid, interrupt_scid, PENDING); delay(1); @@ -446,14 +446,14 @@ void PS3BT::L2CAP_task() { identifier++; delay(1); pBtd->l2cap_config_request(hci_handle,identifier, interrupt_scid); - + l2cap_state = L2CAP_INTERRUPT_REQUEST; } break; case L2CAP_INTERRUPT_REQUEST: if (l2cap_config_request_interrupt_flag) { #ifdef DEBUG - Notify(PSTR("\r\nHID Interrupt Configuration Request")); + Notify(PSTR("\r\nHID Interrupt Configuration Request"), 0x80); #endif pBtd->l2cap_config_response(hci_handle,identifier, interrupt_scid); l2cap_state = L2CAP_INTERRUPT_SUCCESS; @@ -462,14 +462,14 @@ void PS3BT::L2CAP_task() { case L2CAP_INTERRUPT_SUCCESS: if (l2cap_config_success_interrupt_flag) { #ifdef DEBUG - Notify(PSTR("\r\nHID Interrupt Successfully Configured")); + Notify(PSTR("\r\nHID Interrupt Successfully Configured"), 0x80); #endif if(remote_name[0] == 'M') { // First letter in Motion Controller ('M') for (uint8_t i = 0; i < BULK_MAXPKTSIZE; i++) // Reset l2cap in buffer as it sometimes read it as a button has been pressed l2capinbuf[i] = 0; ButtonState = 0; OldButtonState = 0; - + l2cap_state = L2CAP_HID_PS3_LED; } else l2cap_state = L2CAP_HID_ENABLE_SIXAXIS; @@ -478,22 +478,22 @@ void PS3BT::L2CAP_task() { break; /* These states are handled in Run() */ - + case L2CAP_INTERRUPT_DISCONNECT: if (l2cap_disconnect_response_interrupt_flag) { #ifdef DEBUG - Notify(PSTR("\r\nDisconnected Interrupt Channel")); + Notify(PSTR("\r\nDisconnected Interrupt Channel"), 0x80); #endif identifier++; - pBtd->l2cap_disconnection_request(hci_handle, identifier, control_scid, control_dcid); + pBtd->l2cap_disconnection_request(hci_handle, identifier, control_scid, control_dcid); l2cap_state = L2CAP_CONTROL_DISCONNECT; } break; - + case L2CAP_CONTROL_DISCONNECT: if (l2cap_disconnect_response_control_flag) { #ifdef DEBUG - Notify(PSTR("\r\nDisconnected Control Channel")); + Notify(PSTR("\r\nDisconnected Control Channel"), 0x80); #endif pBtd->hci_disconnect(hci_handle); hci_handle = -1; // Reset handle @@ -501,7 +501,7 @@ void PS3BT::L2CAP_task() { l2cap_state = L2CAP_WAIT; } break; - } + } } void PS3BT::Run() { switch (l2cap_state) { @@ -511,7 +511,7 @@ void PS3BT::Run() { l2capinbuf[i] = 0; ButtonState = 0; OldButtonState = 0; - + enable_sixaxis(); for (uint8_t i = 15; i < 19; i++) l2capinbuf[i] = 0x7F; // Set the analog joystick values to center position @@ -519,33 +519,33 @@ void PS3BT::Run() { timer = millis(); } break; - + case L2CAP_HID_PS3_LED: if(millis() - timer > 1000) { // loop 1 second before sending the command if (remote_name[0] == 'P') { // First letter in PLAYSTATION(R)3 Controller ('P') setLedOn(LED1); #ifdef DEBUG - Notify(PSTR("\r\nDualshock 3 Controller Enabled\r\n")); + Notify(PSTR("\r\nDualshock 3 Controller Enabled\r\n"), 0x80); #endif PS3Connected = true; } else if (remote_name[0] == 'N') { // First letter in Navigation Controller ('N') setLedOn(LED1); // This just turns LED constantly on, on the Navigation controller #ifdef DEBUG - Notify(PSTR("\r\nNavigation Controller Enabled\r\n")); + Notify(PSTR("\r\nNavigation Controller Enabled\r\n"), 0x80); #endif PS3NavigationConnected = true; } else if(remote_name[0] == 'M') { // First letter in Motion Controller ('M') moveSetBulb(Red); timerBulbRumble = millis(); #ifdef DEBUG - Notify(PSTR("\r\nMotion Controller Enabled\r\n")); + Notify(PSTR("\r\nMotion Controller Enabled\r\n"), 0x80); #endif PS3MoveConnected = true; } l2cap_state = L2CAP_DONE; } break; - + case L2CAP_DONE: if (PS3MoveConnected) { //The Bulb and rumble values, has to be send at aproximatly every 5th second for it to stay on if (millis() - timerBulbRumble > 4000) { //Send at least every 4th second @@ -562,8 +562,8 @@ void PS3BT::Run() { /************************************************************/ //Playstation Sixaxis Dualshock and Navigation Controller commands -void PS3BT::HID_Command(uint8_t* data, uint8_t nbytes) { - if (millis() - timerHID <= 250)// Check if is has been more than 250ms since last command +void PS3BT::HID_Command(uint8_t* data, uint8_t nbytes) { + if (millis() - timerHID <= 250)// Check if is has been more than 250ms since last command delay((uint32_t)(250 - (millis() - timerHID)));//There have to be a delay between commands pBtd->L2CAP_Command(hci_handle,data,nbytes,control_scid[0],control_scid[1]); // Both the Navigation and Dualshock controller sends data via the control channel timerHID = millis(); @@ -571,7 +571,7 @@ void PS3BT::HID_Command(uint8_t* data, uint8_t nbytes) { void PS3BT::setAllOff() { for (uint8_t i = 0; i < OUTPUT_REPORT_BUFFER_SIZE; i++) HIDBuffer[i + 2] = pgm_read_byte(&OUTPUT_REPORT_BUFFER[i]);//First two bytes reserved for report type and ID - + HID_Command(HIDBuffer, HID_BUFFERSIZE); } void PS3BT::setRumbleOff() { @@ -579,7 +579,7 @@ void PS3BT::setRumbleOff() { HIDBuffer[4] = 0x00;//low mode off HIDBuffer[5] = 0x00; HIDBuffer[6] = 0x00;//high mode off - + HID_Command(HIDBuffer, HID_BUFFERSIZE); } void PS3BT::setRumbleOn(Rumble mode) { @@ -591,7 +591,7 @@ void PS3BT::setRumbleOn(Rumble mode) { */ if ((mode & 0x30) > 0) { HIDBuffer[3] = 0xfe; - HIDBuffer[5] = 0xfe; + HIDBuffer[5] = 0xfe; if (mode == RumbleHigh) { HIDBuffer[4] = 0;//low mode off HIDBuffer[6] = 0xff;//high mode on @@ -599,7 +599,7 @@ void PS3BT::setRumbleOn(Rumble mode) { else { HIDBuffer[4] = 0xff;//low mode on HIDBuffer[6] = 0;//high mode off - } + } HID_Command(HIDBuffer, HID_BUFFERSIZE); } } @@ -623,7 +623,7 @@ void PS3BT::enable_sixaxis() { //Command used to enable the Dualshock 3 and Navi cmd_buf[3] = 0x03; cmd_buf[4] = 0x00; cmd_buf[5] = 0x00; - + HID_Command(cmd_buf, 6); } @@ -635,12 +635,12 @@ void PS3BT::HIDMove_Command(uint8_t* data,uint8_t nbytes) { timerHID = millis(); } void PS3BT::moveSetBulb(uint8_t r, uint8_t g, uint8_t b) { //Use this to set the Color using RGB values - //set the Bulb's values into the write buffer + //set the Bulb's values into the write buffer HIDMoveBuffer[3] = r; HIDMoveBuffer[4] = g; HIDMoveBuffer[5] = b; - - HIDMove_Command(HIDMoveBuffer, HID_BUFFERSIZE); + + HIDMove_Command(HIDMoveBuffer, HID_BUFFERSIZE); } void PS3BT::moveSetBulb(Colors color) { //Use this to set the Color using the predefined colors in enum moveSetBulb((uint8_t)(color >> 16),(uint8_t)(color >> 8),(uint8_t)(color)); @@ -648,10 +648,10 @@ void PS3BT::moveSetBulb(Colors color) { //Use this to set the Color using the pr void PS3BT::moveSetRumble(uint8_t rumble) { #ifdef DEBUG if(rumble < 64 && rumble != 0) // The rumble value has to at least 64, or approximately 25% (64/255*100) - Notify(PSTR("\r\nThe rumble value has to at least 64, or approximately 25%")); + Notify(PSTR("\r\nThe rumble value has to at least 64, or approximately 25%"), 0x80); #endif //set the rumble value into the write buffer HIDMoveBuffer[7] = rumble; - - HIDMove_Command(HIDMoveBuffer, HID_BUFFERSIZE); + + HIDMove_Command(HIDMoveBuffer, HID_BUFFERSIZE); } \ No newline at end of file diff --git a/PS3USB.cpp b/PS3USB.cpp index 57c2e2b9..13d835db 100644 --- a/PS3USB.cpp +++ b/PS3USB.cpp @@ -1,15 +1,15 @@ /* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved. - + This software may be distributed and modified under the terms of the GNU General Public License version 2 (GPL2) as published by the Free Software Foundation and appearing in the file GPL2.TXT included in the packaging of this file. Please note that GPL2 Section 2[b] requires that all works based on this software must also be made publicly available under the terms of the GPL2 ("Copyleft"). - + Contact information ------------------- - + Kristian Lauszus, TKJ Electronics Web : http://www.tkjelectronics.com e-mail : kristianl@tkjelectronics.com @@ -21,20 +21,20 @@ //#define PRINTREPORT // Uncomment to print the report send by the PS3 Controllers const uint8_t PS3_REPORT_BUFFER[] PROGMEM = { - 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, - 0xff, 0x27, 0x10, 0x00, 0x32, - 0xff, 0x27, 0x10, 0x00, 0x32, - 0xff, 0x27, 0x10, 0x00, 0x32, - 0xff, 0x27, 0x10, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0x27, 0x10, 0x00, 0x32, + 0xff, 0x27, 0x10, 0x00, 0x32, + 0xff, 0x27, 0x10, 0x00, 0x32, + 0xff, 0x27, 0x10, 0x00, 0x32, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; const uint8_t MOVE_REPORT_BUFFER[] PROGMEM = { - 0x02, 0x00, // Always 0x02, 0x00, - 0x00, 0x00, 0x00, // r, g, b, - 0x00, // Always 0x00, + 0x02, 0x00, // Always 0x02, 0x00, + 0x00, 0x00, 0x00, // r, g, b, + 0x00, // Always 0x00, 0x00 // Rumble }; @@ -46,13 +46,13 @@ bPollEnable(false) // don't start polling before dongle is connected for(uint8_t i=0; iRegisterDeviceClass(this); //set devConfig[] entry - + my_bdaddr[5] = btadr5; // Change to your dongle's Bluetooth address instead my_bdaddr[4] = btadr4; my_bdaddr[3] = btadr3; @@ -68,68 +68,68 @@ uint8_t PS3USB::Init(uint8_t parent, uint8_t port, bool lowspeed) { EpInfo *oldep_ptr = NULL; uint16_t PID; uint16_t VID; - + // get memory address of USB device address pool - AddressPool &addrPool = pUsb->GetAddressPool(); + AddressPool &addrPool = pUsb->GetAddressPool(); #ifdef EXTRADEBUG - Notify(PSTR("\r\nPS3USB Init")); + Notify(PSTR("\r\nPS3USB Init"), 0x80); #endif // check if address has already been assigned to an instance if (bAddress) { #ifdef DEBUG - Notify(PSTR("\r\nAddress in use")); + Notify(PSTR("\r\nAddress in use"), 0x80); #endif return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE; } - + // Get pointer to pseudo device with address 0 assigned p = addrPool.GetUsbDevicePtr(0); - - if (!p) { + + if (!p) { #ifdef DEBUG - Notify(PSTR("\r\nAddress not found")); + Notify(PSTR("\r\nAddress not found"), 0x80); #endif return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; } - + if (!p->epinfo) { #ifdef DEBUG - Notify(PSTR("\r\nepinfo is null")); + Notify(PSTR("\r\nepinfo is null"), 0x80); #endif return USB_ERROR_EPINFO_IS_NULL; } - + // Save old pointer to EP_RECORD of address 0 oldep_ptr = p->epinfo; - + // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence p->epinfo = epInfo; - + p->lowspeed = lowspeed; - + // Get device descriptor rcode = pUsb->getDevDescr(0, 0, sizeof(USB_DEVICE_DESCRIPTOR), (uint8_t*)buf);// Get device descriptor - addr, ep, nbytes, data // Restore p->epinfo p->epinfo = oldep_ptr; - + if(rcode) goto FailGetDevDescr; - + VID = ((USB_DEVICE_DESCRIPTOR*)buf)->idVendor; PID = ((USB_DEVICE_DESCRIPTOR*)buf)->idProduct; - + if(VID != PS3_VID || (PID != PS3_PID && PID != PS3NAVIGATION_PID && PID != PS3MOVE_PID)) - goto FailUnknownDevice; - + goto FailUnknownDevice; + // Allocate new address according to device class bAddress = addrPool.AllocAddress(parent, false, port); - + if (!bAddress) return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; - + // Extract Max Packet Size from device descriptor - epInfo[0].maxPktSize = (uint8_t)((USB_DEVICE_DESCRIPTOR*)buf)->bMaxPacketSize0; - + epInfo[0].maxPktSize = (uint8_t)((USB_DEVICE_DESCRIPTOR*)buf)->bMaxPacketSize0; + // Assign new address to the device rcode = pUsb->setAddr( 0, 0, bAddress ); if (rcode) { @@ -137,34 +137,34 @@ uint8_t PS3USB::Init(uint8_t parent, uint8_t port, bool lowspeed) { addrPool.FreeAddress(bAddress); bAddress = 0; #ifdef DEBUG - Notify(PSTR("\r\nsetAddr: ")); + Notify(PSTR("\r\nsetAddr: "), 0x80); #endif - PrintHex(rcode); + PrintHex(rcode, 0x80); return rcode; } #ifdef EXTRADEBUG - Notify(PSTR("\r\nAddr: ")); - PrintHex(bAddress); + Notify(PSTR("\r\nAddr: "), 0x80); + PrintHex(bAddress, 0x80); #endif p->lowspeed = false; - + //get pointer to assigned address record p = addrPool.GetUsbDevicePtr(bAddress); - if (!p) + if (!p) return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; - - p->lowspeed = lowspeed; - + + p->lowspeed = lowspeed; + // Assign epInfo to epinfo pointer - only EP0 is known rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); if (rcode) goto FailSetDevTblEntry; - - + + /* The application will work in reduced host mode, so we can save program and data memory space. After verifying the PID and VID we will use known values for the configuration values for device, interface, endpoints and HID for the PS3 Controllers */ - + /* Initialize data structures for endpoints of device */ epInfo[ PS3_OUTPUT_PIPE ].epAddr = 0x02; // PS3 output endpoint epInfo[ PS3_OUTPUT_PIPE ].epAttribs = EP_INTERRUPT; @@ -178,26 +178,26 @@ uint8_t PS3USB::Init(uint8_t parent, uint8_t port, bool lowspeed) { epInfo[ PS3_INPUT_PIPE ].maxPktSize = EP_MAXPKTSIZE; epInfo[ PS3_INPUT_PIPE ].bmSndToggle = bmSNDTOG0; epInfo[ PS3_INPUT_PIPE ].bmRcvToggle = bmRCVTOG0; - + rcode = pUsb->setEpInfoEntry(bAddress, 3, epInfo); if( rcode ) goto FailSetDevTblEntry; - + delay(200);//Give time for address change - + rcode = pUsb->setConf(bAddress, epInfo[ PS3_CONTROL_PIPE ].epAddr, 1); if( rcode ) goto FailSetConf; - + if(PID == PS3_PID || PID == PS3NAVIGATION_PID) { if(PID == PS3_PID) { #ifdef DEBUG - Notify(PSTR("\r\nDualshock 3 Controller Connected")); -#endif + Notify(PSTR("\r\nDualshock 3 Controller Connected"), 0x80); +#endif PS3Connected = true; } else { // must be a navigation controller #ifdef DEBUG - Notify(PSTR("\r\nNavigation Controller Connected")); + Notify(PSTR("\r\nNavigation Controller Connected"), 0x80); #endif PS3NavigationConnected = true; } @@ -205,62 +205,62 @@ uint8_t PS3USB::Init(uint8_t parent, uint8_t port, bool lowspeed) { setBdaddr(my_bdaddr); enable_sixaxis(); setLedOn(LED1); - + // Needed for PS3 Dualshock and Navigation commands to work for (uint8_t i = 0; i < PS3_REPORT_BUFFER_SIZE; i++) writeBuf[i] = pgm_read_byte(&PS3_REPORT_BUFFER[i]); - + for (uint8_t i = 6; i < 10; i++) readBuf[i] = 0x7F; // Set the analog joystick values to center position } else { // must be a Motion controller #ifdef DEBUG - Notify(PSTR("\r\nMotion Controller Connected")); -#endif + Notify(PSTR("\r\nMotion Controller Connected"), 0x80); +#endif PS3MoveConnected = true; setMoveBdaddr(my_bdaddr); // Set internal bluetooth address moveSetBulb(Red); - + // Needed for Move commands to work for (uint8_t i = 0; i < MOVE_REPORT_BUFFER_SIZE; i++) writeBuf[i] = pgm_read_byte(&MOVE_REPORT_BUFFER[i]); } bPollEnable = true; - Notify(PSTR("\r\n")); + Notify(PSTR("\r\n"), 0x80); timer = millis(); return 0; // successful configuration - - /* diagnostic messages */ + + /* diagnostic messages */ FailGetDevDescr: #ifdef DEBUG - Notify(PSTR("\r\ngetDevDescr:")); + Notify(PSTR("\r\ngetDevDescr:"), 0x80); #endif - goto Fail; + goto Fail; FailSetDevTblEntry: #ifdef DEBUG - Notify(PSTR("\r\nsetDevTblEn:")); + Notify(PSTR("\r\nsetDevTblEn:"), 0x80); #endif goto Fail; FailSetConf: #ifdef DEBUG - Notify(PSTR("\r\nsetConf:")); + Notify(PSTR("\r\nsetConf:"), 0x80); #endif - goto Fail; + goto Fail; FailUnknownDevice: #ifdef DEBUG - Notify(PSTR("\r\nUnknown Device Connected - VID: ")); - PrintHex(VID); - Notify(PSTR(" PID: ")); - PrintHex(PID); + Notify(PSTR("\r\nUnknown Device Connected - VID: "), 0x80); + PrintHex(VID, 0x80); + Notify(PSTR(" PID: "), 0x80); + PrintHex(PID, 0x80); #endif rcode = USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; goto Fail; Fail: #ifdef DEBUG - Notify(PSTR("\r\nPS3 Init Failed, error code: ")); + Notify(PSTR("\r\nPS3 Init Failed, error code: "), 0x80); Serial.print(rcode,HEX); -#endif +#endif Release(); return rcode; } @@ -270,15 +270,15 @@ uint8_t PS3USB::Release() { PS3Connected = false; PS3MoveConnected = false; PS3NavigationConnected = false; - pUsb->GetAddressPool().FreeAddress(bAddress); + pUsb->GetAddressPool().FreeAddress(bAddress); bAddress = 0; bPollEnable = false; return 0; } -uint8_t PS3USB::Poll() { +uint8_t PS3USB::Poll() { if (!bPollEnable) return 0; - + if(PS3Connected || PS3NavigationConnected) { uint16_t BUFFER_SIZE = EP_MAXPKTSIZE; pUsb->inTransfer(bAddress, epInfo[ PS3_INPUT_PIPE ].epAddr, &BUFFER_SIZE, readBuf); // input on endpoint 1 @@ -289,25 +289,25 @@ uint8_t PS3USB::Poll() { #endif } } - else if(PS3MoveConnected) { // One can only set the color of the bulb, set the rumble, set and get the bluetooth address and calibrate the magnetometer via USB + else if(PS3MoveConnected) { // One can only set the color of the bulb, set the rumble, set and get the bluetooth address and calibrate the magnetometer via USB if (millis() - timer > 4000) // Send at least every 4th second { Move_Command(writeBuf, MOVE_REPORT_BUFFER_SIZE); // The Bulb and rumble values, has to be written again and again, for it to stay turned on timer = millis(); - } - } + } + } return 0; } -void PS3USB::readReport() { +void PS3USB::readReport() { if (readBuf == NULL) - return; + return; ButtonState = (uint32_t)(readBuf[2] | ((uint16_t)readBuf[3] << 8) | ((uint32_t)readBuf[4] << 16)); - - //Notify(PSTR("\r\nButtonState"); - //PrintHex(ButtonState); - + + //Notify(PSTR("\r\nButtonState", 0x80); + //PrintHex(ButtonState, 0x80); + if(ButtonState != OldButtonState) { ButtonClickState = ButtonState & ~OldButtonState; // Update click state variable OldButtonState = ButtonState; @@ -319,9 +319,9 @@ void PS3USB::printReport() { //Uncomment "#define PRINTREPORT" to print the repo if (readBuf == NULL) return; for(uint8_t i = 0; i < PS3_REPORT_BUFFER_SIZE;i++) { - PrintHex(readBuf[i]); + PrintHex(readBuf[i], 0x80); Serial.print(" "); - } + } Serial.println(); #endif } @@ -342,7 +342,7 @@ uint8_t PS3USB::getAnalogButton(Button a) { } uint8_t PS3USB::getAnalogHat(AnalogHat a) { if (readBuf == NULL) - return 0; + return 0; return (uint8_t)(readBuf[((uint8_t)a+6)]); } uint16_t PS3USB::getSensor(Sensor a) { @@ -350,22 +350,22 @@ uint16_t PS3USB::getSensor(Sensor a) { return 0; return ((readBuf[((uint16_t)a)-9] << 8) | readBuf[((uint16_t)a + 1)-9]); } -double PS3USB::getAngle(Angle a) { +double PS3USB::getAngle(Angle a) { if(PS3Connected) { double accXval; double accYval; double accZval; - + // Data for the Kionix KXPC4 used in the DualShock 3 const double zeroG = 511.5; // 1.65/3.3*1023 (1,65V) accXval = -((double)getSensor(aX)-zeroG); accYval = -((double)getSensor(aY)-zeroG); accZval = -((double)getSensor(aZ)-zeroG); - + // Convert to 360 degrees resolution // atan2 outputs the value of -π to π (radians) - // We are then converting it to 0 to 2π and then to degrees - if (a == Pitch) { + // We are then converting it to 0 to 2π and then to degrees + if (a == Pitch) { double angle = (atan2(accYval,accZval)+PI)*RAD_TO_DEG; return angle; } else { @@ -373,7 +373,7 @@ double PS3USB::getAngle(Angle a) { return angle; } } else - return 0; + return 0; } bool PS3USB::getStatus(Status c) { if (readBuf == NULL) @@ -385,16 +385,16 @@ bool PS3USB::getStatus(Status c) { String PS3USB::getStatusString() { if (PS3Connected || PS3NavigationConnected) { char statusOutput[100]; - + strcpy(statusOutput,"ConnectionStatus: "); - + if (getStatus(Plugged)) strcat(statusOutput,"Plugged"); else if (getStatus(Unplugged)) strcat(statusOutput,"Unplugged"); else strcat(statusOutput,"Error"); - - + + strcat(statusOutput," - PowerRating: "); - + if (getStatus(Charging)) strcat(statusOutput,"Charging"); else if (getStatus(NotCharging)) strcat(statusOutput,"Not Charging"); else if (getStatus(Shutdown)) strcat(statusOutput,"Shutdown"); @@ -403,16 +403,16 @@ String PS3USB::getStatusString() { else if (getStatus(High)) strcat(statusOutput,"High"); else if (getStatus(Full)) strcat(statusOutput,"Full"); else strcat(statusOutput,"Error"); - + strcat(statusOutput," - WirelessStatus: "); - + if (getStatus(CableRumble)) strcat(statusOutput,"Cable - Rumble is on"); else if (getStatus(Cable)) strcat(statusOutput,"Cable - Rumble is off"); else if (getStatus(BluetoothRumble)) strcat(statusOutput,"Bluetooth - Rumble is on"); else if (getStatus(Bluetooth)) strcat(statusOutput,"Bluetooth - Rumble is off"); else strcat(statusOutput,"Error"); - - return statusOutput; + + return statusOutput; } } @@ -424,7 +424,7 @@ void PS3USB::PS3_Command(uint8_t* data, uint16_t nbytes) { void PS3USB::setAllOff() { for (uint8_t i = 0; i < PS3_REPORT_BUFFER_SIZE; i++) writeBuf[i] = pgm_read_byte(&PS3_REPORT_BUFFER[i]); // Reset buffer - + PS3_Command(writeBuf, PS3_REPORT_BUFFER_SIZE); } void PS3USB::setRumbleOff() { @@ -432,7 +432,7 @@ void PS3USB::setRumbleOff() { writeBuf[2] = 0x00;//low mode off writeBuf[3] = 0x00; writeBuf[4] = 0x00;//high mode off - + PS3_Command(writeBuf, PS3_REPORT_BUFFER_SIZE); } void PS3USB::setRumbleOn(Rumble mode) { @@ -444,7 +444,7 @@ void PS3USB::setRumbleOn(Rumble mode) { */ if ((mode & 0x30) > 0) { writeBuf[1] = 0xfe; - writeBuf[3] = 0xfe; + writeBuf[3] = 0xfe; if (mode == RumbleHigh) { writeBuf[2] = 0;//low mode off writeBuf[4] = 0xff;//high mode on @@ -468,23 +468,23 @@ void PS3USB::setLedToggle(LED a) { writeBuf[9] ^= (uint8_t)((pgm_read_byte(&LEDS[(uint8_t)a]) & 0x0f) << 1); PS3_Command(writeBuf, PS3_REPORT_BUFFER_SIZE); } -void PS3USB::setBdaddr(uint8_t* BDADDR) { - /* Set the internal bluetooth address */ - uint8_t buf[8]; +void PS3USB::setBdaddr(uint8_t* BDADDR) { + /* Set the internal bluetooth address */ + uint8_t buf[8]; buf[0] = 0x01; buf[1] = 0x00; for (uint8_t i = 0; i < 6; i++) buf[i+2] = BDADDR[5 - i];//Copy into buffer, has to be written reversed - + //bmRequest = Host to device (0x00) | Class (0x20) | Interface (0x01) = 0x21, bRequest = Set Report (0x09), Report ID (0xF5), Report Type (Feature 0x03), interface (0x00), datalength, datalength, data) - pUsb->ctrlReq(bAddress,epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0xF5, 0x03, 0x00, 8, 8, buf, NULL); + pUsb->ctrlReq(bAddress,epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0xF5, 0x03, 0x00, 8, 8, buf, NULL); #ifdef DEBUG - Notify(PSTR("\r\nBluetooth Address was set to: ")); + Notify(PSTR("\r\nBluetooth Address was set to: "), 0x80); for(int8_t i = 5; i > 0; i--) { - PrintHex(my_bdaddr[i]); + PrintHex(my_bdaddr[i], 0x80); Serial.print(":"); } - PrintHex(my_bdaddr[0]); + PrintHex(my_bdaddr[0], 0x80); #endif return; } @@ -494,7 +494,7 @@ void PS3USB::enable_sixaxis() { //Command used to enable the Dualshock 3 and Nav cmd_buf[1] = 0x0c; cmd_buf[2] = 0x00; cmd_buf[3] = 0x00; - + //bmRequest = Host to device (0x00) | Class (0x20) | Interface (0x01) = 0x21, bRequest = Set Report (0x09), Report ID (0xF4), Report Type (Feature 0x03), interface (0x00), datalength, datalength, data) pUsb->ctrlReq(bAddress,epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0xF4, 0x03, 0x00, 4, 4, cmd_buf, NULL); } @@ -502,15 +502,15 @@ void PS3USB::enable_sixaxis() { //Command used to enable the Dualshock 3 and Nav /* Playstation Move Controller commands */ void PS3USB::Move_Command(uint8_t* data, uint16_t nbytes) { pUsb->outTransfer(bAddress, epInfo[ PS3_OUTPUT_PIPE ].epAddr, nbytes, data); -} +} void PS3USB::moveSetBulb(uint8_t r, uint8_t g, uint8_t b) { //Use this to set the Color using RGB values - // set the Bulb's values into the write buffer + // set the Bulb's values into the write buffer writeBuf[2] = r; writeBuf[3] = g; writeBuf[4] = b; - - Move_Command(writeBuf, MOVE_REPORT_BUFFER_SIZE); + + Move_Command(writeBuf, MOVE_REPORT_BUFFER_SIZE); } void PS3USB::moveSetBulb(Colors color) { //Use this to set the Color using the predefined colors in "enums.h" moveSetBulb((uint8_t)(color >> 16),(uint8_t)(color >> 8),(uint8_t)(color)); @@ -518,34 +518,34 @@ void PS3USB::moveSetBulb(Colors color) { //Use this to set the Color using the p void PS3USB::moveSetRumble(uint8_t rumble) { #ifdef DEBUG if(rumble < 64 && rumble != 0) // The rumble value has to at least 64, or approximately 25% (64/255*100) - Notify(PSTR("\r\nThe rumble value has to at least 64, or approximately 25%")); + Notify(PSTR("\r\nThe rumble value has to at least 64, or approximately 25%"), 0x80); #endif //set the rumble value into the write buffer writeBuf[6] = rumble; - - Move_Command(writeBuf, MOVE_REPORT_BUFFER_SIZE); + + Move_Command(writeBuf, MOVE_REPORT_BUFFER_SIZE); } void PS3USB::setMoveBdaddr(uint8_t* BDADDR) { - /* Set the internal bluetooth address */ + /* Set the internal bluetooth address */ uint8_t buf[11]; buf[0] = 0x05; buf[7] = 0x10; buf[8] = 0x01; buf[9] = 0x02; - buf[10] = 0x12; - + buf[10] = 0x12; + for (uint8_t i = 0; i < 6; i++) buf[i + 1] = BDADDR[i]; - + //bmRequest = Host to device (0x00) | Class (0x20) | Interface (0x01) = 0x21, bRequest = Set Report (0x09), Report ID (0x05), Report Type (Feature 0x03), interface (0x00), datalength, datalength, data) - pUsb->ctrlReq(bAddress,epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0x05, 0x03, 0x00,11,11, buf, NULL); + pUsb->ctrlReq(bAddress,epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0x05, 0x03, 0x00,11,11, buf, NULL); #ifdef DEBUG - Notify(PSTR("\r\nBluetooth Address was set to: ")); + Notify(PSTR("\r\nBluetooth Address was set to: "), 0x80); for(int8_t i = 5; i > 0; i--) { - PrintHex(my_bdaddr[i]); + PrintHex(my_bdaddr[i], 0x80); Serial.print(":"); } - PrintHex(my_bdaddr[0]); + PrintHex(my_bdaddr[0], 0x80); #endif return; } \ No newline at end of file diff --git a/SPP.cpp b/SPP.cpp index 62920555..538d2193 100644 --- a/SPP.cpp +++ b/SPP.cpp @@ -1,15 +1,15 @@ /* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved. - + This software may be distributed and modified under the terms of the GNU General Public License version 2 (GPL2) as published by the Free Software Foundation and appearing in the file GPL2.TXT included in the packaging of this file. Please note that GPL2 Section 2[b] requires that all works based on this software must also be made publicly available under the terms of the GPL2 ("Copyleft"). - + Contact information ------------------- - + Kristian Lauszus, TKJ Electronics Web : http://www.tkjelectronics.com e-mail : kristianl@tkjelectronics.com @@ -47,16 +47,16 @@ pBtd(p) // Pointer to BTD class instance - mandatory { if (pBtd) pBtd->registerServiceClass(this); // Register it as a Bluetooth service - + pBtd->btdName = name; pBtd->btdPin = pin; - + /* Set device cid for the SDP and RFCOMM channelse */ sdp_dcid[0] = 0x50; // 0x0050 sdp_dcid[1] = 0x00; rfcomm_dcid[0] = 0x51; // 0x0051 rfcomm_dcid[1] = 0x00; - + Reset(); } void SPP::Reset() { @@ -65,7 +65,7 @@ void SPP::Reset() { SDPConnected = false; l2cap_sdp_state = L2CAP_SDP_WAIT; l2cap_rfcomm_state = L2CAP_RFCOMM_WAIT; - l2cap_event_flag = 0; + l2cap_event_flag = 0; } void SPP::disconnect(){ connected = false; @@ -96,31 +96,31 @@ void SPP::ACLData(uint8_t* l2capinbuf) { if ((l2capinbuf[6] | (l2capinbuf[7] << 8)) == 0x0001) { //l2cap_control - Channel ID for ACL-U if (l2capinbuf[8] == L2CAP_CMD_COMMAND_REJECT) { #ifdef DEBUG - Notify(PSTR("\r\nL2CAP Command Rejected - Reason: ")); - PrintHex(l2capinbuf[13]); - Notify(PSTR(" ")); - PrintHex(l2capinbuf[12]); - Notify(PSTR(" Data: ")); - PrintHex(l2capinbuf[17]); - Notify(PSTR(" ")); - PrintHex(l2capinbuf[16]); - Notify(PSTR(" ")); - PrintHex(l2capinbuf[15]); - Notify(PSTR(" ")); - PrintHex(l2capinbuf[14]); + Notify(PSTR("\r\nL2CAP Command Rejected - Reason: "), 0x80); + PrintHex(l2capinbuf[13], 0x80); + Notify(PSTR(" "), 0x80); + PrintHex(l2capinbuf[12], 0x80); + Notify(PSTR(" Data: "), 0x80); + PrintHex(l2capinbuf[17], 0x80); + Notify(PSTR(" "), 0x80); + PrintHex(l2capinbuf[16], 0x80); + Notify(PSTR(" "), 0x80); + PrintHex(l2capinbuf[15], 0x80); + Notify(PSTR(" "), 0x80); + PrintHex(l2capinbuf[14], 0x80); #endif } else if (l2capinbuf[8] == L2CAP_CMD_CONNECTION_REQUEST) { #ifdef EXTRADEBUG - Notify(PSTR("\r\nL2CAP Connection Request - PSM: ")); - PrintHex(l2capinbuf[13]); - Notify(PSTR(" ")); - PrintHex(l2capinbuf[12]); - Notify(PSTR(" SCID: ")); - PrintHex(l2capinbuf[15]); - Notify(PSTR(" ")); - PrintHex(l2capinbuf[14]); - Notify(PSTR(" Identifier: ")); - PrintHex(l2capinbuf[9]); + Notify(PSTR("\r\nL2CAP Connection Request - PSM: "), 0x80); + PrintHex(l2capinbuf[13], 0x80); + Notify(PSTR(" "), 0x80); + PrintHex(l2capinbuf[12], 0x80); + Notify(PSTR(" SCID: "), 0x80); + PrintHex(l2capinbuf[15], 0x80); + Notify(PSTR(" "), 0x80); + PrintHex(l2capinbuf[14], 0x80); + Notify(PSTR(" Identifier: "), 0x80); + PrintHex(l2capinbuf[9], 0x80); #endif if ((l2capinbuf[12] | (l2capinbuf[13] << 8)) == SDP_PSM) { // It doesn't matter if it receives another reqeust, since it waits for the channel to disconnect in the L2CAP_SDP_DONE state, and the l2cap_event_flag will be cleared if so identifier = l2capinbuf[9]; @@ -157,11 +157,11 @@ void SPP::ACLData(uint8_t* l2capinbuf) { } } else if (l2capinbuf[8] == L2CAP_CMD_DISCONNECT_REQUEST) { if (l2capinbuf[12] == sdp_dcid[0] && l2capinbuf[13] == sdp_dcid[1]) { - //Notify(PSTR("\r\nDisconnect Request: SDP Channel")); + //Notify(PSTR("\r\nDisconnect Request: SDP Channel"), 0x80); identifier = l2capinbuf[9]; l2cap_event_flag |= L2CAP_FLAG_DISCONNECT_SDP_REQUEST; } else if (l2capinbuf[12] == rfcomm_dcid[0] && l2capinbuf[13] == rfcomm_dcid[1]) { - //Notify(PSTR("\r\nDisconnect Request: RFCOMM Channel")); + //Notify(PSTR("\r\nDisconnect Request: RFCOMM Channel"), 0x80); identifier = l2capinbuf[9]; l2cap_event_flag |= L2CAP_FLAG_DISCONNECT_RFCOMM_REQUEST; } @@ -177,15 +177,15 @@ void SPP::ACLData(uint8_t* l2capinbuf) { } } else if (l2capinbuf[8] == L2CAP_CMD_INFORMATION_REQUEST) { #ifdef DEBUG - Notify(PSTR("\r\nInformation request")); + Notify(PSTR("\r\nInformation request"), 0x80); #endif identifier = l2capinbuf[9]; pBtd->l2cap_information_response(hci_handle,identifier,l2capinbuf[12],l2capinbuf[13]); } #ifdef EXTRADEBUG else { - Notify(PSTR("\r\nL2CAP Unknown Signaling Command: ")); - PrintHex(l2capinbuf[8]); + Notify(PSTR("\r\nL2CAP Unknown Signaling Command: "), 0x80); + PrintHex(l2capinbuf[8], 0x80); } #endif } else if (l2capinbuf[6] == sdp_dcid[0] && l2capinbuf[7] == sdp_dcid[1]) { // SDP @@ -221,25 +221,25 @@ void SPP::ACLData(uint8_t* l2capinbuf) { rfcommCommandResponse = l2capinbuf[8] & 0x02; rfcommChannelType = l2capinbuf[9] & 0xEF; rfcommPfBit = l2capinbuf[9] & 0x10; - + if(rfcommChannel>>3 != 0x00) rfcommChannelConnection = rfcommChannel; - + #ifdef EXTRADEBUG - Notify(PSTR("\r\nRFCOMM Channel: ")); + Notify(PSTR("\r\nRFCOMM Channel: "), 0x80); Serial.print(rfcommChannel>>3,HEX); - Notify(PSTR(" Direction: ")); + Notify(PSTR(" Direction: "), 0x80); Serial.print(rfcommDirection>>2,HEX); - Notify(PSTR(" CommandResponse: ")); + Notify(PSTR(" CommandResponse: "), 0x80); Serial.print(rfcommCommandResponse>>1,HEX); - Notify(PSTR(" ChannelType: ")); + Notify(PSTR(" ChannelType: "), 0x80); Serial.print(rfcommChannelType,HEX); - Notify(PSTR(" PF_BIT: ")); + Notify(PSTR(" PF_BIT: "), 0x80); Serial.print(rfcommPfBit,HEX); #endif if (rfcommChannelType == RFCOMM_DISC) { #ifdef DEBUG - Notify(PSTR("\r\nReceived Disconnect RFCOMM Command on channel: ")); + Notify(PSTR("\r\nReceived Disconnect RFCOMM Command on channel: "), 0x80); Serial.print(rfcommChannel>>3,HEX); #endif connected = false; @@ -256,10 +256,10 @@ void SPP::ACLData(uint8_t* l2capinbuf) { rfcommAvailable += length; } #ifdef EXTRADEBUG - Notify(PSTR("\r\nRFCOMM Data Available: ")); + Notify(PSTR("\r\nRFCOMM Data Available: "), 0x80); Serial.print(rfcommAvailable); if (offset) { - Notify(PSTR(" - Credit: 0x")); + Notify(PSTR(" - Credit: 0x"), 0x80); Serial.print(l2capinbuf[11],HEX); } #endif @@ -269,7 +269,7 @@ void SPP::ACLData(uint8_t* l2capinbuf) { #endif } else if (rfcommChannelType == RFCOMM_UIH && l2capinbuf[11] == BT_RFCOMM_RPN_CMD) { // UIH Remote Port Negotiation Command #ifdef DEBUG - Notify(PSTR("\r\nReceived UIH Remote Port Negotiation Command")); + Notify(PSTR("\r\nReceived UIH Remote Port Negotiation Command"), 0x80); #endif rfcommbuf[0] = BT_RFCOMM_RPN_RSP; // Command rfcommbuf[1] = l2capinbuf[12]; // Length and shiftet like so: length << 1 | 1 @@ -284,7 +284,7 @@ void SPP::ACLData(uint8_t* l2capinbuf) { sendRfcomm(rfcommChannel,rfcommDirection,0,RFCOMM_UIH,rfcommPfBit,rfcommbuf,0x0A); // UIH Remote Port Negotiation Response } else if(rfcommChannelType == RFCOMM_UIH && l2capinbuf[11] == BT_RFCOMM_MSC_CMD) { // UIH Modem Status Command #ifdef DEBUG - Notify(PSTR("\r\nSend UIH Modem Status Response")); + Notify(PSTR("\r\nSend UIH Modem Status Response"), 0x80); #endif rfcommbuf[0] = BT_RFCOMM_MSC_RSP; // UIH Modem Status Response rfcommbuf[1] = 2 << 1 | 1; // Length and shiftet like so: length << 1 | 1 @@ -295,12 +295,12 @@ void SPP::ACLData(uint8_t* l2capinbuf) { } else { if(rfcommChannelType == RFCOMM_SABM) { // SABM Command - this is sent twice: once for channel 0 and then for the channel to establish #ifdef DEBUG - Notify(PSTR("\r\nReceived SABM Command")); -#endif + Notify(PSTR("\r\nReceived SABM Command"), 0x80); +#endif sendRfcomm(rfcommChannel,rfcommDirection,rfcommCommandResponse,RFCOMM_UA,rfcommPfBit,rfcommbuf,0x00); // UA Command } else if(rfcommChannelType == RFCOMM_UIH && l2capinbuf[11] == BT_RFCOMM_PN_CMD) { // UIH Parameter Negotiation Command #ifdef DEBUG - Notify(PSTR("\r\nReceived UIH Parameter Negotiation Command")); + Notify(PSTR("\r\nReceived UIH Parameter Negotiation Command"), 0x80); #endif rfcommbuf[0] = BT_RFCOMM_PN_RSP; // UIH Parameter Negotiation Response rfcommbuf[1] = l2capinbuf[12]; // Length and shiftet like so: length << 1 | 1 @@ -315,28 +315,28 @@ void SPP::ACLData(uint8_t* l2capinbuf) { sendRfcomm(rfcommChannel,rfcommDirection,0,RFCOMM_UIH,rfcommPfBit,rfcommbuf,0x0A); } else if(rfcommChannelType == RFCOMM_UIH && l2capinbuf[11] == BT_RFCOMM_MSC_CMD) { // UIH Modem Status Command #ifdef DEBUG - Notify(PSTR("\r\nSend UIH Modem Status Response")); + Notify(PSTR("\r\nSend UIH Modem Status Response"), 0x80); #endif rfcommbuf[0] = BT_RFCOMM_MSC_RSP; // UIH Modem Status Response rfcommbuf[1] = 2 << 1 | 1; // Length and shiftet like so: length << 1 | 1 rfcommbuf[2] = l2capinbuf[13]; // Channel: (1 << 0) | (1 << 1) | (0 << 2) | (channel << 3) rfcommbuf[3] = l2capinbuf[14]; sendRfcomm(rfcommChannel,rfcommDirection,0,RFCOMM_UIH,rfcommPfBit,rfcommbuf,0x04); - + delay(1); #ifdef DEBUG - Notify(PSTR("\r\nSend UIH Modem Status Command")); + Notify(PSTR("\r\nSend UIH Modem Status Command"), 0x80); #endif rfcommbuf[0] = BT_RFCOMM_MSC_CMD; // UIH Modem Status Command rfcommbuf[1] = 2 << 1 | 1; // Length and shiftet like so: length << 1 | 1 rfcommbuf[2] = l2capinbuf[13]; // Channel: (1 << 0) | (1 << 1) | (0 << 2) | (channel << 3) rfcommbuf[3] = 0x8D; // Can receive frames (YES), Ready to Communicate (YES), Ready to Receive (YES), Incomig Call (NO), Data is Value (YES) - + sendRfcomm(rfcommChannel,rfcommDirection,0,RFCOMM_UIH,rfcommPfBit,rfcommbuf,0x04); } else if(rfcommChannelType == RFCOMM_UIH && l2capinbuf[11] == BT_RFCOMM_MSC_RSP) { // UIH Modem Status Response if(!creditSent) { #ifdef DEBUG - Notify(PSTR("\r\nSend UIH Command with credit")); + Notify(PSTR("\r\nSend UIH Command with credit"), 0x80); #endif sendRfcommCredit(rfcommChannelConnection,rfcommDirection,0,RFCOMM_UIH,0x10,sizeof(rfcommDataBuffer)); // Send credit creditSent = true; @@ -345,11 +345,11 @@ void SPP::ACLData(uint8_t* l2capinbuf) { } } else if(rfcommChannelType == RFCOMM_UIH && l2capinbuf[10] == 0x01) { // UIH Command with credit #ifdef DEBUG - Notify(PSTR("\r\nReceived UIH Command with credit")); -#endif + Notify(PSTR("\r\nReceived UIH Command with credit"), 0x80); +#endif } else if(rfcommChannelType == RFCOMM_UIH && l2capinbuf[11] == BT_RFCOMM_RPN_CMD) { // UIH Remote Port Negotiation Command #ifdef DEBUG - Notify(PSTR("\r\nReceived UIH Remote Port Negotiation Command")); + Notify(PSTR("\r\nReceived UIH Remote Port Negotiation Command"), 0x80); #endif rfcommbuf[0] = BT_RFCOMM_RPN_RSP; // Command rfcommbuf[1] = l2capinbuf[12]; // Length and shiftet like so: length << 1 | 1 @@ -363,28 +363,28 @@ void SPP::ACLData(uint8_t* l2capinbuf) { rfcommbuf[9] = l2capinbuf[20]; // Number of Frames sendRfcomm(rfcommChannel,rfcommDirection,0,RFCOMM_UIH,rfcommPfBit,rfcommbuf,0x0A); // UIH Remote Port Negotiation Response #ifdef DEBUG - Notify(PSTR("\r\nRFCOMM Connection is now established\r\n")); -#endif + Notify(PSTR("\r\nRFCOMM Connection is now established\r\n"), 0x80); +#endif waitForLastCommand = false; creditSent = false; connected = true; // The RFCOMM channel is now established } #ifdef DEBUG else if(rfcommChannelType != RFCOMM_DISC) { - Notify(PSTR("\r\nUnsupported RFCOMM Data - ChannelType: ")); - PrintHex(rfcommChannelType); - Notify(PSTR(" Command: ")); - PrintHex(l2capinbuf[11]); + Notify(PSTR("\r\nUnsupported RFCOMM Data - ChannelType: "), 0x80); + PrintHex(rfcommChannelType, 0x80); + Notify(PSTR(" Command: "), 0x80); + PrintHex(l2capinbuf[11], 0x80); } -#endif +#endif } } #ifdef EXTRADEBUG else { - Notify(PSTR("\r\nUnsupported L2CAP Data - Channel ID: ")); - PrintHex(l2capinbuf[7]); - Notify(PSTR(" ")); - PrintHex(l2capinbuf[6]); + Notify(PSTR("\r\nUnsupported L2CAP Data - Channel ID: "), 0x80); + PrintHex(l2capinbuf[7], 0x80); + Notify(PSTR(" "), 0x80); + PrintHex(l2capinbuf[6], 0x80); } #endif SDP_task(); @@ -394,12 +394,12 @@ void SPP::ACLData(uint8_t* l2capinbuf) { void SPP::Run() { if(waitForLastCommand && (millis() - timer) > 100) { // We will only wait 100ms and see if the UIH Remote Port Negotiation Command is send, as some deviced don't send it #ifdef DEBUG - Notify(PSTR("\r\nRFCOMM Connection is now established - Automatic\r\n")); + Notify(PSTR("\r\nRFCOMM Connection is now established - Automatic\r\n"), 0x80); #endif creditSent = false; waitForLastCommand = false; connected = true; // The RFCOMM channel is now established - } + } } void SPP::SDP_task() { switch (l2cap_sdp_state) @@ -408,24 +408,24 @@ void SPP::SDP_task() { if (l2cap_connection_request_sdp_flag) { l2cap_event_flag &= ~L2CAP_FLAG_CONNECTION_SDP_REQUEST; // Clear flag #ifdef DEBUG - Notify(PSTR("\r\nSDP Incoming Connection Request")); + Notify(PSTR("\r\nSDP Incoming Connection Request"), 0x80); #endif pBtd->l2cap_connection_response(hci_handle,identifier, sdp_dcid, sdp_scid, PENDING); delay(1); - pBtd->l2cap_connection_response(hci_handle,identifier, sdp_dcid, sdp_scid, SUCCESSFUL); + pBtd->l2cap_connection_response(hci_handle,identifier, sdp_dcid, sdp_scid, SUCCESSFUL); identifier++; delay(1); - pBtd->l2cap_config_request(hci_handle,identifier, sdp_scid); - l2cap_sdp_state = L2CAP_SDP_REQUEST; - } + pBtd->l2cap_config_request(hci_handle,identifier, sdp_scid); + l2cap_sdp_state = L2CAP_SDP_REQUEST; + } break; case L2CAP_SDP_REQUEST: if (l2cap_config_request_sdp_flag) { l2cap_event_flag &= ~L2CAP_FLAG_CONFIG_SDP_REQUEST; // Clear flag #ifdef DEBUG - Notify(PSTR("\r\nSDP Configuration Request")); -#endif - pBtd->l2cap_config_response(hci_handle,identifier, sdp_scid); + Notify(PSTR("\r\nSDP Configuration Request"), 0x80); +#endif + pBtd->l2cap_config_response(hci_handle,identifier, sdp_scid); l2cap_sdp_state = L2CAP_SDP_SUCCESS; } break; @@ -433,7 +433,7 @@ void SPP::SDP_task() { if (l2cap_config_success_sdp_flag) { l2cap_event_flag &= ~L2CAP_FLAG_CONFIG_SDP_SUCCESS; // Clear flag #ifdef DEBUG - Notify(PSTR("\r\nSDP Successfully Configured")); + Notify(PSTR("\r\nSDP Successfully Configured"), 0x80); #endif firstMessage = true; // Reset bool SDPConnected = true; @@ -445,9 +445,9 @@ void SPP::SDP_task() { l2cap_event_flag &= ~L2CAP_FLAG_DISCONNECT_SDP_REQUEST; // Clear flag SDPConnected = false; #ifdef DEBUG - Notify(PSTR("\r\nDisconnected SDP Channel")); + Notify(PSTR("\r\nDisconnected SDP Channel"), 0x80); #endif - pBtd->l2cap_disconnection_response(hci_handle,identifier,sdp_dcid,sdp_scid); + pBtd->l2cap_disconnection_response(hci_handle,identifier,sdp_dcid,sdp_scid); l2cap_sdp_state = L2CAP_SDP_WAIT; } else if(l2cap_connection_request_sdp_flag) l2cap_rfcomm_state = L2CAP_SDP_WAIT; @@ -455,7 +455,7 @@ void SPP::SDP_task() { case L2CAP_DISCONNECT_RESPONSE: // This is for both disconnection response from the RFCOMM and SDP channel if they were connected if (l2cap_disconnect_response_flag) { #ifdef DEBUG - Notify(PSTR("\r\nDisconnected L2CAP Connection")); + Notify(PSTR("\r\nDisconnected L2CAP Connection"), 0x80); #endif RFCOMMConnected = false; SDPConnected = false; @@ -465,35 +465,35 @@ void SPP::SDP_task() { l2cap_sdp_state = L2CAP_SDP_WAIT; l2cap_rfcomm_state = L2CAP_RFCOMM_WAIT; } - break; + break; } } void SPP::RFCOMM_task() -{ +{ switch (l2cap_rfcomm_state) { - case L2CAP_RFCOMM_WAIT: + case L2CAP_RFCOMM_WAIT: if(l2cap_connection_request_rfcomm_flag) { l2cap_event_flag &= ~L2CAP_FLAG_CONNECTION_RFCOMM_REQUEST; // Clear flag #ifdef DEBUG - Notify(PSTR("\r\nRFCOMM Incoming Connection Request")); + Notify(PSTR("\r\nRFCOMM Incoming Connection Request"), 0x80); #endif - pBtd->l2cap_connection_response(hci_handle,identifier, rfcomm_dcid, rfcomm_scid, PENDING); + pBtd->l2cap_connection_response(hci_handle,identifier, rfcomm_dcid, rfcomm_scid, PENDING); delay(1); - pBtd->l2cap_connection_response(hci_handle,identifier, rfcomm_dcid, rfcomm_scid, SUCCESSFUL); + pBtd->l2cap_connection_response(hci_handle,identifier, rfcomm_dcid, rfcomm_scid, SUCCESSFUL); identifier++; delay(1); - pBtd->l2cap_config_request(hci_handle,identifier, rfcomm_scid); - l2cap_rfcomm_state = L2CAP_RFCOMM_REQUEST; - } - break; + pBtd->l2cap_config_request(hci_handle,identifier, rfcomm_scid); + l2cap_rfcomm_state = L2CAP_RFCOMM_REQUEST; + } + break; case L2CAP_RFCOMM_REQUEST: if (l2cap_config_request_rfcomm_flag) { l2cap_event_flag &= ~L2CAP_FLAG_CONFIG_RFCOMM_REQUEST; // Clear flag #ifdef DEBUG - Notify(PSTR("\r\nRFCOMM Configuration Request")); + Notify(PSTR("\r\nRFCOMM Configuration Request"), 0x80); #endif - pBtd->l2cap_config_response(hci_handle,identifier, rfcomm_scid); + pBtd->l2cap_config_response(hci_handle,identifier, rfcomm_scid); l2cap_rfcomm_state = L2CAP_RFCOMM_SUCCESS; } break; @@ -501,27 +501,27 @@ void SPP::RFCOMM_task() if (l2cap_config_success_rfcomm_flag) { l2cap_event_flag &= ~L2CAP_FLAG_CONFIG_RFCOMM_SUCCESS; // Clear flag #ifdef DEBUG - Notify(PSTR("\r\nRFCOMM Successfully Configured")); -#endif + Notify(PSTR("\r\nRFCOMM Successfully Configured"), 0x80); +#endif rfcommAvailable = 0; // Reset number of bytes available bytesRead = 0; // Reset number of bytes received RFCOMMConnected = true; l2cap_rfcomm_state = L2CAP_RFCOMM_DONE; } - break; + break; case L2CAP_RFCOMM_DONE: if(l2cap_disconnect_request_rfcomm_flag) { l2cap_event_flag &= ~L2CAP_FLAG_DISCONNECT_RFCOMM_REQUEST; // Clear flag RFCOMMConnected = false; connected = false; #ifdef DEBUG - Notify(PSTR("\r\nDisconnected RFCOMM Channel")); + Notify(PSTR("\r\nDisconnected RFCOMM Channel"), 0x80); #endif pBtd->l2cap_disconnection_response(hci_handle,identifier,rfcomm_dcid,rfcomm_scid); l2cap_rfcomm_state = L2CAP_RFCOMM_WAIT; } else if(l2cap_connection_request_rfcomm_flag) l2cap_rfcomm_state = L2CAP_RFCOMM_WAIT; - break; + break; } } /************************************************************/ @@ -538,12 +538,12 @@ void SPP::serviceNotSupported(uint8_t transactionIDHigh, uint8_t transactionIDLo l2capoutbuf[4] = 0x05; // Parameter Length l2capoutbuf[5] = 0x00; // AttributeListsByteCount l2capoutbuf[6] = 0x02; // AttributeListsByteCount - + /* Attribute ID/Value Sequence: */ l2capoutbuf[7] = 0x35; l2capoutbuf[8] = 0x00; l2capoutbuf[9] = 0x00; - + SDP_Command(l2capoutbuf,10); } void SPP::serialPortResponse1(uint8_t transactionIDHigh, uint8_t transactionIDLow) { @@ -561,7 +561,7 @@ void SPP::serialPortResponse1(uint8_t transactionIDHigh, uint8_t transactionIDLo l2capoutbuf[9] = 0x3C; l2capoutbuf[10] = 0x36; l2capoutbuf[11] = 0x00; - + l2capoutbuf[12] = 0x39; l2capoutbuf[13] = 0x09; l2capoutbuf[14] = 0x00; @@ -578,7 +578,7 @@ void SPP::serialPortResponse1(uint8_t transactionIDHigh, uint8_t transactionIDLo l2capoutbuf[25] = 0x03; l2capoutbuf[26] = 0x19; l2capoutbuf[27] = 0x11; - + l2capoutbuf[28] = 0x01; l2capoutbuf[29] = 0x09; l2capoutbuf[30] = 0x00; @@ -595,13 +595,13 @@ void SPP::serialPortResponse1(uint8_t transactionIDHigh, uint8_t transactionIDLo l2capoutbuf[41] = 0x19; l2capoutbuf[42] = 0x00; l2capoutbuf[43] = 0x03; - + l2capoutbuf[44] = 0x08; l2capoutbuf[45] = 0x02; // Two extra bytes l2capoutbuf[46] = 0x00; // 25 (0x19) more bytes to come - l2capoutbuf[47] = 0x19; - - SDP_Command(l2capoutbuf,48); + l2capoutbuf[47] = 0x19; + + SDP_Command(l2capoutbuf,48); } void SPP::serialPortResponse2(uint8_t transactionIDHigh, uint8_t transactionIDLow) { l2capoutbuf[0] = SDP_SERVICE_SEARCH_ATTRIBUTE_RESPONSE_PDU; @@ -611,14 +611,14 @@ void SPP::serialPortResponse2(uint8_t transactionIDHigh, uint8_t transactionIDLo l2capoutbuf[4] = 0x1C; // Parameter Length l2capoutbuf[5] = 0x00; // AttributeListsByteCount l2capoutbuf[6] = 0x19; // AttributeListsByteCount - + /* Attribute ID/Value Sequence: */ l2capoutbuf[7] = 0x01; l2capoutbuf[8] = 0x09; l2capoutbuf[9] = 0x00; l2capoutbuf[10] = 0x06; l2capoutbuf[11] = 0x35; - + l2capoutbuf[12] = 0x09; l2capoutbuf[13] = 0x09; l2capoutbuf[14] = 0x65; @@ -634,7 +634,7 @@ void SPP::serialPortResponse2(uint8_t transactionIDHigh, uint8_t transactionIDLo l2capoutbuf[24] = 0x00; l2capoutbuf[25] = 0x25; - l2capoutbuf[26] = 0x05; // Name length + l2capoutbuf[26] = 0x05; // Name length l2capoutbuf[27] = 'T'; l2capoutbuf[28] = 'K'; l2capoutbuf[29] = 'J'; @@ -648,7 +648,7 @@ void SPP::l2capResponse1(uint8_t transactionIDHigh, uint8_t transactionIDLow) { serialPortResponse1(transactionIDHigh,transactionIDLow); // These has to send all the supported functions, since it only supports virtual serialport it just sends the message again } void SPP::l2capResponse2(uint8_t transactionIDHigh, uint8_t transactionIDLow) { - serialPortResponse2(transactionIDHigh,transactionIDLow); // Same data as serialPortResponse2 + serialPortResponse2(transactionIDHigh,transactionIDLow); // Same data as serialPortResponse2 } /************************************************************/ /* RFCOMM Commands */ @@ -666,26 +666,26 @@ void SPP::sendRfcomm(uint8_t channel, uint8_t direction, uint8_t CR, uint8_t cha l2capoutbuf[i+3] = data[i]; l2capoutbuf[i+3] = calcFcs(l2capoutbuf); #ifdef EXTRADEBUG - Notify(PSTR(" - RFCOMM Data: ")); + Notify(PSTR(" - RFCOMM Data: "), 0x80); for(i = 0; i < length+4; i++) { Serial.print(l2capoutbuf[i],HEX); - Notify(PSTR(" ")); + Notify(PSTR(" "), 0x80); } -#endif +#endif RFCOMM_Command(l2capoutbuf,length+4); -} +} void SPP::sendRfcommCredit(uint8_t channel, uint8_t direction, uint8_t CR, uint8_t channelType, uint8_t pfBit, uint8_t credit) { l2capoutbuf[0] = channel | direction | CR | extendAddress; // RFCOMM Address l2capoutbuf[1] = channelType | pfBit; // RFCOMM Control l2capoutbuf[2] = 0x01; // Length = 0 l2capoutbuf[3] = credit; // Credit - l2capoutbuf[4] = calcFcs(l2capoutbuf); + l2capoutbuf[4] = calcFcs(l2capoutbuf); #ifdef EXTRADEBUG - Notify(PSTR(" - RFCOMM Credit Data: ")); + Notify(PSTR(" - RFCOMM Credit Data: "), 0x80); for(uint8_t i = 0; i < 5; i++) { Serial.print(l2capoutbuf[i],HEX); - Notify(PSTR(" ")); + Notify(PSTR(" "), 0x80); } #endif RFCOMM_Command(l2capoutbuf,5); @@ -714,11 +714,11 @@ void SPP::print(const String &str) { l2capoutbuf[0] = rfcommChannelConnection | 0 | 0 | extendAddress;; // RFCOMM Address l2capoutbuf[1] = RFCOMM_UIH; // RFCOMM Control l2capoutbuf[2] = length << 1 | 1; // Length - uint8_t i = 0; + uint8_t i = 0; for(; i < length; i++) l2capoutbuf[i+3] = str[i]; l2capoutbuf[i+3] = calcFcs(l2capoutbuf); - + RFCOMM_Command(l2capoutbuf,length+4); } void SPP::print(const char* str) { @@ -728,13 +728,13 @@ void SPP::print(const char* str) { if(length > (sizeof(l2capoutbuf)-4)) length = sizeof(l2capoutbuf)-4; l2capoutbuf[0] = rfcommChannelConnection | 0 | 0 | extendAddress;; // RFCOMM Address - l2capoutbuf[1] = RFCOMM_UIH; // RFCOMM Control + l2capoutbuf[1] = RFCOMM_UIH; // RFCOMM Control l2capoutbuf[2] = length << 1 | 1; // Length uint8_t i = 0; for(; i < length; i++) - l2capoutbuf[i+3] = str[i]; - l2capoutbuf[i+3] = calcFcs(l2capoutbuf); - + l2capoutbuf[i+3] = str[i]; + l2capoutbuf[i+3] = calcFcs(l2capoutbuf); + RFCOMM_Command(l2capoutbuf,length+4); } void SPP::print(uint8_t* array, uint8_t length) { @@ -749,7 +749,7 @@ void SPP::print(uint8_t* array, uint8_t length) { for(; i < length; i++) l2capoutbuf[i+3] = array[i]; l2capoutbuf[i+3] = calcFcs(l2capoutbuf); - + RFCOMM_Command(l2capoutbuf,length+4); } void SPP::println(const String &str) { @@ -783,10 +783,10 @@ void SPP::printFlashString(const __FlashStringHelper *ifsh, bool newline) { size++; } uint8_t buf[size+2]; // Add two extra in case it needs to print a newline and carriage return - + for(uint8_t i = 0; i < size; i++) buf[i] = pgm_read_byte(p++); - + if(newline) { buf[size] = '\r'; buf[size+1] = '\n'; @@ -868,13 +868,13 @@ void SPP::doubleToString(double input, char* output, uint8_t digits) { } else strcpy(output,""); - + // Round correctly double rounding = 0.5; for (uint8_t i=0; iregisterServiceClass(this); // Register it as a Bluetooth service - + pBtd->pairWithWii = pair; - + HIDBuffer[0] = 0xA2;// HID BT DATA_request (0xA0) | Report Type (Output 0x02) - + /* Set device cid for the control and intterrupt channelse - LSB */ control_dcid[0] = 0x60;//0x0060 control_dcid[1] = 0x00; interrupt_dcid[0] = 0x61;//0x0061 interrupt_dcid[1] = 0x00; - + Reset(); } void WII::Reset() { @@ -117,10 +117,10 @@ void WII::Reset() { void WII::disconnect() { // Use this void to disconnect any of the controllers if(motionPlusConnected && !pBtd->motionPlusInside) { // Disable the Motion Plus extension -#ifdef DEBUG - Notify(PSTR("\r\nDeactivating Motion Plus")); +#ifdef DEBUG + Notify(PSTR("\r\nDeactivating Motion Plus"), 0x80); #endif - initExtension1(); // This will disable the Motion Plus extension + initExtension1(); // This will disable the Motion Plus extension } //First the HID interrupt channel has to be disconencted, then the HID control channel and finally the HCI connection pBtd->l2cap_disconnection_request(hci_handle,0x0A, interrupt_scid, interrupt_dcid); @@ -144,18 +144,18 @@ void WII::ACLData(uint8_t* l2capinbuf) { if ((l2capinbuf[6] | (l2capinbuf[7] << 8)) == 0x0001) { //l2cap_control - Channel ID for ACL-U if (l2capinbuf[8] == L2CAP_CMD_COMMAND_REJECT) { #ifdef DEBUG - Notify(PSTR("\r\nL2CAP Command Rejected - Reason: ")); - PrintHex(l2capinbuf[13]); - Notify(PSTR(" ")); - PrintHex(l2capinbuf[12]); - Notify(PSTR(" ")); - PrintHex(l2capinbuf[17]); - Notify(PSTR(" ")); - PrintHex(l2capinbuf[16]); - Notify(PSTR(" ")); - PrintHex(l2capinbuf[15]); - Notify(PSTR(" ")); - PrintHex(l2capinbuf[14]); + Notify(PSTR("\r\nL2CAP Command Rejected - Reason: "), 0x80); + PrintHex(l2capinbuf[13], 0x80); + Notify(PSTR(" "), 0x80); + PrintHex(l2capinbuf[12], 0x80); + Notify(PSTR(" "), 0x80); + PrintHex(l2capinbuf[17], 0x80); + Notify(PSTR(" "), 0x80); + PrintHex(l2capinbuf[16], 0x80); + Notify(PSTR(" "), 0x80); + PrintHex(l2capinbuf[15], 0x80); + Notify(PSTR(" "), 0x80); + PrintHex(l2capinbuf[14], 0x80); #endif } else if (l2capinbuf[8] == L2CAP_CMD_CONNECTION_RESPONSE) { @@ -175,19 +175,19 @@ void WII::ACLData(uint8_t* l2capinbuf) { l2cap_event_flag |= L2CAP_FLAG_INTERRUPT_CONNECTED; } } - } + } else if (l2capinbuf[8] == L2CAP_CMD_CONNECTION_REQUEST) { #ifdef EXTRADEBUG - Notify(PSTR("\r\nL2CAP Connection Request - PSM: ")); - PrintHex(l2capinbuf[13]); - Notify(PSTR(" ")); - PrintHex(l2capinbuf[12]); - Notify(PSTR(" SCID: ")); - PrintHex(l2capinbuf[15]); - Notify(PSTR(" ")); - PrintHex(l2capinbuf[14]); - Notify(PSTR(" Identifier: ")); - PrintHex(l2capinbuf[9]); + Notify(PSTR("\r\nL2CAP Connection Request - PSM: "), 0x80); + PrintHex(l2capinbuf[13], 0x80); + Notify(PSTR(" "), 0x80); + PrintHex(l2capinbuf[12], 0x80); + Notify(PSTR(" SCID: "), 0x80); + PrintHex(l2capinbuf[15], 0x80); + Notify(PSTR(" "), 0x80); + PrintHex(l2capinbuf[14], 0x80); + Notify(PSTR(" Identifier: "), 0x80); + PrintHex(l2capinbuf[9], 0x80); #endif if ((l2capinbuf[12] | (l2capinbuf[13] << 8)) == HID_CTRL_PSM) { identifier = l2capinbuf[9]; @@ -211,7 +211,7 @@ void WII::ACLData(uint8_t* l2capinbuf) { } else if (l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) { //Serial.print("\r\nHID Interrupt Configuration Complete"); - identifier = l2capinbuf[9]; + identifier = l2capinbuf[9]; l2cap_event_flag |= L2CAP_FLAG_CONFIG_INTERRUPT_SUCCESS; } } @@ -229,18 +229,18 @@ void WII::ACLData(uint8_t* l2capinbuf) { else if (l2capinbuf[8] == L2CAP_CMD_DISCONNECT_REQUEST) { if (l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) { #ifdef DEBUG - Notify(PSTR("\r\nDisconnect Request: Control Channel")); + Notify(PSTR("\r\nDisconnect Request: Control Channel"), 0x80); #endif identifier = l2capinbuf[9]; - pBtd->l2cap_disconnection_response(hci_handle,identifier,control_dcid,control_scid); + pBtd->l2cap_disconnection_response(hci_handle,identifier,control_dcid,control_scid); Reset(); } else if (l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) { #ifdef DEBUG - Notify(PSTR("\r\nDisconnect Request: Interrupt Channel")); + Notify(PSTR("\r\nDisconnect Request: Interrupt Channel"), 0x80); #endif identifier = l2capinbuf[9]; - pBtd->l2cap_disconnection_response(hci_handle,identifier,interrupt_dcid,interrupt_scid); + pBtd->l2cap_disconnection_response(hci_handle,identifier,interrupt_dcid,interrupt_scid); Reset(); } } @@ -259,8 +259,8 @@ void WII::ACLData(uint8_t* l2capinbuf) { #ifdef EXTRADEBUG else { identifier = l2capinbuf[9]; - Notify(PSTR("\r\nL2CAP Unknown Signaling Command: ")); - PrintHex(l2capinbuf[8]); + Notify(PSTR("\r\nL2CAP Unknown Signaling Command: "), 0x80); + PrintHex(l2capinbuf[8], 0x80); } #endif } else if (l2capinbuf[6] == interrupt_dcid[0] && l2capinbuf[7] == interrupt_dcid[1]) { // l2cap_interrupt @@ -285,11 +285,11 @@ void WII::ACLData(uint8_t* l2capinbuf) { else if(!unknownExtensionConnected) ButtonState = (uint32_t)((l2capinbuf[10] & 0x1F) | ((uint16_t)(l2capinbuf[11] & 0x9F) << 8)); #ifdef PRINTREPORT - Notify(PSTR("ButtonState: ")); - PrintHex(ButtonState); - Notify(PSTR("\r\n")); + Notify(PSTR("ButtonState: "), 0x80); + PrintHex(ButtonState, 0x80); + Notify(PSTR("\r\n"), 0x80); #endif - if(ButtonState != OldButtonState) { + if(ButtonState != OldButtonState) { ButtonClickState = ButtonState & ~OldButtonState; // Update click state variable OldButtonState = ButtonState; } @@ -297,7 +297,7 @@ void WII::ACLData(uint8_t* l2capinbuf) { if(l2capinbuf[9] == 0x31 || l2capinbuf[9] == 0x33 || l2capinbuf[9] == 0x35 || l2capinbuf[9] == 0x37) { // Read the accelerometer accX = ((l2capinbuf[12] << 2) | (l2capinbuf[10] & 0x60 >> 5))-500; accY = ((l2capinbuf[13] << 2) | (l2capinbuf[11] & 0x20 >> 4))-500; - accZ = ((l2capinbuf[14] << 2) | (l2capinbuf[11] & 0x40 >> 5))-500; + accZ = ((l2capinbuf[14] << 2) | (l2capinbuf[11] & 0x40 >> 5))-500; wiimotePitch = (atan2(accY,accZ)+PI)*RAD_TO_DEG; wiimoteRoll = (atan2(accX,accZ)+PI)*RAD_TO_DEG; } @@ -307,27 +307,27 @@ void WII::ACLData(uint8_t* l2capinbuf) { batteryLevel = l2capinbuf[15]; // Update battery level if(l2capinbuf[12] & 0x01) { #ifdef DEBUG - Notify(PSTR("\r\nWARNING: Battery is nearly empty")); -#endif + Notify(PSTR("\r\nWARNING: Battery is nearly empty"), 0x80); +#endif } if(l2capinbuf[12] & 0x02) { // Check if a extension is connected #ifdef DEBUG if(!unknownExtensionConnected) - Notify(PSTR("\r\nExtension connected")); + Notify(PSTR("\r\nExtension connected"), 0x80); #endif unknownExtensionConnected = true; #ifdef WIICAMERA if(!isIRCameraEnabled()) // Don't activate the Motion Plus if we are trying to initialize the IR camera -#endif +#endif setReportMode(false,0x35); // Also read the extension } else { #ifdef DEBUG - Notify(PSTR("\r\nExtension disconnected")); + Notify(PSTR("\r\nExtension disconnected"), 0x80); #endif if(motionPlusConnected) { #ifdef DEBUG - Notify(PSTR(" - from Motion Plus")); + Notify(PSTR(" - from Motion Plus"), 0x80); #endif l2cap_event_flag &= ~WII_FLAG_NUNCHUCK_CONNECTED; if(!activateNunchuck) // If it's already trying to initialize the Nunchuck don't set it to false @@ -336,82 +336,82 @@ void WII::ACLData(uint8_t* l2capinbuf) { } else if(nunchuckConnected) { #ifdef DEBUG - Notify(PSTR(" - Nunchuck")); + Notify(PSTR(" - Nunchuck"), 0x80); #endif nunchuckConnected = false; // It must be the Nunchuck controller then l2cap_event_flag &= ~WII_FLAG_NUNCHUCK_CONNECTED; setLedStatus(); setReportMode(false,0x31); // If there is no extension connected we will read the button and accelerometer } else { - setReportMode(false,0x31); // If there is no extension connected we will read the button and accelerometer + setReportMode(false,0x31); // If there is no extension connected we will read the button and accelerometer } } break; case 0x21: // Read Memory Data if((l2capinbuf[12] & 0x0F) == 0) { // No error // See: http://wiibrew.org/wiki/Wiimote/Extension_Controllers - if(l2capinbuf[16] == 0x00 && l2capinbuf[17] == 0xA4 && l2capinbuf[18] == 0x20 && l2capinbuf[19] == 0x00 && l2capinbuf[20] == 0x00) { + if(l2capinbuf[16] == 0x00 && l2capinbuf[17] == 0xA4 && l2capinbuf[18] == 0x20 && l2capinbuf[19] == 0x00 && l2capinbuf[20] == 0x00) { #ifdef DEBUG - Notify(PSTR("\r\nNunchuck connected")); + Notify(PSTR("\r\nNunchuck connected"), 0x80); #endif - l2cap_event_flag |= WII_FLAG_NUNCHUCK_CONNECTED; + l2cap_event_flag |= WII_FLAG_NUNCHUCK_CONNECTED; } else if(l2capinbuf[16] == 0x00 && (l2capinbuf[17] == 0xA6 || l2capinbuf[17] == 0xA4) && l2capinbuf[18] == 0x20 && l2capinbuf[19] == 0x00 && l2capinbuf[20] == 0x05) { #ifdef DEBUG - Notify(PSTR("\r\nMotion Plus connected")); + Notify(PSTR("\r\nMotion Plus connected"), 0x80); #endif l2cap_event_flag |= WII_FLAG_MOTION_PLUS_CONNECTED; } else if(l2capinbuf[16] == 0x00 && l2capinbuf[17] == 0xA4 && l2capinbuf[18] == 0x20 && l2capinbuf[19] == 0x04 && l2capinbuf[20] == 0x05) { #ifdef DEBUG - Notify(PSTR("\r\nMotion Plus activated in normal mode")); + Notify(PSTR("\r\nMotion Plus activated in normal mode"), 0x80); #endif motionPlusConnected = true; } else if(l2capinbuf[16] == 0x00 && l2capinbuf[17] == 0xA4 && l2capinbuf[18] == 0x20 && l2capinbuf[19] == 0x05 && l2capinbuf[20] == 0x05) { #ifdef DEBUG - Notify(PSTR("\r\nMotion Plus activated in Nunchuck pass-through mode")); + Notify(PSTR("\r\nMotion Plus activated in Nunchuck pass-through mode"), 0x80); #endif activateNunchuck = false; motionPlusConnected = true; nunchuckConnected = true; } else if(l2capinbuf[16] == 0x00 && l2capinbuf[17] == 0xA6 && l2capinbuf[18] == 0x20 && (l2capinbuf[19] == 0x00 || l2capinbuf[19] == 0x04 || l2capinbuf[19] == 0x05 || l2capinbuf[19] == 0x07) && l2capinbuf[20] == 0x05) { #ifdef DEBUG - Notify(PSTR("\r\nInactive Wii Motion Plus")); - Notify(PSTR("\r\nPlease unplug the Motion Plus, disconnect the Wiimote and then replug the Motion Plus Extension")); + Notify(PSTR("\r\nInactive Wii Motion Plus"), 0x80); + Notify(PSTR("\r\nPlease unplug the Motion Plus, disconnect the Wiimote and then replug the Motion Plus Extension"), 0x80); #endif stateCounter = 300; // Skip the rest in "L2CAP_CHECK_MOTION_PLUS_STATE" } else if(l2capinbuf[16] == 0x00 && l2capinbuf[17] == 0xA4 && l2capinbuf[18] == 0x20 && l2capinbuf[19] == 0x01 && l2capinbuf[20] == 0x20) { #ifdef DEBUG - Notify(PSTR("\r\nWii U Pro Controller connected")); + Notify(PSTR("\r\nWii U Pro Controller connected"), 0x80); #endif wiiUProControllerConnected = true; } #ifdef DEBUG else { - Notify(PSTR("\r\nUnknown Device: ")); - PrintHex(l2capinbuf[13]); - PrintHex(l2capinbuf[14]); - Notify(PSTR("\r\nData: ")); + Notify(PSTR("\r\nUnknown Device: "), 0x80); + PrintHex(l2capinbuf[13], 0x80); + PrintHex(l2capinbuf[14], 0x80); + Notify(PSTR("\r\nData: "), 0x80); for(uint8_t i = 0; i < ((l2capinbuf[12] >> 4)+1); i++) { // bit 4-7 is the length-1 - PrintHex(l2capinbuf[15+i]); - Notify(PSTR(" ")); + PrintHex(l2capinbuf[15+i], 0x80); + Notify(PSTR(" "), 0x80); } } #endif } #ifdef EXTRADEBUG else { - Notify(PSTR("\r\nReport Error: ")); - PrintHex(l2capinbuf[13]); - PrintHex(l2capinbuf[14]); + Notify(PSTR("\r\nReport Error: "), 0x80); + PrintHex(l2capinbuf[13], 0x80); + PrintHex(l2capinbuf[14], 0x80); } #endif break; case 0x22: // Acknowledge output report, return function result #ifdef DEBUG if(l2capinbuf[13] != 0x00) { // Check if there is an error - Notify(PSTR("\r\nCommand failed: ")); - PrintHex(l2capinbuf[12]); + Notify(PSTR("\r\nCommand failed: "), 0x80); + PrintHex(l2capinbuf[12], 0x80); } -#endif +#endif break; case 0x30: // Core buttons - (a1) 30 BB BB break; @@ -425,7 +425,7 @@ void WII::ACLData(uint8_t* l2capinbuf) { pitch = wiimotePitch; // The pitch is just equal to the angle calculated from the wiimote as there is no Motion Plus data available roll = wiimoteRoll; #ifdef WIICAMERA - // Read the IR data + // Read the IR data IR_object_x1 = (l2capinbuf[15] | ((uint16_t)(l2capinbuf[17] & 0x30) << 4)); // x position IR_object_y1 = (l2capinbuf[16] | ((uint16_t)(l2capinbuf[17] & 0xC0) << 2)); // y position IR_object_s1 = (l2capinbuf[17] & 0x0F); // size value, 0-15 @@ -447,7 +447,7 @@ void WII::ACLData(uint8_t* l2capinbuf) { break; /* 0x3e and 0x3f both give unknown report types when report mode is 0x3e or 0x3f with mode number 0x05 */ case 0x3E: // Core Buttons with Accelerometer and 32 IR bytes - // (a1) 31 BB BB AA AA AA II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II + // (a1) 31 BB BB AA AA AA II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II // corresponds to output report mode 0x3e /**** for reading in full mode: DOES NOT WORK YET ****/ @@ -456,7 +456,7 @@ void WII::ACLData(uint8_t* l2capinbuf) { IR_object_x1 = (l2capinbuf[13] | ((uint16_t)(l2capinbuf[15] & 0x30) << 4)); IR_object_y1 = (l2capinbuf[14] | ((uint16_t)(l2capinbuf[15] & 0xC0) << 2)); IR_object_s1 = (l2capinbuf[15] & 0x0F); - */ + */ break; case 0x3F: /* @@ -466,7 +466,7 @@ void WII::ACLData(uint8_t* l2capinbuf) { */ break; case 0x35: // Core Buttons and Accelerometer with 16 Extension Bytes - // (a1) 35 BB BB AA AA AA EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE + // (a1) 35 BB BB AA AA AA EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE if(motionPlusConnected) { if(l2capinbuf[20] & 0x02) { // Check if it's a report from the Motion controller or the extension if(motionValuesReset) { // We will only use the values when the gyro value has been set @@ -477,7 +477,7 @@ void WII::ACLData(uint8_t* l2capinbuf) { yawGyroSpeed = (double)gyroYawRaw/((double)gyroYawZero/yawGyroScale); rollGyroSpeed = -(double)gyroRollRaw/((double)gyroRollZero/rollGyroScale); // We invert these values so they will fit the acc values pitchGyroSpeed = (double)gyroPitchRaw/((double)gyroPitchZero/pitchGyroScale); - + /* The onboard gyro has two ranges for slow and fast mode */ if(!(l2capinbuf[18] & 0x02)) // Check if fast more is used yawGyroSpeed *= 4.545; @@ -485,10 +485,10 @@ void WII::ACLData(uint8_t* l2capinbuf) { pitchGyroSpeed *= 4.545; if(!(l2capinbuf[19] & 0x02)) // Check if fast more is used rollGyroSpeed *= 4.545; - + pitch = (0.93*(pitch+(pitchGyroSpeed*(double)(micros()-timer)/1000000)))+(0.07*wiimotePitch); // Use a complimentary filter to calculate the angle roll = (0.93*(roll+(rollGyroSpeed*(double)(micros()-timer)/1000000)))+(0.07*wiimoteRoll); - + gyroYaw += (yawGyroSpeed*((double)(micros()-timer)/1000000)); gyroRoll += (rollGyroSpeed*((double)(micros()-timer)/1000000)); gyroPitch += (pitchGyroSpeed*((double)(micros()-timer)/1000000)); @@ -503,20 +503,20 @@ void WII::ACLData(uint8_t* l2capinbuf) { Serial.print(gyroPitch); */ /* - Serial.print("\twiimoteRoll: "); + Serial.print("\twiimoteRoll: "); Serial.print(wiimoteRoll); Serial.print("\twiimotePitch: "); Serial.print(wiimotePitch); - */ + */ } else { if((micros() - timer) > 1000000) { // Loop for 1 sec before resetting the values #ifdef DEBUG - Notify(PSTR("\r\nThe gyro values has been reset")); + Notify(PSTR("\r\nThe gyro values has been reset"), 0x80); #endif gyroYawZero = (l2capinbuf[15] | ((l2capinbuf[18] & 0xFC) << 6)); gyroRollZero = (l2capinbuf[16] | ((l2capinbuf[19] & 0xFC) << 6)); gyroPitchZero = (l2capinbuf[17] | ((l2capinbuf[20] & 0xFC) << 6)); - + rollGyroScale = 500; // You might need to adjust these pitchGyroScale = 400; yawGyroScale = 415; @@ -524,10 +524,10 @@ void WII::ACLData(uint8_t* l2capinbuf) { gyroYaw = 0; gyroRoll = 0; gyroPitch = 0; - + motionValuesReset = true; timer = micros(); - } + } } } else { if(nunchuckConnected) { @@ -539,14 +539,14 @@ void WII::ACLData(uint8_t* l2capinbuf) { nunchuckPitch = (atan2(accY,accZ)+PI)*RAD_TO_DEG; nunchuckRoll = (atan2(accX,accZ)+PI)*RAD_TO_DEG; } - //else if(classicControllerConnected) { } + //else if(classicControllerConnected) { } } if(l2capinbuf[19] & 0x01) { if(!extensionConnected) { extensionConnected = true; unknownExtensionConnected = true; #ifdef DEBUG - Notify(PSTR("\r\nExtension connected to Motion Plus")); + Notify(PSTR("\r\nExtension connected to Motion Plus"), 0x80); #endif } } @@ -555,12 +555,12 @@ void WII::ACLData(uint8_t* l2capinbuf) { extensionConnected = false; unknownExtensionConnected = true; #ifdef DEBUG - Notify(PSTR("\r\nExtension disconnected from Motion Plus")); + Notify(PSTR("\r\nExtension disconnected from Motion Plus"), 0x80); #endif nunchuckConnected = false; // There is no extension connected to the Motion Plus if this report is sent } } - + } else if(nunchuckConnected) { hatValues[HatX] = l2capinbuf[15]; hatValues[HatY] = l2capinbuf[16]; @@ -569,7 +569,7 @@ void WII::ACLData(uint8_t* l2capinbuf) { accZ = ((l2capinbuf[19] << 2) | (l2capinbuf[20] & 0xC0 >> 6))-416; nunchuckPitch = (atan2(accY,accZ)+PI)*RAD_TO_DEG; nunchuckRoll = (atan2(accX,accZ)+PI)*RAD_TO_DEG; - + pitch = wiimotePitch; // The pitch is just equal to the angle calculated from the wiimote as there is no Motion Plus connected roll = wiimoteRoll; } else if(wiiUProControllerConnected) { @@ -581,11 +581,11 @@ void WII::ACLData(uint8_t* l2capinbuf) { break; #ifdef DEBUG default: - Notify(PSTR("\r\nUnknown Report type: ")); + Notify(PSTR("\r\nUnknown Report type: "), 0x80); Serial.print(l2capinbuf[9],HEX); break; #endif - } + } } } } @@ -598,16 +598,16 @@ void WII::L2CAP_task() { case L2CAP_CONTROL_SUCCESS: if (l2cap_config_success_control_flag) { #ifdef DEBUG - Notify(PSTR("\r\nHID Control Successfully Configured")); + Notify(PSTR("\r\nHID Control Successfully Configured"), 0x80); #endif l2cap_state = L2CAP_INTERRUPT_SETUP; } break; - + case L2CAP_INTERRUPT_SETUP: if (l2cap_connection_request_interrupt_flag) { #ifdef DEBUG - Notify(PSTR("\r\nHID Interrupt Incoming Connection Request")); + Notify(PSTR("\r\nHID Interrupt Incoming Connection Request"), 0x80); #endif pBtd->l2cap_connection_response(hci_handle,identifier, interrupt_dcid, interrupt_scid, PENDING); delay(1); @@ -615,7 +615,7 @@ void WII::L2CAP_task() { identifier++; delay(1); pBtd->l2cap_config_request(hci_handle,identifier, interrupt_scid); - + l2cap_state = L2CAP_INTERRUPT_CONFIG_REQUEST; } break; @@ -624,40 +624,40 @@ void WII::L2CAP_task() { case L2CAP_CONTROL_CONNECT_REQUEST: if (l2cap_connected_control_flag) { #ifdef DEBUG - Notify(PSTR("\r\nSend HID Control Config Request")); + Notify(PSTR("\r\nSend HID Control Config Request"), 0x80); #endif identifier++; pBtd->l2cap_config_request(hci_handle, identifier, control_scid); l2cap_state = L2CAP_CONTROL_CONFIG_REQUEST; } break; - + case L2CAP_CONTROL_CONFIG_REQUEST: if(l2cap_config_success_control_flag) { #ifdef DEBUG - Notify(PSTR("\r\nSend HID Interrupt Connection Request")); + Notify(PSTR("\r\nSend HID Interrupt Connection Request"), 0x80); #endif identifier++; pBtd->l2cap_connection_request(hci_handle,identifier,interrupt_dcid,HID_INTR_PSM); l2cap_state = L2CAP_INTERRUPT_CONNECT_REQUEST; } break; - + case L2CAP_INTERRUPT_CONNECT_REQUEST: if(l2cap_connected_interrupt_flag) { #ifdef DEBUG - Notify(PSTR("\r\nSend HID Interrupt Config Request")); + Notify(PSTR("\r\nSend HID Interrupt Config Request"), 0x80); #endif identifier++; pBtd->l2cap_config_request(hci_handle, identifier, interrupt_scid); l2cap_state = L2CAP_INTERRUPT_CONFIG_REQUEST; } break; - + case L2CAP_INTERRUPT_CONFIG_REQUEST: if(l2cap_config_success_interrupt_flag) { // Now the HID channels is established #ifdef DEBUG - Notify(PSTR("\r\nHID Channels Established")); + Notify(PSTR("\r\nHID Channels Established"), 0x80); #endif pBtd->connectToWii = false; pBtd->pairWithWii = false; @@ -666,24 +666,24 @@ void WII::L2CAP_task() { l2cap_state = L2CAP_CHECK_MOTION_PLUS_STATE; } break; - - /* The next states are in run() */ - + + /* The next states are in run() */ + case L2CAP_INTERRUPT_DISCONNECT: if (l2cap_disconnect_response_interrupt_flag) { #ifdef DEBUG - Notify(PSTR("\r\nDisconnected Interrupt Channel")); + Notify(PSTR("\r\nDisconnected Interrupt Channel"), 0x80); #endif identifier++; - pBtd->l2cap_disconnection_request(hci_handle, identifier, control_scid, control_dcid); + pBtd->l2cap_disconnection_request(hci_handle, identifier, control_scid, control_dcid); l2cap_state = L2CAP_CONTROL_DISCONNECT; } break; - + case L2CAP_CONTROL_DISCONNECT: if (l2cap_disconnect_response_control_flag) { #ifdef DEBUG - Notify(PSTR("\r\nDisconnected Control Channel")); + Notify(PSTR("\r\nDisconnected Control Channel"), 0x80); #endif pBtd->hci_disconnect(hci_handle); hci_handle = -1; // Reset handle @@ -691,7 +691,7 @@ void WII::L2CAP_task() { l2cap_state = L2CAP_WAIT; } break; - } + } } void WII::Run() { switch (l2cap_state) { @@ -700,16 +700,16 @@ void WII::Run() { pBtd->l2capConnectionClaimed = true; activeConnection = true; #ifdef DEBUG - Notify(PSTR("\r\nSend HID Control Connection Request")); + Notify(PSTR("\r\nSend HID Control Connection Request"), 0x80); #endif - hci_handle = pBtd->hci_handle; // Store the HCI Handle for the connection + hci_handle = pBtd->hci_handle; // Store the HCI Handle for the connection l2cap_event_flag = 0; // Reset flags identifier = 0; pBtd->l2cap_connection_request(hci_handle,identifier,control_dcid,HID_CTRL_PSM); - l2cap_state = L2CAP_CONTROL_CONNECT_REQUEST; + l2cap_state = L2CAP_CONTROL_CONNECT_REQUEST; } else if (l2cap_connection_request_control_flag) { #ifdef DEBUG - Notify(PSTR("\r\nHID Control Incoming Connection Request")); + Notify(PSTR("\r\nHID Control Incoming Connection Request"), 0x80); #endif pBtd->l2cap_connection_response(hci_handle,identifier, control_dcid, control_scid, PENDING); delay(1); @@ -719,12 +719,12 @@ void WII::Run() { pBtd->l2cap_config_request(hci_handle,identifier, control_scid); l2cap_state = L2CAP_CONTROL_SUCCESS; } - break; - + break; + case L2CAP_CHECK_MOTION_PLUS_STATE: #ifdef DEBUG if(stateCounter == 0) // Only print onnce - Notify(PSTR("\r\nChecking if a Motion Plus is connected")); + Notify(PSTR("\r\nChecking if a Motion Plus is connected"), 0x80); #endif stateCounter++; if(stateCounter%200 == 0) @@ -733,28 +733,28 @@ void WII::Run() { stateCounter = 0; l2cap_state = L2CAP_INIT_MOTION_PLUS_STATE; timer = micros(); - + if(unknownExtensionConnected) { #ifdef DEBUG - Notify(PSTR("\r\nA extension is also connected")); + Notify(PSTR("\r\nA extension is also connected"), 0x80); #endif activateNunchuck = true; // For we will just set this to true as this the only extension supported so far } - + } else if(stateCounter == 601) { // We will try three times to check for the motion plus -#ifdef DEBUG - Notify(PSTR("\r\nNo Motion Plus was detected")); +#ifdef DEBUG + Notify(PSTR("\r\nNo Motion Plus was detected"), 0x80); #endif stateCounter = 0; l2cap_state = L2CAP_CHECK_EXTENSION_STATE; } break; - + case L2CAP_CHECK_EXTENSION_STATE: // This is used to check if there is anything plugged in to the extension port #ifdef DEBUG if(stateCounter == 0) // Only print onnce - Notify(PSTR("\r\nChecking if there is any extension connected")); + Notify(PSTR("\r\nChecking if there is any extension connected"), 0x80); #endif stateCounter++; // We use this counter as there has to be a short delay between the commands if(stateCounter == 1) @@ -774,7 +774,7 @@ void WII::Run() { l2cap_state = L2CAP_LED_STATE; } break; - + case L2CAP_INIT_MOTION_PLUS_STATE: stateCounter++; if(stateCounter == 1) @@ -784,24 +784,24 @@ void WII::Run() { else if(stateCounter == 200) readExtensionType(); // Check if it has been activated else if(stateCounter == 300) { - stateCounter = 0; + stateCounter = 0; unknownExtensionConnected = false; // The motion plus will send a status report when it's activated, we will set this to false so it doesn't reinitialize the Motion Plus l2cap_state = L2CAP_LED_STATE; } break; - + case L2CAP_LED_STATE: if(nunchuck_connected_flag) nunchuckConnected = true; setLedStatus(); l2cap_state = L2CAP_DONE; break; - + case L2CAP_DONE: if(unknownExtensionConnected) { #ifdef DEBUG if(stateCounter == 0) // Only print once - Notify(PSTR("\r\nChecking extension port")); + Notify(PSTR("\r\nChecking extension port"), 0x80); #endif stateCounter++; // We will use this counter as there has to be a short delay between the commands if(stateCounter == 50) @@ -818,7 +818,7 @@ void WII::Run() { else if(stateCounter == 250) { if(nunchuck_connected_flag) { #ifdef DEBUG - Notify(PSTR("\r\nNunchuck was reconnected")); + Notify(PSTR("\r\nNunchuck was reconnected"), 0x80); #endif activateNunchuck = true; nunchuckConnected = true; @@ -829,7 +829,7 @@ void WII::Run() { else if (stateCounter == 300) { if(motionPlusConnected) { #ifdef DEBUG - Notify(PSTR("\r\nReactivating the Motion Plus")); + Notify(PSTR("\r\nReactivating the Motion Plus"), 0x80); #endif initMotionPlus(); } else @@ -867,7 +867,7 @@ void WII::setAllOff() { void WII::setRumbleOff() { HIDBuffer[1] = 0x11; HIDBuffer[2] &= ~0x01; // Bit 0 control the rumble - HID_Command(HIDBuffer, 3); + HID_Command(HIDBuffer, 3); } void WII::setRumbleOn() { HIDBuffer[1] = 0x11; @@ -963,12 +963,12 @@ void WII::activateMotionPlus() { uint8_t buf[1]; if(pBtd->wiiUProController) { #ifdef DEBUG - Notify(PSTR("\r\nActivating Wii U Pro Controller")); + Notify(PSTR("\r\nActivating Wii U Pro Controller"), 0x80); #endif buf[0] = 0x00; // It seems like you can send anything but 0x04, 0x05, and 0x07 } else if(activateNunchuck) { #ifdef DEBUG - Notify(PSTR("\r\nActivating Motion Plus in pass-through mode")); + Notify(PSTR("\r\nActivating Motion Plus in pass-through mode"), 0x80); #endif buf[0] = 0x05; // Activate nunchuck pass-through mode } @@ -976,7 +976,7 @@ void WII::activateMotionPlus() { //buf[0] = 0x07; else { #ifdef DEBUG - Notify(PSTR("\r\nActivating Motion Plus in normal mode")); + Notify(PSTR("\r\nActivating Motion Plus in normal mode"), 0x80); #endif buf[0] = 0x04; // Don't use any extension } @@ -989,13 +989,13 @@ void WII::readData(uint32_t offset, uint16_t size, bool EEPROM) { if(EEPROM) cmd_buf[2] = 0x00 | (HIDBuffer[2] & 0x01); // Read from EEPROM else - cmd_buf[2] = 0x04 | (HIDBuffer[2] & 0x01); // Read from memory + cmd_buf[2] = 0x04 | (HIDBuffer[2] & 0x01); // Read from memory cmd_buf[3] = (uint8_t)((offset & 0xFF0000) >> 16); cmd_buf[4] = (uint8_t)((offset & 0xFF00) >> 8); cmd_buf[5] = (uint8_t)(offset & 0xFF); cmd_buf[6] = (uint8_t)((size & 0xFF00) >> 8); cmd_buf[7] = (uint8_t)(size & 0xFF); - + HID_Command(cmd_buf,8); } void WII::readExtensionType() { @@ -1014,7 +1014,7 @@ void WII::checkMotionPresent() { bool WII::getButtonPress(Button b) { // Return true when a button is pressed if(wiiUProControllerConnected) - return (ButtonState & pgm_read_dword(&PROCONTROLLERBUTTONS[(uint8_t)b])); + return (ButtonState & pgm_read_dword(&PROCONTROLLERBUTTONS[(uint8_t)b])); else return (ButtonState & pgm_read_dword(&BUTTONS[(uint8_t)b])); } @@ -1057,69 +1057,69 @@ uint16_t WII::getAnalogHat(AnalogHat a) { #ifdef WIICAMERA void WII::IRinitialize(){ // Turns on and initialises the IR camera - + enableIRCamera1(); #ifdef DEBUG - Notify(PSTR("\r\nEnable IR Camera1 Complete")); + Notify(PSTR("\r\nEnable IR Camera1 Complete"), 0x80); #endif delay(80); - + enableIRCamera2(); #ifdef DEBUG - Notify(PSTR("\r\nEnable IR Camera2 Complete")); + Notify(PSTR("\r\nEnable IR Camera2 Complete"), 0x80); #endif delay(80); - + write0x08Value(); #ifdef DEBUG - Notify(PSTR("\r\nWrote hex number 0x08")); + Notify(PSTR("\r\nWrote hex number 0x08"), 0x80); #endif delay(80); - + writeSensitivityBlock1(); #ifdef DEBUG - Notify(PSTR("\r\nWrote Sensitivity Block 1")); + Notify(PSTR("\r\nWrote Sensitivity Block 1"), 0x80); #endif delay(80); - + writeSensitivityBlock2(); #ifdef DEBUG - Notify(PSTR("\r\nWrote Sensitivity Block 2")); + Notify(PSTR("\r\nWrote Sensitivity Block 2"), 0x80); #endif delay(80); uint8_t mode_num = 0x03; setWiiModeNumber(mode_num); // Change input for whatever mode you want i.e. 0x01, 0x03, or 0x05 #ifdef DEBUG - Notify(PSTR("\r\nSet Wii Mode Number To 0x")); - PrintHex(mode_num); + Notify(PSTR("\r\nSet Wii Mode Number To 0x"), 0x80); + PrintHex(mode_num, 0x80); #endif delay(80); - + write0x08Value(); #ifdef DEBUG - Notify(PSTR("\r\nWrote Hex Number 0x08")); + Notify(PSTR("\r\nWrote Hex Number 0x08"), 0x80); #endif delay(80); setReportMode(false, 0x33); //setReportMode(false, 0x3f); // For full reporting mode, doesn't work yet #ifdef DEBUG - Notify(PSTR("\r\nSet Report Mode to 0x33")); + Notify(PSTR("\r\nSet Report Mode to 0x33"), 0x80); #endif delay(80); - + statusRequest(); // Used to update wiiState - call isIRCameraEnabled() afterwards to check if it actually worked #ifdef DEBUG - Notify(PSTR("\r\nIR Initialized")); -#endif + Notify(PSTR("\r\nIR Initialized"), 0x80); +#endif } void WII::enableIRCamera1(){ uint8_t cmd_buf[3]; cmd_buf[0] = 0xA2; // HID BT DATA_request (0xA0) | Report Type (Output 0x02) cmd_buf[1] = 0x13; // Output report 13 - cmd_buf[2] = 0x04 | (HIDBuffer[2] & 0x01); // Keep the rumble bit and sets bit 2 + cmd_buf[2] = 0x04 | (HIDBuffer[2] & 0x01); // Keep the rumble bit and sets bit 2 HID_Command(cmd_buf, 3); } @@ -1127,7 +1127,7 @@ void WII::enableIRCamera2(){ uint8_t cmd_buf[3]; cmd_buf[0] = 0xA2; // HID BT DATA_request (0xA0) | Report Type (Output 0x02) cmd_buf[1] = 0x1A; // Output report 1A - cmd_buf[2] = 0x04 | (HIDBuffer[2] & 0x01); // Keep the rumble bit and sets bit 2 + cmd_buf[2] = 0x04 | (HIDBuffer[2] & 0x01); // Keep the rumble bit and sets bit 2 HID_Command(cmd_buf, 3); } @@ -1162,4 +1162,4 @@ void WII::write0x08Value(){ void WII::setWiiModeNumber(uint8_t mode_number){ // mode_number in hex i.e. 0x03 for extended mode writeData(0xb00033,1,&mode_number); } -#endif \ No newline at end of file +#endif diff --git a/XBOXRECV.cpp b/XBOXRECV.cpp index e4d0627a..ab0df9ef 100644 --- a/XBOXRECV.cpp +++ b/XBOXRECV.cpp @@ -1,15 +1,15 @@ /* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved. - + This software may be distributed and modified under the terms of the GNU General Public License version 2 (GPL2) as published by the Free Software Foundation and appearing in the file GPL2.TXT included in the packaging of this file. Please note that GPL2 Section 2[b] requires that all works based on this software must also be made publicly available under the terms of the GPL2 ("Copyleft"). - + Contact information ------------------- - + Kristian Lauszus, TKJ Electronics Web : http://www.tkjelectronics.com e-mail : kristianl@tkjelectronics.com @@ -29,10 +29,10 @@ bPollEnable(false) { // don't start polling before dongle is connected for(uint8_t i=0; iRegisterDeviceClass(this); //set devConfig[] entry } @@ -44,74 +44,74 @@ uint8_t XBOXRECV::Init(uint8_t parent, uint8_t port, bool lowspeed) { EpInfo *oldep_ptr = NULL; uint16_t PID; uint16_t VID; - + // get memory address of USB device address pool - AddressPool &addrPool = pUsb->GetAddressPool(); + AddressPool &addrPool = pUsb->GetAddressPool(); #ifdef EXTRADEBUG - Notify(PSTR("\r\nXBOXRECV Init")); + Notify(PSTR("\r\nXBOXRECV Init"), 0x80); #endif // check if address has already been assigned to an instance if (bAddress) { #ifdef DEBUG - Notify(PSTR("\r\nAddress in use")); + Notify(PSTR("\r\nAddress in use"), 0x80); #endif return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE; } - + // Get pointer to pseudo device with address 0 assigned p = addrPool.GetUsbDevicePtr(0); - - if (!p) { + + if (!p) { #ifdef DEBUG - Notify(PSTR("\r\nAddress not found")); + Notify(PSTR("\r\nAddress not found"), 0x80); #endif return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; } - + if (!p->epinfo) { #ifdef DEBUG - Notify(PSTR("\r\nepinfo is null")); + Notify(PSTR("\r\nepinfo is null"), 0x80); #endif return USB_ERROR_EPINFO_IS_NULL; } - + // Save old pointer to EP_RECORD of address 0 oldep_ptr = p->epinfo; - + // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence p->epinfo = epInfo; - + p->lowspeed = lowspeed; - + // Get device descriptor rcode = pUsb->getDevDescr(0, 0, sizeof(USB_DEVICE_DESCRIPTOR), (uint8_t*)buf);// Get device descriptor - addr, ep, nbytes, data // Restore p->epinfo p->epinfo = oldep_ptr; - + if(rcode) goto FailGetDevDescr; - + VID = ((USB_DEVICE_DESCRIPTOR*)buf)->idVendor; PID = ((USB_DEVICE_DESCRIPTOR*)buf)->idProduct; - + if(VID != XBOX_VID && VID != MADCATZ_VID) // We just check if it's a xbox receiver using the Vendor ID goto FailUnknownDevice; else if(PID != XBOX_WIRELESS_RECEIVER_PID && PID != XBOX_WIRELESS_RECEIVER_THIRD_PARTY_PID) { #ifdef DEBUG - Notify(PSTR("\r\nYou'll need a wireless receiver for this libary to work")); + Notify(PSTR("\r\nYou'll need a wireless receiver for this libary to work"), 0x80); #endif goto FailUnknownDevice; - } - + } + // Allocate new address according to device class bAddress = addrPool.AllocAddress(parent, false, port); - + if (!bAddress) return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; - + // Extract Max Packet Size from device descriptor - epInfo[0].maxPktSize = (uint8_t)((USB_DEVICE_DESCRIPTOR*)buf)->bMaxPacketSize0; - + epInfo[0].maxPktSize = (uint8_t)((USB_DEVICE_DESCRIPTOR*)buf)->bMaxPacketSize0; + // Assign new address to the device rcode = pUsb->setAddr( 0, 0, bAddress ); if (rcode) { @@ -119,33 +119,33 @@ uint8_t XBOXRECV::Init(uint8_t parent, uint8_t port, bool lowspeed) { addrPool.FreeAddress(bAddress); bAddress = 0; #ifdef DEBUG - Notify(PSTR("\r\nsetAddr: ")); + Notify(PSTR("\r\nsetAddr: "), 0x80); #endif - PrintHex(rcode); + PrintHex(rcode, 0x80); return rcode; } #ifdef EXTRADEBUG - Notify(PSTR("\r\nAddr: ")); - PrintHex(bAddress); + Notify(PSTR("\r\nAddr: "), 0x80); + PrintHex(bAddress, 0x80); #endif p->lowspeed = false; - + //get pointer to assigned address record p = addrPool.GetUsbDevicePtr(bAddress); - if (!p) + if (!p) return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; - - p->lowspeed = lowspeed; - + + p->lowspeed = lowspeed; + // Assign epInfo to epinfo pointer - only EP0 is known rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); if (rcode) goto FailSetDevTblEntry; - + /* The application will work in reduced host mode, so we can save program and data memory space. After verifying the VID we will use known values for the configuration values for device, interface, endpoints and HID for the XBOX360 Wireless receiver */ - + /* Initialize data structures for endpoints of device */ epInfo[ XBOX_INPUT_PIPE_1 ].epAddr = 0x01; // XBOX 360 report endpoint - poll interval 1ms epInfo[ XBOX_INPUT_PIPE_1 ].epAttribs = EP_INTERRUPT; @@ -159,7 +159,7 @@ uint8_t XBOXRECV::Init(uint8_t parent, uint8_t port, bool lowspeed) { epInfo[ XBOX_OUTPUT_PIPE_1 ].maxPktSize = EP_MAXPKTSIZE; epInfo[ XBOX_OUTPUT_PIPE_1 ].bmSndToggle = bmSNDTOG0; epInfo[ XBOX_OUTPUT_PIPE_1 ].bmRcvToggle = bmRCVTOG0; - + epInfo[ XBOX_INPUT_PIPE_2 ].epAddr = 0x03; // XBOX 360 report endpoint - poll interval 1ms epInfo[ XBOX_INPUT_PIPE_2 ].epAttribs = EP_INTERRUPT; epInfo[ XBOX_INPUT_PIPE_2 ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints @@ -172,7 +172,7 @@ uint8_t XBOXRECV::Init(uint8_t parent, uint8_t port, bool lowspeed) { epInfo[ XBOX_OUTPUT_PIPE_2 ].maxPktSize = EP_MAXPKTSIZE; epInfo[ XBOX_OUTPUT_PIPE_2 ].bmSndToggle = bmSNDTOG0; epInfo[ XBOX_OUTPUT_PIPE_2 ].bmRcvToggle = bmRCVTOG0; - + epInfo[ XBOX_INPUT_PIPE_3 ].epAddr = 0x05; // XBOX 360 report endpoint - poll interval 1ms epInfo[ XBOX_INPUT_PIPE_3 ].epAttribs = EP_INTERRUPT; epInfo[ XBOX_INPUT_PIPE_3 ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints @@ -185,7 +185,7 @@ uint8_t XBOXRECV::Init(uint8_t parent, uint8_t port, bool lowspeed) { epInfo[ XBOX_OUTPUT_PIPE_3 ].maxPktSize = EP_MAXPKTSIZE; epInfo[ XBOX_OUTPUT_PIPE_3 ].bmSndToggle = bmSNDTOG0; epInfo[ XBOX_OUTPUT_PIPE_3 ].bmRcvToggle = bmRCVTOG0; - + epInfo[ XBOX_INPUT_PIPE_4 ].epAddr = 0x07; // XBOX 360 report endpoint - poll interval 1ms epInfo[ XBOX_INPUT_PIPE_4 ].epAttribs = EP_INTERRUPT; epInfo[ XBOX_INPUT_PIPE_4 ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints @@ -198,54 +198,54 @@ uint8_t XBOXRECV::Init(uint8_t parent, uint8_t port, bool lowspeed) { epInfo[ XBOX_OUTPUT_PIPE_4 ].maxPktSize = EP_MAXPKTSIZE; epInfo[ XBOX_OUTPUT_PIPE_4 ].bmSndToggle = bmSNDTOG0; epInfo[ XBOX_OUTPUT_PIPE_4 ].bmRcvToggle = bmRCVTOG0; - + rcode = pUsb->setEpInfoEntry(bAddress, 9, epInfo); if( rcode ) goto FailSetDevTblEntry; - + delay(200);//Give time for address change - + rcode = pUsb->setConf(bAddress, epInfo[ XBOX_CONTROL_PIPE ].epAddr, 1); if( rcode ) - goto FailSetConf; + goto FailSetConf; #ifdef DEBUG - Notify(PSTR("\r\nXbox Wireless Receiver Connected\r\n")); + Notify(PSTR("\r\nXbox Wireless Receiver Connected\r\n"), 0x80); #endif XboxReceiverConnected = true; bPollEnable = true; return 0; // successful configuration - - /* diagnostic messages */ + + /* diagnostic messages */ FailGetDevDescr: #ifdef DEBUG - Notify(PSTR("\r\ngetDevDescr:")); + Notify(PSTR("\r\ngetDevDescr:"), 0x80); #endif - goto Fail; + goto Fail; FailSetDevTblEntry: #ifdef DEBUG - Notify(PSTR("\r\nsetDevTblEn:")); + Notify(PSTR("\r\nsetDevTblEn:"), 0x80); #endif goto Fail; FailSetConf: #ifdef DEBUG - Notify(PSTR("\r\nsetConf:")); + Notify(PSTR("\r\nsetConf:"), 0x80); #endif - goto Fail; + goto Fail; FailUnknownDevice: #ifdef DEBUG - Notify(PSTR("\r\nUnknown Device Connected - VID: ")); - PrintHex(VID); - Notify(PSTR(" PID: ")); - PrintHex(PID); + Notify(PSTR("\r\nUnknown Device Connected - VID: "), 0x80); + PrintHex(VID, 0x80); + Notify(PSTR(" PID: "), 0x80); + PrintHex(PID, 0x80); #endif rcode = USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; goto Fail; Fail: #ifdef DEBUG - Notify(PSTR("\r\nXbox 360 Init Failed, error code: ")); + Notify(PSTR("\r\nXbox 360 Init Failed, error code: "), 0x80); Serial.print(rcode,HEX); -#endif +#endif Release(); return rcode; } @@ -255,12 +255,12 @@ uint8_t XBOXRECV::Release() { XboxReceiverConnected = false; for(uint8_t i=0;i<4;i++) Xbox360Connected[i] = 0x00; - pUsb->GetAddressPool().FreeAddress(bAddress); + pUsb->GetAddressPool().FreeAddress(bAddress); bAddress = 0; bPollEnable = false; return 0; } -uint8_t XBOXRECV::Poll() { +uint8_t XBOXRECV::Poll() { if (!bPollEnable) return 0; if(!timer || ((millis() - timer) > 3000)) { // Run checkStatus every 3 seconds @@ -269,7 +269,7 @@ uint8_t XBOXRECV::Poll() { } uint8_t inputPipe; uint16_t bufferSize; - for(uint8_t i=0;i<4;i++) { + for(uint8_t i=0;i<4;i++) { switch (i) { case 0: inputPipe = XBOX_INPUT_PIPE_1; break; case 1: inputPipe = XBOX_INPUT_PIPE_2; break; @@ -280,14 +280,14 @@ uint8_t XBOXRECV::Poll() { pUsb->inTransfer(bAddress, epInfo[ inputPipe ].epAddr, &bufferSize, readBuf); if(bufferSize > 0) { // The number of received bytes #ifdef EXTRADEBUG - Notify(PSTR("Bytes Received: ")); + Notify(PSTR("Bytes Received: "), 0x80); Serial.print(bufferSize); - Notify(PSTR("\r\n")); + Notify(PSTR("\r\n"), 0x80); #endif readReport(i); #ifdef PRINTREPORT printReport(i,bufferSize); // Uncomment "#define PRINTREPORT" to print the report send by the Xbox 360 Controller -#endif +#endif } } return 0; @@ -300,7 +300,7 @@ void XBOXRECV::readReport(uint8_t controller) { if(readBuf[0] == 0x08 && readBuf[1] != Xbox360Connected[controller]) { Xbox360Connected[controller] = readBuf[1]; #ifdef DEBUG - Notify(PSTR("Controller ")); + Notify(PSTR("Controller "), 0x80); Serial.print(controller); #endif if(Xbox360Connected[controller]) { @@ -310,9 +310,9 @@ void XBOXRECV::readReport(uint8_t controller) { case 0x80: str = PSTR(" as controller\r\n"); break; case 0x40: str = PSTR(" as headset\r\n"); break; case 0xC0: str = PSTR(" as controller+headset\r\n"); break; - } - Notify(PSTR(": connected")); - Notify(str); + } + Notify(PSTR(": connected"), 0x80); + Notify(str, 0x80); #endif LED led; switch (controller) { @@ -325,7 +325,7 @@ void XBOXRECV::readReport(uint8_t controller) { } #ifdef DEBUG else - Notify(PSTR(": disconnected\r\n")); + Notify(PSTR(": disconnected\r\n"), 0x80); #endif return; } @@ -336,21 +336,21 @@ void XBOXRECV::readReport(uint8_t controller) { } if(readBuf[1] != 0x01) // Check if it's the correct report - the receiver also sends different status reports return; - + // A controller must be connected if it's sending data if(!Xbox360Connected[controller]) Xbox360Connected[controller] |= 0x80; ButtonState[controller] = (uint32_t)(readBuf[9] | ((uint16_t)readBuf[8] << 8) | ((uint32_t)readBuf[7] << 16) | ((uint32_t)readBuf[6] << 24)); - + hatValue[controller][LeftHatX] = (int16_t)(((uint16_t)readBuf[11] << 8) | readBuf[10]); hatValue[controller][LeftHatY] = (int16_t)(((uint16_t)readBuf[13] << 8) | readBuf[12]); hatValue[controller][RightHatX] = (int16_t)(((uint16_t)readBuf[15] << 8) | readBuf[14]); hatValue[controller][RightHatY] = (int16_t)(((uint16_t)readBuf[17] << 8) | readBuf[16]); - - //Notify(PSTR("\r\nButtonState: ")); - //PrintHex(ButtonState[controller]); - + + //Notify(PSTR("\r\nButtonState: "), 0x80); + //PrintHex(ButtonState[controller], 0x80); + if(ButtonState[controller] != OldButtonState[controller]) { buttonStateChanged[controller] = true; ButtonClickState[controller] = (ButtonState[controller] >> 16) & ((~OldButtonState[controller]) >> 16); // Update click state variable, but don't include the two trigger buttons L2 and R2 @@ -366,11 +366,11 @@ void XBOXRECV::printReport(uint8_t controller, uint8_t nBytes) { //Uncomment "#d #ifdef PRINTREPORT if (readBuf == NULL) return; - Notify(PSTR("Controller ")); + Notify(PSTR("Controller "), 0x80); Serial.print(controller); - Notify(PSTR(": ")); + Notify(PSTR(": "), 0x80); for(uint8_t i = 0; i < nBytes;i++) { - PrintHex(readBuf[i]); + PrintHex(readBuf[i], 0x80); Serial.print(" "); } Serial.println(); @@ -433,8 +433,8 @@ ControllerStatus Breakdown uint8_t XBOXRECV::getBatteryLevel(uint8_t controller) { uint8_t batteryLevel = ((controllerStatus[controller] & 0x00C0) >> 6) * 33; if(batteryLevel == 99) - batteryLevel = 100; - return batteryLevel; + batteryLevel = 100; + return batteryLevel; } void XBOXRECV::XboxCommand(uint8_t controller, uint8_t* data, uint16_t nbytes) { @@ -449,7 +449,7 @@ void XBOXRECV::XboxCommand(uint8_t controller, uint8_t* data, uint16_t nbytes) { rcode = pUsb->outTransfer(bAddress, epInfo[ outputPipe ].epAddr, nbytes, data); #ifdef EXTRADEBUG if(rcode) - Notify(PSTR("Error sending Xbox message\r\n")); + Notify(PSTR("Error sending Xbox message\r\n"), 0x80); #endif } void XBOXRECV::setLedRaw(uint8_t controller, uint8_t value) { @@ -457,7 +457,7 @@ void XBOXRECV::setLedRaw(uint8_t controller, uint8_t value) { writeBuf[1] = 0x00; writeBuf[2] = 0x08; writeBuf[3] = value | 0x40; - + XboxCommand(controller, writeBuf, 4); } void XBOXRECV::setLedOn(uint8_t controller, LED led) { @@ -470,12 +470,12 @@ void XBOXRECV::setLedBlink(uint8_t controller, LED led) { void XBOXRECV::setLedMode(uint8_t controller, LEDMode ledMode) { // This function is used to do some speciel LED stuff the controller supports setLedRaw(controller,(uint8_t)ledMode); } -/* PC runs this at interval of approx 2 seconds +/* PC runs this at interval of approx 2 seconds Thanks to BusHound from Perisoft.net for the Windows USB Analysis output Found by timstamp.co.uk */ void XBOXRECV::checkStatus() { - if(!bPollEnable) + if(!bPollEnable) return; // Get controller info writeBuf[0] = 0x08; @@ -504,6 +504,6 @@ void XBOXRECV::setRumbleOn(uint8_t controller, uint8_t lValue, uint8_t rValue) { writeBuf[4] = 0x00; writeBuf[5] = lValue; // big weight writeBuf[6] = rValue; // small weight - + XboxCommand(controller, writeBuf, 7); -} \ No newline at end of file +} diff --git a/XBOXUSB.cpp b/XBOXUSB.cpp index c18d056f..93047227 100644 --- a/XBOXUSB.cpp +++ b/XBOXUSB.cpp @@ -1,15 +1,15 @@ /* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved. - + This software may be distributed and modified under the terms of the GNU General Public License version 2 (GPL2) as published by the Free Software Foundation and appearing in the file GPL2.TXT included in the packaging of this file. Please note that GPL2 Section 2[b] requires that all works based on this software must also be made publicly available under the terms of the GPL2 ("Copyleft"). - + Contact information ------------------- - + Kristian Lauszus, TKJ Electronics Web : http://www.tkjelectronics.com e-mail : kristianl@tkjelectronics.com @@ -27,10 +27,10 @@ bPollEnable(false) { // don't start polling before dongle is connected for(uint8_t i=0; iRegisterDeviceClass(this); //set devConfig[] entry } @@ -42,80 +42,80 @@ uint8_t XBOXUSB::Init(uint8_t parent, uint8_t port, bool lowspeed) { EpInfo *oldep_ptr = NULL; uint16_t PID; uint16_t VID; - + // get memory address of USB device address pool - AddressPool &addrPool = pUsb->GetAddressPool(); + AddressPool &addrPool = pUsb->GetAddressPool(); #ifdef EXTRADEBUG - Notify(PSTR("\r\nXBOXUSB Init")); + Notify(PSTR("\r\nXBOXUSB Init"), 0x80); #endif // check if address has already been assigned to an instance if (bAddress) { #ifdef DEBUG - Notify(PSTR("\r\nAddress in use")); + Notify(PSTR("\r\nAddress in use"), 0x80); #endif return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE; } - + // Get pointer to pseudo device with address 0 assigned p = addrPool.GetUsbDevicePtr(0); - - if (!p) { + + if (!p) { #ifdef DEBUG - Notify(PSTR("\r\nAddress not found")); + Notify(PSTR("\r\nAddress not found"), 0x80); #endif return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; } - + if (!p->epinfo) { #ifdef DEBUG - Notify(PSTR("\r\nepinfo is null")); + Notify(PSTR("\r\nepinfo is null"), 0x80); #endif return USB_ERROR_EPINFO_IS_NULL; } - + // Save old pointer to EP_RECORD of address 0 oldep_ptr = p->epinfo; - + // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence p->epinfo = epInfo; - + p->lowspeed = lowspeed; - + // Get device descriptor rcode = pUsb->getDevDescr(0, 0, sizeof(USB_DEVICE_DESCRIPTOR), (uint8_t*)buf);// Get device descriptor - addr, ep, nbytes, data // Restore p->epinfo p->epinfo = oldep_ptr; - + if(rcode) goto FailGetDevDescr; - + VID = ((USB_DEVICE_DESCRIPTOR*)buf)->idVendor; PID = ((USB_DEVICE_DESCRIPTOR*)buf)->idProduct; - + if(VID != XBOX_VID && VID != MADCATZ_VID && VID != JOYTECH_VID) // We just check if it's a xbox controller using the Vendor ID goto FailUnknownDevice; if(PID == XBOX_WIRELESS_PID) { #ifdef DEBUG - Notify(PSTR("\r\nYou have plugged in a wireless Xbox 360 controller - it doesn't support USB communication")); + Notify(PSTR("\r\nYou have plugged in a wireless Xbox 360 controller - it doesn't support USB communication"), 0x80); #endif goto FailUnknownDevice; } else if(PID == XBOX_WIRELESS_RECEIVER_PID || PID == XBOX_WIRELESS_RECEIVER_THIRD_PARTY_PID) { #ifdef DEBUG - Notify(PSTR("\r\nThis library only supports Xbox 360 controllers via USB")); + Notify(PSTR("\r\nThis library only supports Xbox 360 controllers via USB"), 0x80); #endif goto FailUnknownDevice; - } - + } + // Allocate new address according to device class bAddress = addrPool.AllocAddress(parent, false, port); - + if (!bAddress) return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; - + // Extract Max Packet Size from device descriptor - epInfo[0].maxPktSize = (uint8_t)((USB_DEVICE_DESCRIPTOR*)buf)->bMaxPacketSize0; - + epInfo[0].maxPktSize = (uint8_t)((USB_DEVICE_DESCRIPTOR*)buf)->bMaxPacketSize0; + // Assign new address to the device rcode = pUsb->setAddr( 0, 0, bAddress ); if (rcode) { @@ -123,33 +123,33 @@ uint8_t XBOXUSB::Init(uint8_t parent, uint8_t port, bool lowspeed) { addrPool.FreeAddress(bAddress); bAddress = 0; #ifdef DEBUG - Notify(PSTR("\r\nsetAddr: ")); + Notify(PSTR("\r\nsetAddr: "), 0x80); #endif - PrintHex(rcode); + PrintHex(rcode, 0x80); return rcode; } #ifdef EXTRADEBUG - Notify(PSTR("\r\nAddr: ")); - PrintHex(bAddress); + Notify(PSTR("\r\nAddr: "), 0x80); + PrintHex(bAddress, 0x80); #endif p->lowspeed = false; - + //get pointer to assigned address record p = addrPool.GetUsbDevicePtr(bAddress); - if (!p) + if (!p) return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; - - p->lowspeed = lowspeed; - + + p->lowspeed = lowspeed; + // Assign epInfo to epinfo pointer - only EP0 is known rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); if (rcode) goto FailSetDevTblEntry; - + /* The application will work in reduced host mode, so we can save program and data memory space. After verifying the VID we will use known values for the configuration values for device, interface, endpoints and HID for the XBOX360 Controllers */ - + /* Initialize data structures for endpoints of device */ epInfo[ XBOX_INPUT_PIPE ].epAddr = 0x01; // XBOX 360 report endpoint epInfo[ XBOX_INPUT_PIPE ].epAttribs = EP_INTERRUPT; @@ -163,55 +163,55 @@ uint8_t XBOXUSB::Init(uint8_t parent, uint8_t port, bool lowspeed) { epInfo[ XBOX_OUTPUT_PIPE ].maxPktSize = EP_MAXPKTSIZE; epInfo[ XBOX_OUTPUT_PIPE ].bmSndToggle = bmSNDTOG0; epInfo[ XBOX_OUTPUT_PIPE ].bmRcvToggle = bmRCVTOG0; - + rcode = pUsb->setEpInfoEntry(bAddress, 3, epInfo); if( rcode ) goto FailSetDevTblEntry; - + delay(200);//Give time for address change - + rcode = pUsb->setConf(bAddress, epInfo[ XBOX_CONTROL_PIPE ].epAddr, 1); if( rcode ) - goto FailSetConf; + goto FailSetConf; #ifdef DEBUG - Notify(PSTR("\r\nXbox 360 Controller Connected\r\n")); -#endif + Notify(PSTR("\r\nXbox 360 Controller Connected\r\n"), 0x80); +#endif setLedOn(LED1); Xbox360Connected = true; bPollEnable = true; return 0; // successful configuration - - /* diagnostic messages */ + + /* diagnostic messages */ FailGetDevDescr: #ifdef DEBUG - Notify(PSTR("\r\ngetDevDescr:")); + Notify(PSTR("\r\ngetDevDescr:"), 0x80); #endif - goto Fail; + goto Fail; FailSetDevTblEntry: #ifdef DEBUG - Notify(PSTR("\r\nsetDevTblEn:")); + Notify(PSTR("\r\nsetDevTblEn:"), 0x80); #endif goto Fail; FailSetConf: #ifdef DEBUG - Notify(PSTR("\r\nsetConf:")); + Notify(PSTR("\r\nsetConf:"), 0x80); #endif - goto Fail; + goto Fail; FailUnknownDevice: #ifdef DEBUG - Notify(PSTR("\r\nUnknown Device Connected - VID: ")); - PrintHex(VID); - Notify(PSTR(" PID: ")); - PrintHex(PID); + Notify(PSTR("\r\nUnknown Device Connected - VID: "), 0x80); + PrintHex(VID, 0x80); + Notify(PSTR(" PID: "), 0x80); + PrintHex(PID, 0x80); #endif rcode = USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; goto Fail; Fail: #ifdef DEBUG - Notify(PSTR("\r\nXbox 360 Init Failed, error code: ")); + Notify(PSTR("\r\nXbox 360 Init Failed, error code: "), 0x80); Serial.print(rcode,HEX); -#endif +#endif Release(); return rcode; } @@ -219,12 +219,12 @@ Fail: /* Performs a cleanup after failed Init() attempt */ uint8_t XBOXUSB::Release() { Xbox360Connected = false; - pUsb->GetAddressPool().FreeAddress(bAddress); + pUsb->GetAddressPool().FreeAddress(bAddress); bAddress = 0; bPollEnable = false; return 0; } -uint8_t XBOXUSB::Poll() { +uint8_t XBOXUSB::Poll() { if (!bPollEnable) return 0; uint16_t BUFFER_SIZE = EP_MAXPKTSIZE; @@ -236,7 +236,7 @@ uint8_t XBOXUSB::Poll() { return 0; } -void XBOXUSB::readReport() { +void XBOXUSB::readReport() { if (readBuf == NULL) return; if(readBuf[0] != 0x00 || readBuf[1] != 0x14) { // Check if it's the correct report - the controller also sends different status reports @@ -244,15 +244,15 @@ void XBOXUSB::readReport() { } ButtonState = (uint32_t)(readBuf[5] | ((uint16_t)readBuf[4] << 8) | ((uint32_t)readBuf[3] << 16) | ((uint32_t)readBuf[2] << 24)); - + hatValue[LeftHatX] = (int16_t)(((uint16_t)readBuf[7] << 8) | readBuf[6]); hatValue[LeftHatY] = (int16_t)(((uint16_t)readBuf[9] << 8) | readBuf[8]); hatValue[RightHatX] = (int16_t)(((uint16_t)readBuf[11] << 8) | readBuf[10]); hatValue[RightHatY] = (int16_t)(((uint16_t)readBuf[13] << 8) | readBuf[12]); - - //Notify(PSTR("\r\nButtonState")); - //PrintHex(ButtonState); - + + //Notify(PSTR("\r\nButtonState"), 0x80); + //PrintHex(ButtonState, 0x80); + if(ButtonState != OldButtonState) { ButtonClickState = (ButtonState >> 16) & ((~OldButtonState) >> 16); // Update click state variable, but don't include the two trigger buttons L2 and R2 if(((uint8_t)OldButtonState) == 0 && ((uint8_t)ButtonState) != 0) // The L2 and R2 buttons are special as they are analog buttons @@ -261,18 +261,18 @@ void XBOXUSB::readReport() { L2Clicked = true; OldButtonState = ButtonState; } -} +} void XBOXUSB::printReport() { //Uncomment "#define PRINTREPORT" to print the report send by the Xbox 360 Controller #ifdef PRINTREPORT if (readBuf == NULL) return; for(uint8_t i = 0; i < XBOX_REPORT_BUFFER_SIZE;i++) { - PrintHex(readBuf[i]); + PrintHex(readBuf[i], 0x80); Serial.print(" "); - } + } Serial.println(); -#endif +#endif } uint8_t XBOXUSB::getButtonPress(Button b) { @@ -315,7 +315,7 @@ void XBOXUSB::setLedRaw(uint8_t value) { writeBuf[0] = 0x01; writeBuf[1] = 0x03; writeBuf[2] = value; - + XboxCommand(writeBuf, 3); } void XBOXUSB::setLedOn(LED led) { @@ -337,6 +337,6 @@ void XBOXUSB::setRumbleOn(uint8_t lValue, uint8_t rValue) { writeBuf[5] = 0x00; writeBuf[6] = 0x00; writeBuf[7] = 0x00; - + XboxCommand(writeBuf, 8); -} \ No newline at end of file +} From 904f2ff25a923753cd31776bc1ce40a79aa84f2a Mon Sep 17 00:00:00 2001 From: "Andrew J. Kroll" Date: Thu, 28 Mar 2013 04:46:43 -0400 Subject: [PATCH 3/7] Clean up code formatting to industry standards. --- BTD.h | 621 +++++++------- PS3BT.cpp | 1013 +++++++++++----------- PS3BT.h | 360 ++++---- PS3Enums.h | 269 +++--- PS3USB.cpp | 808 +++++++++--------- PS3USB.h | 366 ++++---- SPP.cpp | 1425 ++++++++++++++++--------------- SPP.h | 550 ++++++------ Usb.cpp | 8 +- Usb.h | 20 +- Wii.cpp | 1851 ++++++++++++++++++++-------------------- Wii.h | 701 ++++++++------- XBOXRECV.cpp | 705 +++++++-------- XBOXRECV.h | 334 ++++---- XBOXUSB.cpp | 442 +++++----- XBOXUSB.h | 279 +++--- address.h | 52 +- adk.cpp | 15 +- adk.h | 6 +- avrpins.h | 10 +- cdcacm.cpp | 12 +- cdcftdi.cpp | 12 +- cdcprolific.cpp | 10 +- confdescparser.h | 36 +- controllerEnums.h | 164 ++-- hexdump.h | 6 +- hid.cpp | 2 +- hidboot.cpp | 12 +- hidboot.h | 60 +- hidescriptorparser.cpp | 222 ++--- hidescriptorparser.h | 2 +- hiduniversal.cpp | 14 +- masstorage.cpp | 28 +- masstorage.h | 12 +- parsetools.cpp | 2 +- parsetools.h | 12 +- printhex.h | 22 +- usb_ch9.h | 12 +- usbhost.h | 56 +- usbhub.cpp | 14 +- usbhub.h | 24 +- xboxEnums.h | 62 +- 42 files changed, 5429 insertions(+), 5202 deletions(-) diff --git a/BTD.h b/BTD.h index 238b8959..c314e6cd 100755 --- a/BTD.h +++ b/BTD.h @@ -1,15 +1,15 @@ /* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved. - + This software may be distributed and modified under the terms of the GNU General Public License version 2 (GPL2) as published by the Free Software Foundation and appearing in the file GPL2.TXT included in the packaging of this file. Please note that GPL2 Section 2[b] requires that all works based on this software must also be made publicly available under the terms of the GPL2 ("Copyleft"). - + Contact information ------------------- - + Kristian Lauszus, TKJ Electronics Web : http://www.tkjelectronics.com e-mail : kristianl@tkjelectronics.com @@ -134,17 +134,17 @@ /** All Bluetooth services should include this class. */ class BluetoothService { public: - /** - * Used to pass acldata to the Bluetooth service. - * @param ACLData Pointer to the incoming acldata. - */ - virtual void ACLData(uint8_t* ACLData); - /** Used to run the different state machines in the Bluetooth service. */ - virtual void Run(); - /** Used to reset the Bluetooth service. */ - virtual void Reset(); - /** Used to disconnect both the L2CAP Channel and the HCI Connection for the Bluetooth service. */ - virtual void disconnect(); + /** + * Used to pass acldata to the Bluetooth service. + * @param ACLData Pointer to the incoming acldata. + */ + virtual void ACLData(uint8_t* ACLData); + /** Used to run the different state machines in the Bluetooth service. */ + virtual void Run(); + /** Used to reset the Bluetooth service. */ + virtual void Reset(); + /** Used to disconnect both the L2CAP Channel and the HCI Connection for the Bluetooth service. */ + virtual void disconnect(); }; /** @@ -153,299 +153,312 @@ public: */ class BTD : public USBDeviceConfig, public UsbConfigXtracter { public: - /** - * Constructor for the BTD class. - * @param p Pointer to USB class instance. - */ - BTD(USB *p); - - /** @name USBDeviceConfig implementation */ - /** - * Initialize the Bluetooth dongle. - * @param parent Hub number. - * @param port Port number on the hub. - * @param lowspeed Speed of the device. - * @return 0 on success. - */ - virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed); - /** - * Release the USB device. - * @return 0 on success. - */ - virtual uint8_t Release(); - /** - * Poll the USB Input endpoins and run the state machines. - * @return 0 on success. - */ - virtual uint8_t Poll(); - /** - * Get the device address. - * @return The device address. - */ - virtual uint8_t GetAddress() { return bAddress; }; - /** - * Used to check if the dongle has been initialized. - * @return True if it's ready. - */ - virtual bool isReady() { return bPollEnable; }; - /**@}*/ - - /** @name UsbConfigXtracter implementation */ - /** - * UsbConfigXtracter implementation, used to extract endpoint information. - * @param conf Configuration value. - * @param iface Interface number. - * @param alt Alternate setting. - * @param proto Interface Protocol. - * @param ep Endpoint Descriptor. - */ - virtual void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep); - /**@}*/ + /** + * Constructor for the BTD class. + * @param p Pointer to USB class instance. + */ + BTD(USB *p); - /** Disconnects both the L2CAP Channel and the HCI Connection for all Bluetooth services. */ - void disconnect() { - for (uint8_t i=0; idisconnect(); - }; - /** - * Register bluetooth dongle members/services. - * @param pService Pointer to BluetoothService class instance. - * @return The serice ID on succes or -1 on fail. - */ - int8_t registerServiceClass(BluetoothService *pService) { - for (uint8_t i=0; idisconnect(); + }; + + /** + * Register bluetooth dongle members/services. + * @param pService Pointer to BluetoothService class instance. + * @return The serice ID on succes or -1 on fail. + */ + int8_t registerServiceClass(BluetoothService *pService) { + for(uint8_t i = 0; i < BTD_NUMSERVICES; i++) { + if(!btService[i]) { + btService[i] = pService; + return i; // Return ID + } + } + return -1; // ErrorregisterServiceClass + }; + + /** @name HCI Commands */ + /** + * Used to send a HCI Command. + * @param data Data to send. + * @param nbytes Number of bytes to send. + */ + void HCI_Command(uint8_t* data, uint16_t nbytes); + /** Reset the Bluetooth dongle. */ + void hci_reset(); + /** Read the Bluetooth address of the dongle. */ + void hci_read_bdaddr(); + /** Read the HCI Version of the Bluetooth dongle. */ + void hci_read_local_version_information(); + /** + * Set the local name of the Bluetooth dongle. + * @param name Desired name. + */ + void hci_set_local_name(const char* name); + /** Enable visibility to other Bluetooth devices. */ + void hci_write_scan_enable(); + /** Disable visibility to other Bluetooth devices. */ + void hci_write_scan_disable(); + /** Read the remote devices name. */ + void hci_remote_name(); + /** Accept the connection with the Bluetooth device. */ + void hci_accept_connection(); + /** + * Disconnect the HCI connection. + * @param handle The HCI Handle for the connection. + */ + void hci_disconnect(uint16_t handle); + /** + * Respond with the pin for the connection. + * The pin is automatically set for the Wii library, + * but can be customized for the SPP library. + */ + void hci_pin_code_request_reply(); + /** Respons when no pin was set. */ + void hci_pin_code_negative_request_reply(); + /** + * Command is used to reply to a Link Key Request event from the BR/EDR Controller + * if the Host does not have a stored Link Key for the connection. + */ + void hci_link_key_request_negative_reply(); + /** Used to try to authenticate with the remote device. */ + void hci_authentication_request(); + /** Start a HCI inquiry. */ + void hci_inquiry(); + /** Cancel a HCI inquiry. */ + void hci_inquiry_cancel(); + /** Connect to a device. */ + void hci_connect(); + /** Used to a set the class of the device. */ + void hci_write_class_of_device(); + /**@}*/ + + /** @name L2CAP Commands */ + /** + * Used to send L2CAP Commands. + * @param handle HCI Handle. + * @param data Data to send. + * @param nbytes Number of bytes to send. + * @param channelLow,channelHigh Low and high byte of channel to send to. + * If argument is omitted then the Standard L2CAP header: Channel ID (0x01) for ACL-U will be used. + */ + void L2CAP_Command(uint16_t handle, uint8_t* data, uint8_t nbytes, uint8_t channelLow = 0x01, uint8_t channelHigh = 0x00); + /** + * L2CAP Connection Request. + * @param handle HCI handle. + * @param rxid Identifier. + * @param scid Source Channel Identifier. + * @param psm Protocol/Service Multiplexer - see: https://www.bluetooth.org/Technical/AssignedNumbers/logical_link.htm. + */ + void l2cap_connection_request(uint16_t handle, uint8_t rxid, uint8_t* scid, uint16_t psm); + /** + * L2CAP Connection Response. + * @param handle HCI handle. + * @param rxid Identifier. + * @param dcid Destination Channel Identifier. + * @param scid Source Channel Identifier. + * @param result Result - First send ::PENDING and then ::SUCCESSFUL. + */ + void l2cap_connection_response(uint16_t handle, uint8_t rxid, uint8_t* dcid, uint8_t* scid, uint8_t result); + /** + * L2CAP Config Request. + * @param handle HCI Handle. + * @param rxid Identifier. + * @param dcid Destination Channel Identifier. + */ + void l2cap_config_request(uint16_t handle, uint8_t rxid, uint8_t* dcid); + /** + * L2CAP Config Response. + * @param handle HCI Handle. + * @param rxid Identifier. + * @param scid Source Channel Identifier. + */ + void l2cap_config_response(uint16_t handle, uint8_t rxid, uint8_t* scid); + /** + * L2CAP Disconnection Request. + * @param handle HCI Handle. + * @param rxid Identifier. + * @param dcid Device Channel Identifier. + * @param scid Source Channel Identifier. + */ + void l2cap_disconnection_request(uint16_t handle, uint8_t rxid, uint8_t* dcid, uint8_t* scid); + /** + * L2CAP Disconnection Response. + * @param handle HCI Handle. + * @param rxid Identifier. + * @param dcid Device Channel Identifier. + * @param scid Source Channel Identifier. + */ + void l2cap_disconnection_response(uint16_t handle, uint8_t rxid, uint8_t* dcid, uint8_t* scid); + /** + * L2CAP Information Response. + * @param handle HCI Handle. + * @param rxid Identifier. + * @param infoTypeLow,infoTypeHigh Infotype. + */ + void l2cap_information_response(uint16_t handle, uint8_t rxid, uint8_t infoTypeLow, uint8_t infoTypeHigh); + /**@}*/ + + /** Use this to see if it is waiting for a incoming connection. */ + bool watingForConnection; + /** This is used by the service to know when to store the device information. */ + bool l2capConnectionClaimed; + /** This is used by the SPP library to claim the current SDP incoming request. */ + bool sdpConnectionClaimed; + /** This is used by the SPP library to claim the current RFCOMM incoming request. */ + bool rfcommConnectionClaimed; + + /** The name you wish to make the dongle show up as. It is set automatically by the SPP library. */ + const char* btdName; + /** The pin you wish to make the dongle use for authentication. It is set automatically by the SPP library. */ + const char* btdPin; + + /** The bluetooth dongles Bluetooth address. */ + uint8_t my_bdaddr[6]; + /** HCI handle for the last connection. */ + uint16_t hci_handle; + /** Last incoming devices Bluetooth address. */ + uint8_t disc_bdaddr[6]; + /** First 30 chars of last remote name. */ + uint8_t remote_name[30]; + /** + * The supported HCI Version read from the Bluetooth dongle. + * Used by the PS3BT library to check the HCI Version of the Bluetooth dongle, + * it should be at least 3 to work properly with the library. + */ + uint8_t hci_version; + + /** Call this function to pair with a Wiimote */ + void pairWithWiimote() { + pairWithWii = true; + hci_state = HCI_CHECK_WII_SERVICE; + }; + /** Used to only send the ACL data to the wiimote. */ + bool connectToWii; + /** True if a Wiimote is connecting. */ + bool incomingWii; + /** True when it should pair with the incoming Wiimote. */ + bool pairWithWii; + /** True if it's the new Wiimote with the Motion Plus Inside or a Wii U Pro Controller. */ + bool motionPlusInside; + /** True if it's a Wii U Pro Controller. */ + bool wiiUProController; + + /** + * Read the poll interval taken from the endpoint descriptors. + * @return The poll interval in ms. + */ + uint8_t readPollInterval() { + return pollInterval; + }; - /** - * Read the poll interval taken from the endpoint descriptors. - * @return The poll interval in ms. - */ - uint8_t readPollInterval() { return pollInterval; }; - protected: - /** Pointer to USB class instance. */ - USB *pUsb; - /** Device address. */ - uint8_t bAddress; - /** Endpoint info structure. */ - EpInfo epInfo[BTD_MAX_ENDPOINTS]; - - /** Configuration number. */ - uint8_t bConfNum; - /** Total number of endpoints in the configuration. */ - uint8_t bNumEP; - /** Next poll time based on poll interval taken from the USB descriptor. */ - uint32_t qNextPollTime; - - /** Bluetooth dongle control endpoint. */ - static const uint8_t BTD_CONTROL_PIPE; - /** HCI event endpoint index. */ - static const uint8_t BTD_EVENT_PIPE; - /** ACL In endpoint index. */ - static const uint8_t BTD_DATAIN_PIPE; - /** ACL Out endpoint index. */ - static const uint8_t BTD_DATAOUT_PIPE; - - /** - * Used to print the USB Endpoint Descriptor. - * @param ep_ptr Pointer to USB Endpoint Descriptor. - */ - void PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr); - + /** Pointer to USB class instance. */ + USB *pUsb; + /** Device address. */ + uint8_t bAddress; + /** Endpoint info structure. */ + EpInfo epInfo[BTD_MAX_ENDPOINTS]; + + /** Configuration number. */ + uint8_t bConfNum; + /** Total number of endpoints in the configuration. */ + uint8_t bNumEP; + /** Next poll time based on poll interval taken from the USB descriptor. */ + uint32_t qNextPollTime; + + /** Bluetooth dongle control endpoint. */ + static const uint8_t BTD_CONTROL_PIPE; + /** HCI event endpoint index. */ + static const uint8_t BTD_EVENT_PIPE; + /** ACL In endpoint index. */ + static const uint8_t BTD_DATAIN_PIPE; + /** ACL Out endpoint index. */ + static const uint8_t BTD_DATAOUT_PIPE; + + /** + * Used to print the USB Endpoint Descriptor. + * @param ep_ptr Pointer to USB Endpoint Descriptor. + */ + void PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr); + private: - BluetoothService* btService[BTD_NUMSERVICES]; - - bool bPollEnable; - uint8_t pollInterval; - - /* Variables used by high level HCI task */ - uint8_t hci_state; //current state of bluetooth hci connection - uint16_t hci_counter; // counter used for bluetooth hci reset loops - uint8_t hci_num_reset_loops; // this value indicate how many times it should read before trying to reset - uint16_t hci_event_flag; // hci flags of received bluetooth events - uint8_t inquiry_counter; - - uint8_t hcibuf[BULK_MAXPKTSIZE];//General purpose buffer for hci data - uint8_t l2capinbuf[BULK_MAXPKTSIZE];//General purpose buffer for l2cap in data - uint8_t l2capoutbuf[BULK_MAXPKTSIZE];//General purpose buffer for l2cap out data - - /* State machines */ - void HCI_event_task(); // Poll the HCI event pipe - void HCI_task(); // HCI state machine - void ACL_event_task(); // ACL input pipe - - /* Used to set the Bluetooth Address internally to the PS3 Controllers */ - void setBdaddr(uint8_t* BDADDR); - void setMoveBdaddr(uint8_t* BDADDR); + BluetoothService* btService[BTD_NUMSERVICES]; + + bool bPollEnable; + uint8_t pollInterval; + + /* Variables used by high level HCI task */ + uint8_t hci_state; //current state of bluetooth hci connection + uint16_t hci_counter; // counter used for bluetooth hci reset loops + uint8_t hci_num_reset_loops; // this value indicate how many times it should read before trying to reset + uint16_t hci_event_flag; // hci flags of received bluetooth events + uint8_t inquiry_counter; + + uint8_t hcibuf[BULK_MAXPKTSIZE]; //General purpose buffer for hci data + uint8_t l2capinbuf[BULK_MAXPKTSIZE]; //General purpose buffer for l2cap in data + uint8_t l2capoutbuf[BULK_MAXPKTSIZE]; //General purpose buffer for l2cap out data + + /* State machines */ + void HCI_event_task(); // Poll the HCI event pipe + void HCI_task(); // HCI state machine + void ACL_event_task(); // ACL input pipe + + /* Used to set the Bluetooth Address internally to the PS3 Controllers */ + void setBdaddr(uint8_t* BDADDR); + void setMoveBdaddr(uint8_t* BDADDR); }; #endif diff --git a/PS3BT.cpp b/PS3BT.cpp index 87214ab3..1912808c 100644 --- a/PS3BT.cpp +++ b/PS3BT.cpp @@ -21,540 +21,542 @@ //#define PRINTREPORT // Uncomment to print the report send by the PS3 Controllers const uint8_t OUTPUT_REPORT_BUFFER[] PROGMEM = { - 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, - 0xff, 0x27, 0x10, 0x00, 0x32, - 0xff, 0x27, 0x10, 0x00, 0x32, - 0xff, 0x27, 0x10, 0x00, 0x32, - 0xff, 0x27, 0x10, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0x27, 0x10, 0x00, 0x32, + 0xff, 0x27, 0x10, 0x00, 0x32, + 0xff, 0x27, 0x10, 0x00, 0x32, + 0xff, 0x27, 0x10, 0x00, 0x32, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; -PS3BT::PS3BT(BTD *p, uint8_t btadr5, uint8_t btadr4, uint8_t btadr3, uint8_t btadr2, uint8_t btadr1, uint8_t btadr0): +PS3BT::PS3BT(BTD *p, uint8_t btadr5, uint8_t btadr4, uint8_t btadr3, uint8_t btadr2, uint8_t btadr1, uint8_t btadr0) : pBtd(p) // pointer to USB class instance - mandatory { - if (pBtd) - pBtd->registerServiceClass(this); // Register it as a Bluetooth service + if (pBtd) + pBtd->registerServiceClass(this); // Register it as a Bluetooth service - pBtd->my_bdaddr[5] = btadr5; // Change to your dongle's Bluetooth address instead - pBtd->my_bdaddr[4] = btadr4; - pBtd->my_bdaddr[3] = btadr3; - pBtd->my_bdaddr[2] = btadr2; - pBtd->my_bdaddr[1] = btadr1; - pBtd->my_bdaddr[0] = btadr0; + pBtd->my_bdaddr[5] = btadr5; // Change to your dongle's Bluetooth address instead + pBtd->my_bdaddr[4] = btadr4; + pBtd->my_bdaddr[3] = btadr3; + pBtd->my_bdaddr[2] = btadr2; + pBtd->my_bdaddr[1] = btadr1; + pBtd->my_bdaddr[0] = btadr0; - HIDBuffer[0] = 0x52;// HID BT Set_report (0x50) | Report Type (Output 0x02) - HIDBuffer[1] = 0x01;// Report ID + HIDBuffer[0] = 0x52; // HID BT Set_report (0x50) | Report Type (Output 0x02) + HIDBuffer[1] = 0x01; // Report ID - //Needed for PS3 Move Controller commands to work via bluetooth - HIDMoveBuffer[0] = 0xA2;// HID BT DATA_request (0xA0) | Report Type (Output 0x02) - HIDMoveBuffer[1] = 0x02;// Report ID + //Needed for PS3 Move Controller commands to work via bluetooth + HIDMoveBuffer[0] = 0xA2; // HID BT DATA_request (0xA0) | Report Type (Output 0x02) + HIDMoveBuffer[1] = 0x02; // Report ID - /* Set device cid for the control and intterrupt channelse - LSB */ - control_dcid[0] = 0x40;//0x0040 - control_dcid[1] = 0x00; - interrupt_dcid[0] = 0x41;//0x0041 - interrupt_dcid[1] = 0x00; + /* Set device cid for the control and intterrupt channelse - LSB */ + control_dcid[0] = 0x40; //0x0040 + control_dcid[1] = 0x00; + interrupt_dcid[0] = 0x41; //0x0041 + interrupt_dcid[1] = 0x00; - Reset(); + Reset(); } + bool PS3BT::getButtonPress(Button b) { - return (ButtonState & pgm_read_dword(&BUTTONS[(uint8_t)b])); + return (ButtonState & pgm_read_dword(&BUTTONS[(uint8_t)b])); } + bool PS3BT::getButtonClick(Button b) { - uint32_t button = pgm_read_dword(&BUTTONS[(uint8_t)b]); - bool click = (ButtonClickState & button); - ButtonClickState &= ~button; // clear "click" event - return click; + uint32_t button = pgm_read_dword(&BUTTONS[(uint8_t)b]); + bool click = (ButtonClickState & button); + ButtonClickState &= ~button; // clear "click" event + return click; } + uint8_t PS3BT::getAnalogButton(Button a) { - if (l2capinbuf == NULL) - return 0; - return (uint8_t)(l2capinbuf[pgm_read_byte(&ANALOGBUTTONS[(uint8_t)a])]); + if (l2capinbuf == NULL) + return 0; + return (uint8_t)(l2capinbuf[pgm_read_byte(&ANALOGBUTTONS[(uint8_t)a])]); } + uint8_t PS3BT::getAnalogHat(AnalogHat a) { - if (l2capinbuf == NULL) - return 0; - return (uint8_t)(l2capinbuf[(uint8_t)a+15]); + if (l2capinbuf == NULL) + return 0; + return (uint8_t)(l2capinbuf[(uint8_t)a + 15]); } + int16_t PS3BT::getSensor(Sensor a) { - if (l2capinbuf == NULL) - return 0; - if(PS3Connected) { - if (a == aX || a == aY || a == aZ || a == gZ) - return ((l2capinbuf[(uint16_t)a] << 8) | l2capinbuf[(uint16_t)a + 1]); - else - return 0; - } else if(PS3MoveConnected) { - if (a == mXmove || a == mYmove) // These are all 12-bits long - return (((l2capinbuf[(uint16_t)a] & 0x0F) << 8) | (l2capinbuf[(uint16_t)a + 1])); - else if (a == mZmove || a == tempMove) // The tempearature is also 12 bits long - return ((l2capinbuf[(uint16_t)a] << 4) | ((l2capinbuf[(uint16_t)a + 1] & 0xF0) >> 4)); - else // aXmove, aYmove, aZmove, gXmove, gYmove and gZmove - return (l2capinbuf[(uint16_t)a] | (l2capinbuf[(uint16_t)a + 1] << 8)); - } else - return 0; + if (l2capinbuf == NULL) + return 0; + if (PS3Connected) { + if (a == aX || a == aY || a == aZ || a == gZ) + return ((l2capinbuf[(uint16_t)a] << 8) | l2capinbuf[(uint16_t)a + 1]); + else + return 0; + } else if (PS3MoveConnected) { + if (a == mXmove || a == mYmove) // These are all 12-bits long + return (((l2capinbuf[(uint16_t)a] & 0x0F) << 8) | (l2capinbuf[(uint16_t)a + 1])); + else if (a == mZmove || a == tempMove) // The tempearature is also 12 bits long + return ((l2capinbuf[(uint16_t)a] << 4) | ((l2capinbuf[(uint16_t)a + 1] & 0xF0) >> 4)); + else // aXmove, aYmove, aZmove, gXmove, gYmove and gZmove + return (l2capinbuf[(uint16_t)a] | (l2capinbuf[(uint16_t)a + 1] << 8)); + } else + return 0; } + double PS3BT::getAngle(Angle a) { - double accXval; - double accYval; - double accZval; + double accXval; + double accYval; + double accZval; - if(PS3Connected) { - // Data for the Kionix KXPC4 used in the DualShock 3 - const double zeroG = 511.5; // 1.65/3.3*1023 (1,65V) - accXval = -((double)getSensor(aX)-zeroG); - accYval = -((double)getSensor(aY)-zeroG); - accZval = -((double)getSensor(aZ)-zeroG); - } else if(PS3MoveConnected) { - // It's a Kionix KXSC4 inside the Motion controller - const uint16_t zeroG = 0x8000; - accXval = -(int16_t)(getSensor(aXmove)-zeroG); - accYval = (int16_t)(getSensor(aYmove)-zeroG); - accZval = (int16_t)(getSensor(aZmove)-zeroG); - } + if (PS3Connected) { + // Data for the Kionix KXPC4 used in the DualShock 3 + const double zeroG = 511.5; // 1.65/3.3*1023 (1,65V) + accXval = -((double)getSensor(aX) - zeroG); + accYval = -((double)getSensor(aY) - zeroG); + accZval = -((double)getSensor(aZ) - zeroG); + } else if (PS3MoveConnected) { + // It's a Kionix KXSC4 inside the Motion controller + const uint16_t zeroG = 0x8000; + accXval = -(int16_t)(getSensor(aXmove) - zeroG); + accYval = (int16_t)(getSensor(aYmove) - zeroG); + accZval = (int16_t)(getSensor(aZmove) - zeroG); + } - // Convert to 360 degrees resolution - // atan2 outputs the value of -π to π (radians) - // We are then converting it to 0 to 2π and then to degrees - if (a == Pitch) { - double angle = (atan2(accYval,accZval)+PI)*RAD_TO_DEG; - return angle; - } else { - double angle = (atan2(accXval,accZval)+PI)*RAD_TO_DEG; - return angle; - } + // Convert to 360 degrees resolution + // atan2 outputs the value of -π to π (radians) + // We are then converting it to 0 to 2π and then to degrees + if (a == Pitch) { + double angle = (atan2(accYval, accZval) + PI) * RAD_TO_DEG; + return angle; + } else { + double angle = (atan2(accXval, accZval) + PI) * RAD_TO_DEG; + return angle; + } } + double PS3BT::get9DOFValues(Sensor a) { // Thanks to Manfred Piendl - if(!PS3MoveConnected) - return 0; - int16_t value = getSensor(a); - if (a == mXmove || a == mYmove || a == mZmove) { - if (value > 2047) - value -= 0x1000; - return (double)value/3.2; // unit: muT = 10^(-6) Tesla - } else if (a == aXmove || a == aYmove || a == aZmove) { - if (value < 0) - value += 0x8000; - else - value -= 0x8000; - return (double)value/442.0; // unit: m/(s^2) - } else if (a == gXmove || a == gYmove || a == gZmove) { - if (value < 0) - value += 0x8000; - else - value -= 0x8000; - if (a == gXmove) - return (double)value/11.6; // unit: deg/s - else if (a == gYmove) - return (double)value/11.2; // unit: deg/s - else // gZmove - return (double)value/9.6; // unit: deg/s - } else - return 0; + if (!PS3MoveConnected) + return 0; + int16_t value = getSensor(a); + if (a == mXmove || a == mYmove || a == mZmove) { + if (value > 2047) + value -= 0x1000; + return (double)value / 3.2; // unit: muT = 10^(-6) Tesla + } else if (a == aXmove || a == aYmove || a == aZmove) { + if (value < 0) + value += 0x8000; + else + value -= 0x8000; + return (double)value / 442.0; // unit: m/(s^2) + } else if (a == gXmove || a == gYmove || a == gZmove) { + if (value < 0) + value += 0x8000; + else + value -= 0x8000; + if (a == gXmove) + return (double)value / 11.6; // unit: deg/s + else if (a == gYmove) + return (double)value / 11.2; // unit: deg/s + else // gZmove + return (double)value / 9.6; // unit: deg/s + } else + return 0; } + String PS3BT::getTemperature() { - if(PS3MoveConnected) { - int16_t input = getSensor(tempMove); + if (PS3MoveConnected) { + int16_t input = getSensor(tempMove); - String output = String(input/100); - output += "."; - if(input%100 < 10) - output += "0"; - output += String(input%100); + String output = String(input / 100); + output += "."; + if (input % 100 < 10) + output += "0"; + output += String(input % 100); - return output; - } + return output; + } } + bool PS3BT::getStatus(Status c) { - if (l2capinbuf == NULL) + if (l2capinbuf == NULL) + return false; + if (l2capinbuf[(uint16_t)c >> 8] == ((uint8_t)c & 0xff)) + return true; return false; - if (l2capinbuf[(uint16_t)c >> 8] == ((uint8_t)c & 0xff)) - return true; - return false; } + String PS3BT::getStatusString() { - if (PS3Connected || PS3NavigationConnected) { - char statusOutput[100]; + if (PS3Connected || PS3NavigationConnected) { + char statusOutput[100]; - strcpy(statusOutput,"ConnectionStatus: "); + strcpy(statusOutput, "ConnectionStatus: "); - if (getStatus(Plugged)) strcat(statusOutput,"Plugged"); - else if (getStatus(Unplugged)) strcat(statusOutput,"Unplugged"); - else strcat(statusOutput,"Error"); + if (getStatus(Plugged)) strcat(statusOutput, "Plugged"); + else if (getStatus(Unplugged)) strcat(statusOutput, "Unplugged"); + else strcat(statusOutput, "Error"); - strcat(statusOutput," - PowerRating: "); - if (getStatus(Charging)) strcat(statusOutput,"Charging"); - else if (getStatus(NotCharging)) strcat(statusOutput,"Not Charging"); - else if (getStatus(Shutdown)) strcat(statusOutput,"Shutdown"); - else if (getStatus(Dying)) strcat(statusOutput,"Dying"); - else if (getStatus(Low)) strcat(statusOutput,"Low"); - else if (getStatus(High)) strcat(statusOutput,"High"); - else if (getStatus(Full)) strcat(statusOutput,"Full"); - else strcat(statusOutput,"Error"); + strcat(statusOutput, " - PowerRating: "); + if (getStatus(Charging)) strcat(statusOutput, "Charging"); + else if (getStatus(NotCharging)) strcat(statusOutput, "Not Charging"); + else if (getStatus(Shutdown)) strcat(statusOutput, "Shutdown"); + else if (getStatus(Dying)) strcat(statusOutput, "Dying"); + else if (getStatus(Low)) strcat(statusOutput, "Low"); + else if (getStatus(High)) strcat(statusOutput, "High"); + else if (getStatus(Full)) strcat(statusOutput, "Full"); + else strcat(statusOutput, "Error"); - strcat(statusOutput," - WirelessStatus: "); + strcat(statusOutput, " - WirelessStatus: "); - if (getStatus(CableRumble)) strcat(statusOutput,"Cable - Rumble is on"); - else if (getStatus(Cable)) strcat(statusOutput,"Cable - Rumble is off"); - else if (getStatus(BluetoothRumble)) strcat(statusOutput,"Bluetooth - Rumble is on"); - else if (getStatus(Bluetooth)) strcat(statusOutput,"Bluetooth - Rumble is off"); - else strcat(statusOutput,"Error"); + if (getStatus(CableRumble)) strcat(statusOutput, "Cable - Rumble is on"); + else if (getStatus(Cable)) strcat(statusOutput, "Cable - Rumble is off"); + else if (getStatus(BluetoothRumble)) strcat(statusOutput, "Bluetooth - Rumble is on"); + else if (getStatus(Bluetooth)) strcat(statusOutput, "Bluetooth - Rumble is off"); + else strcat(statusOutput, "Error"); - return statusOutput; + return statusOutput; - } - else if(PS3MoveConnected) { - char statusOutput[50]; + } else if (PS3MoveConnected) { + char statusOutput[50]; - strcpy(statusOutput,"PowerRating: "); + strcpy(statusOutput, "PowerRating: "); - if (getStatus(MoveCharging)) strcat(statusOutput,"Charging"); - else if (getStatus(MoveNotCharging)) strcat(statusOutput,"Not Charging"); - else if (getStatus(MoveShutdown)) strcat(statusOutput,"Shutdown"); - else if (getStatus(MoveDying)) strcat(statusOutput,"Dying"); - else if (getStatus(MoveLow)) strcat(statusOutput,"Low"); - else if (getStatus(MoveHigh)) strcat(statusOutput,"High"); - else if (getStatus(MoveFull)) strcat(statusOutput,"Full"); - else strcat(statusOutput,"Error"); + if (getStatus(MoveCharging)) strcat(statusOutput, "Charging"); + else if (getStatus(MoveNotCharging)) strcat(statusOutput, "Not Charging"); + else if (getStatus(MoveShutdown)) strcat(statusOutput, "Shutdown"); + else if (getStatus(MoveDying)) strcat(statusOutput, "Dying"); + else if (getStatus(MoveLow)) strcat(statusOutput, "Low"); + else if (getStatus(MoveHigh)) strcat(statusOutput, "High"); + else if (getStatus(MoveFull)) strcat(statusOutput, "Full"); + else strcat(statusOutput, "Error"); - return statusOutput; - } + return statusOutput; + } } -void PS3BT::Reset() { - PS3Connected = false; - PS3MoveConnected = false; - PS3NavigationConnected = false; - activeConnection = false; - l2cap_event_flag = 0; // Reset flags - l2cap_state = L2CAP_WAIT; - // Needed for PS3 Dualshock Controller commands to work via bluetooth - for (uint8_t i = 0; i < OUTPUT_REPORT_BUFFER_SIZE; i++) - HIDBuffer[i + 2] = pgm_read_byte(&OUTPUT_REPORT_BUFFER[i]); // First two bytes reserved for report type and ID +void PS3BT::Reset() { + PS3Connected = false; + PS3MoveConnected = false; + PS3NavigationConnected = false; + activeConnection = false; + l2cap_event_flag = 0; // Reset flags + l2cap_state = L2CAP_WAIT; + + // Needed for PS3 Dualshock Controller commands to work via bluetooth + for (uint8_t i = 0; i < OUTPUT_REPORT_BUFFER_SIZE; i++) + HIDBuffer[i + 2] = pgm_read_byte(&OUTPUT_REPORT_BUFFER[i]); // First two bytes reserved for report type and ID } void PS3BT::disconnect() { // Use this void to disconnect any of the controllers - //First the HID interrupt channel has to be disconencted, then the HID control channel and finally the HCI connection - pBtd->l2cap_disconnection_request(hci_handle,0x0A, interrupt_scid, interrupt_dcid); - Reset(); - l2cap_state = L2CAP_INTERRUPT_DISCONNECT; + //First the HID interrupt channel has to be disconencted, then the HID control channel and finally the HCI connection + pBtd->l2cap_disconnection_request(hci_handle, 0x0A, interrupt_scid, interrupt_dcid); + Reset(); + l2cap_state = L2CAP_INTERRUPT_DISCONNECT; } void PS3BT::ACLData(uint8_t* ACLData) { - if(!pBtd->l2capConnectionClaimed && !PS3Connected && !PS3MoveConnected && !PS3NavigationConnected && !activeConnection && !pBtd->connectToWii && !pBtd->incomingWii && !pBtd->pairWithWii) { - if (ACLData[8] == L2CAP_CMD_CONNECTION_REQUEST) { - if((ACLData[12] | (ACLData[13] << 8)) == HID_CTRL_PSM) { - pBtd->l2capConnectionClaimed = true; // Claim that the incoming connection belongs to this service - activeConnection = true; - hci_handle = pBtd->hci_handle; // Store the HCI Handle for the connection - l2cap_state = L2CAP_WAIT; - for(uint8_t i = 0; i < 30; i++) - remote_name[i] = pBtd->remote_name[i]; // Store the remote name for the connection + if (!pBtd->l2capConnectionClaimed && !PS3Connected && !PS3MoveConnected && !PS3NavigationConnected && !activeConnection && !pBtd->connectToWii && !pBtd->incomingWii && !pBtd->pairWithWii) { + if (ACLData[8] == L2CAP_CMD_CONNECTION_REQUEST) { + if ((ACLData[12] | (ACLData[13] << 8)) == HID_CTRL_PSM) { + pBtd->l2capConnectionClaimed = true; // Claim that the incoming connection belongs to this service + activeConnection = true; + hci_handle = pBtd->hci_handle; // Store the HCI Handle for the connection + l2cap_state = L2CAP_WAIT; + for (uint8_t i = 0; i < 30; i++) + remote_name[i] = pBtd->remote_name[i]; // Store the remote name for the connection #ifdef DEBUG - if(pBtd->hci_version < 3) { // Check the HCI Version of the Bluetooth dongle - Notify(PSTR("\r\nYour dongle may not support reading the analog buttons, sensors and status\r\nYour HCI Version is: "), 0x80); - Serial.print(pBtd->hci_version); - Notify(PSTR("\r\nBut should be at least 3\r\nThis means that it doesn't support Bluetooth Version 2.0+EDR"), 0x80); - } + if (pBtd->hci_version < 3) { // Check the HCI Version of the Bluetooth dongle + Notify(PSTR("\r\nYour dongle may not support reading the analog buttons, sensors and status\r\nYour HCI Version is: "), 0x80); + Serial.print(pBtd->hci_version); + Notify(PSTR("\r\nBut should be at least 3\r\nThis means that it doesn't support Bluetooth Version 2.0+EDR"), 0x80); + } #endif - } + } + } } - } - if (((ACLData[0] | (ACLData[1] << 8)) == (hci_handle | 0x2000))) { //acl_handle_ok - for(uint8_t i = 0; i < BULK_MAXPKTSIZE; i++) - l2capinbuf[i] = ACLData[i]; - if ((l2capinbuf[6] | (l2capinbuf[7] << 8)) == 0x0001) { //l2cap_control - Channel ID for ACL-U - if (l2capinbuf[8] == L2CAP_CMD_COMMAND_REJECT) { + if (((ACLData[0] | (ACLData[1] << 8)) == (hci_handle | 0x2000))) { //acl_handle_ok + for (uint8_t i = 0; i < BULK_MAXPKTSIZE; i++) + l2capinbuf[i] = ACLData[i]; + if ((l2capinbuf[6] | (l2capinbuf[7] << 8)) == 0x0001) { //l2cap_control - Channel ID for ACL-U + if (l2capinbuf[8] == L2CAP_CMD_COMMAND_REJECT) { #ifdef DEBUG - Notify(PSTR("\r\nL2CAP Command Rejected - Reason: "), 0x80); - PrintHex(l2capinbuf[13], 0x80); - Serial.print(" "); - PrintHex(l2capinbuf[12], 0x80); - Serial.print(" Data: "); - PrintHex(l2capinbuf[17], 0x80); - Serial.print(" "); - PrintHex(l2capinbuf[16], 0x80); - Serial.print(" "); - PrintHex(l2capinbuf[15], 0x80); - Serial.print(" "); - PrintHex(l2capinbuf[14], 0x80); + Notify(PSTR("\r\nL2CAP Command Rejected - Reason: "), 0x80); + PrintHex (l2capinbuf[13], 0x80); + Serial.print(" "); + PrintHex (l2capinbuf[12], 0x80); + Serial.print(" Data: "); + PrintHex (l2capinbuf[17], 0x80); + Serial.print(" "); + PrintHex (l2capinbuf[16], 0x80); + Serial.print(" "); + PrintHex (l2capinbuf[15], 0x80); + Serial.print(" "); + PrintHex (l2capinbuf[14], 0x80); #endif - } - else if (l2capinbuf[8] == L2CAP_CMD_CONNECTION_REQUEST) { + } else if (l2capinbuf[8] == L2CAP_CMD_CONNECTION_REQUEST) { #ifdef EXTRADEBUG - Notify(PSTR("\r\nL2CAP Connection Request - PSM: "), 0x80); - PrintHex(l2capinbuf[13], 0x80); - Notify(PSTR(" "), 0x80); - PrintHex(l2capinbuf[12], 0x80); - Notify(PSTR(" SCID: "), 0x80); - PrintHex(l2capinbuf[15], 0x80); - Notify(PSTR(" "), 0x80); - PrintHex(l2capinbuf[14], 0x80); - Notify(PSTR(" Identifier: "), 0x80); - PrintHex(l2capinbuf[9], 0x80); + Notify(PSTR("\r\nL2CAP Connection Request - PSM: "), 0x80); + PrintHex (l2capinbuf[13], 0x80); + Notify(PSTR(" "), 0x80); + PrintHex (l2capinbuf[12], 0x80); + Notify(PSTR(" SCID: "), 0x80); + PrintHex (l2capinbuf[15], 0x80); + Notify(PSTR(" "), 0x80); + PrintHex (l2capinbuf[14], 0x80); + Notify(PSTR(" Identifier: "), 0x80); + PrintHex (l2capinbuf[9], 0x80); #endif - if ((l2capinbuf[12] | (l2capinbuf[13] << 8)) == HID_CTRL_PSM) { - identifier = l2capinbuf[9]; - control_scid[0] = l2capinbuf[14]; - control_scid[1] = l2capinbuf[15]; - l2cap_event_flag |= L2CAP_FLAG_CONNECTION_CONTROL_REQUEST; - } - else if ((l2capinbuf[12] | (l2capinbuf[13] << 8)) == HID_INTR_PSM) { - identifier = l2capinbuf[9]; - interrupt_scid[0] = l2capinbuf[14]; - interrupt_scid[1] = l2capinbuf[15]; - l2cap_event_flag |= L2CAP_FLAG_CONNECTION_INTERRUPT_REQUEST; - } - } - else if (l2capinbuf[8] == L2CAP_CMD_CONFIG_RESPONSE) { - if ((l2capinbuf[16] | (l2capinbuf[17] << 8)) == 0x0000) { // Success - if (l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) { - //Serial.print("\r\nHID Control Configuration Complete"); - l2cap_event_flag |= L2CAP_FLAG_CONFIG_CONTROL_SUCCESS; - } - else if (l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) { - //Serial.print("\r\nHID Interrupt Configuration Complete"); - l2cap_event_flag |= L2CAP_FLAG_CONFIG_INTERRUPT_SUCCESS; - } - } - } - else if (l2capinbuf[8] == L2CAP_CMD_CONFIG_REQUEST) { - if (l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) { - //Serial.print("\r\nHID Control Configuration Request"); - identifier = l2capinbuf[9]; - l2cap_event_flag |= L2CAP_FLAG_CONFIG_CONTROL_REQUEST; - } - else if (l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) { - //Serial.print("\r\nHID Interrupt Configuration Request"); - identifier = l2capinbuf[9]; - l2cap_event_flag |= L2CAP_FLAG_CONFIG_INTERRUPT_REQUEST; - } - } - else if (l2capinbuf[8] == L2CAP_CMD_DISCONNECT_REQUEST) { - if (l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) { + if ((l2capinbuf[12] | (l2capinbuf[13] << 8)) == HID_CTRL_PSM) { + identifier = l2capinbuf[9]; + control_scid[0] = l2capinbuf[14]; + control_scid[1] = l2capinbuf[15]; + l2cap_event_flag |= L2CAP_FLAG_CONNECTION_CONTROL_REQUEST; + } else if ((l2capinbuf[12] | (l2capinbuf[13] << 8)) == HID_INTR_PSM) { + identifier = l2capinbuf[9]; + interrupt_scid[0] = l2capinbuf[14]; + interrupt_scid[1] = l2capinbuf[15]; + l2cap_event_flag |= L2CAP_FLAG_CONNECTION_INTERRUPT_REQUEST; + } + } else if (l2capinbuf[8] == L2CAP_CMD_CONFIG_RESPONSE) { + if ((l2capinbuf[16] | (l2capinbuf[17] << 8)) == 0x0000) { // Success + if (l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) { + //Serial.print("\r\nHID Control Configuration Complete"); + l2cap_event_flag |= L2CAP_FLAG_CONFIG_CONTROL_SUCCESS; + } else if (l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) { + //Serial.print("\r\nHID Interrupt Configuration Complete"); + l2cap_event_flag |= L2CAP_FLAG_CONFIG_INTERRUPT_SUCCESS; + } + } + } else if (l2capinbuf[8] == L2CAP_CMD_CONFIG_REQUEST) { + if (l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) { + //Serial.print("\r\nHID Control Configuration Request"); + identifier = l2capinbuf[9]; + l2cap_event_flag |= L2CAP_FLAG_CONFIG_CONTROL_REQUEST; + } else if (l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) { + //Serial.print("\r\nHID Interrupt Configuration Request"); + identifier = l2capinbuf[9]; + l2cap_event_flag |= L2CAP_FLAG_CONFIG_INTERRUPT_REQUEST; + } + } else if (l2capinbuf[8] == L2CAP_CMD_DISCONNECT_REQUEST) { + if (l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) { #ifdef DEBUG - Notify(PSTR("\r\nDisconnect Request: Control Channel"), 0x80); + Notify(PSTR("\r\nDisconnect Request: Control Channel"), 0x80); #endif - identifier = l2capinbuf[9]; - pBtd->l2cap_disconnection_response(hci_handle,identifier,control_dcid,control_scid); - Reset(); - } - else if (l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) { + identifier = l2capinbuf[9]; + pBtd->l2cap_disconnection_response(hci_handle, identifier, control_dcid, control_scid); + Reset(); + } else if (l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) { #ifdef DEBUG - Notify(PSTR("\r\nDisconnect Request: Interrupt Channel"), 0x80); + Notify(PSTR("\r\nDisconnect Request: Interrupt Channel"), 0x80); #endif - identifier = l2capinbuf[9]; - pBtd->l2cap_disconnection_response(hci_handle,identifier,interrupt_dcid,interrupt_scid); - Reset(); - } - } - else if (l2capinbuf[8] == L2CAP_CMD_DISCONNECT_RESPONSE) { - if (l2capinbuf[12] == control_scid[0] && l2capinbuf[13] == control_scid[1]) { - //Serial.print("\r\nDisconnect Response: Control Channel"); - identifier = l2capinbuf[9]; - l2cap_event_flag |= L2CAP_FLAG_DISCONNECT_CONTROL_RESPONSE; - } - else if (l2capinbuf[12] == interrupt_scid[0] && l2capinbuf[13] == interrupt_scid[1]) { - //Serial.print("\r\nDisconnect Response: Interrupt Channel"); - identifier = l2capinbuf[9]; - l2cap_event_flag |= L2CAP_FLAG_DISCONNECT_INTERRUPT_RESPONSE; - } - } + identifier = l2capinbuf[9]; + pBtd->l2cap_disconnection_response(hci_handle, identifier, interrupt_dcid, interrupt_scid); + Reset(); + } + } else if (l2capinbuf[8] == L2CAP_CMD_DISCONNECT_RESPONSE) { + if (l2capinbuf[12] == control_scid[0] && l2capinbuf[13] == control_scid[1]) { + //Serial.print("\r\nDisconnect Response: Control Channel"); + identifier = l2capinbuf[9]; + l2cap_event_flag |= L2CAP_FLAG_DISCONNECT_CONTROL_RESPONSE; + } else if (l2capinbuf[12] == interrupt_scid[0] && l2capinbuf[13] == interrupt_scid[1]) { + //Serial.print("\r\nDisconnect Response: Interrupt Channel"); + identifier = l2capinbuf[9]; + l2cap_event_flag |= L2CAP_FLAG_DISCONNECT_INTERRUPT_RESPONSE; + } + } #ifdef EXTRADEBUG - else { - Notify(PSTR("\r\nL2CAP Unknown Signaling Command: "), 0x80); - PrintHex(l2capinbuf[8], 0x80); - } + else { + Notify(PSTR("\r\nL2CAP Unknown Signaling Command: "), 0x80); + PrintHex (l2capinbuf[8], 0x80); + } #endif - } else if (l2capinbuf[6] == interrupt_dcid[0] && l2capinbuf[7] == interrupt_dcid[1]) { // l2cap_interrupt - //Serial.print("\r\nL2CAP Interrupt"); - if(PS3Connected || PS3MoveConnected || PS3NavigationConnected) { - /* Read Report */ - if(l2capinbuf[8] == 0xA1) { // HID_THDR_DATA_INPUT - if(PS3Connected || PS3NavigationConnected) - ButtonState = (uint32_t)(l2capinbuf[11] | ((uint16_t)l2capinbuf[12] << 8) | ((uint32_t)l2capinbuf[13] << 16)); - else if(PS3MoveConnected) - ButtonState = (uint32_t)(l2capinbuf[10] | ((uint16_t)l2capinbuf[11] << 8) | ((uint32_t)l2capinbuf[12] << 16)); + } else if (l2capinbuf[6] == interrupt_dcid[0] && l2capinbuf[7] == interrupt_dcid[1]) { // l2cap_interrupt + //Serial.print("\r\nL2CAP Interrupt"); + if (PS3Connected || PS3MoveConnected || PS3NavigationConnected) { + /* Read Report */ + if (l2capinbuf[8] == 0xA1) { // HID_THDR_DATA_INPUT + if (PS3Connected || PS3NavigationConnected) + ButtonState = (uint32_t)(l2capinbuf[11] | ((uint16_t)l2capinbuf[12] << 8) | ((uint32_t)l2capinbuf[13] << 16)); + else if (PS3MoveConnected) + ButtonState = (uint32_t)(l2capinbuf[10] | ((uint16_t)l2capinbuf[11] << 8) | ((uint32_t)l2capinbuf[12] << 16)); - //Notify(PSTR("\r\nButtonState", 0x80); - //PrintHex(ButtonState, 0x80); + //Notify(PSTR("\r\nButtonState", 0x80); + //PrintHex(ButtonState, 0x80); - if(ButtonState != OldButtonState) { - ButtonClickState = ButtonState & ~OldButtonState; // Update click state variable - OldButtonState = ButtonState; - } + if (ButtonState != OldButtonState) { + ButtonClickState = ButtonState & ~OldButtonState; // Update click state variable + OldButtonState = ButtonState; + } #ifdef PRINTREPORT // Uncomment "#define PRINTREPORT" to print the report send by the PS3 Controllers - for(uint8_t i = 10; i < 58;i++) { - PrintHex(l2capinbuf[i], 0x80); - Serial.print(" "); - } - Serial.println(); + for (uint8_t i = 10; i < 58; i++) { + PrintHex (l2capinbuf[i], 0x80); + Serial.print(" "); + } + Serial.println(); #endif + } + } } - } + L2CAP_task(); } - L2CAP_task(); - } } + void PS3BT::L2CAP_task() { - switch (l2cap_state) { - case L2CAP_WAIT: - if (l2cap_connection_request_control_flag) { + switch (l2cap_state) { + case L2CAP_WAIT: + if (l2cap_connection_request_control_flag) { #ifdef DEBUG - Notify(PSTR("\r\nHID Control Incoming Connection Request"), 0x80); + Notify(PSTR("\r\nHID Control Incoming Connection Request"), 0x80); #endif - pBtd->l2cap_connection_response(hci_handle,identifier, control_dcid, control_scid, PENDING); - delay(1); - pBtd->l2cap_connection_response(hci_handle,identifier, control_dcid, control_scid, SUCCESSFUL); - identifier++; - delay(1); - pBtd->l2cap_config_request(hci_handle,identifier, control_scid); - l2cap_state = L2CAP_CONTROL_REQUEST; - } - break; - case L2CAP_CONTROL_REQUEST: - if (l2cap_config_request_control_flag) { + pBtd->l2cap_connection_response(hci_handle, identifier, control_dcid, control_scid, PENDING); + delay(1); + pBtd->l2cap_connection_response(hci_handle, identifier, control_dcid, control_scid, SUCCESSFUL); + identifier++; + delay(1); + pBtd->l2cap_config_request(hci_handle, identifier, control_scid); + l2cap_state = L2CAP_CONTROL_REQUEST; + } + break; + case L2CAP_CONTROL_REQUEST: + if (l2cap_config_request_control_flag) { #ifdef DEBUG - Notify(PSTR("\r\nHID Control Configuration Request"), 0x80); + Notify(PSTR("\r\nHID Control Configuration Request"), 0x80); #endif - pBtd->l2cap_config_response(hci_handle,identifier, control_scid); - l2cap_state = L2CAP_CONTROL_SUCCESS; - } - break; + pBtd->l2cap_config_response(hci_handle, identifier, control_scid); + l2cap_state = L2CAP_CONTROL_SUCCESS; + } + break; - case L2CAP_CONTROL_SUCCESS: - if (l2cap_config_success_control_flag) { + case L2CAP_CONTROL_SUCCESS: + if (l2cap_config_success_control_flag) { #ifdef DEBUG - Notify(PSTR("\r\nHID Control Successfully Configured"), 0x80); + Notify(PSTR("\r\nHID Control Successfully Configured"), 0x80); #endif - l2cap_state = L2CAP_INTERRUPT_SETUP; - } - break; - case L2CAP_INTERRUPT_SETUP: - if (l2cap_connection_request_interrupt_flag) { + l2cap_state = L2CAP_INTERRUPT_SETUP; + } + break; + case L2CAP_INTERRUPT_SETUP: + if (l2cap_connection_request_interrupt_flag) { #ifdef DEBUG - Notify(PSTR("\r\nHID Interrupt Incoming Connection Request"), 0x80); + Notify(PSTR("\r\nHID Interrupt Incoming Connection Request"), 0x80); #endif - pBtd->l2cap_connection_response(hci_handle,identifier, interrupt_dcid, interrupt_scid, PENDING); - delay(1); - pBtd->l2cap_connection_response(hci_handle,identifier, interrupt_dcid, interrupt_scid, SUCCESSFUL); - identifier++; - delay(1); - pBtd->l2cap_config_request(hci_handle,identifier, interrupt_scid); + pBtd->l2cap_connection_response(hci_handle, identifier, interrupt_dcid, interrupt_scid, PENDING); + delay(1); + pBtd->l2cap_connection_response(hci_handle, identifier, interrupt_dcid, interrupt_scid, SUCCESSFUL); + identifier++; + delay(1); + pBtd->l2cap_config_request(hci_handle, identifier, interrupt_scid); - l2cap_state = L2CAP_INTERRUPT_REQUEST; - } - break; - case L2CAP_INTERRUPT_REQUEST: - if (l2cap_config_request_interrupt_flag) { + l2cap_state = L2CAP_INTERRUPT_REQUEST; + } + break; + case L2CAP_INTERRUPT_REQUEST: + if (l2cap_config_request_interrupt_flag) { #ifdef DEBUG - Notify(PSTR("\r\nHID Interrupt Configuration Request"), 0x80); + Notify(PSTR("\r\nHID Interrupt Configuration Request"), 0x80); #endif - pBtd->l2cap_config_response(hci_handle,identifier, interrupt_scid); - l2cap_state = L2CAP_INTERRUPT_SUCCESS; - } - break; - case L2CAP_INTERRUPT_SUCCESS: - if (l2cap_config_success_interrupt_flag) { + pBtd->l2cap_config_response(hci_handle, identifier, interrupt_scid); + l2cap_state = L2CAP_INTERRUPT_SUCCESS; + } + break; + case L2CAP_INTERRUPT_SUCCESS: + if (l2cap_config_success_interrupt_flag) { #ifdef DEBUG - Notify(PSTR("\r\nHID Interrupt Successfully Configured"), 0x80); + Notify(PSTR("\r\nHID Interrupt Successfully Configured"), 0x80); #endif - if(remote_name[0] == 'M') { // First letter in Motion Controller ('M') - for (uint8_t i = 0; i < BULK_MAXPKTSIZE; i++) // Reset l2cap in buffer as it sometimes read it as a button has been pressed - l2capinbuf[i] = 0; - ButtonState = 0; - OldButtonState = 0; + if (remote_name[0] == 'M') { // First letter in Motion Controller ('M') + for (uint8_t i = 0; i < BULK_MAXPKTSIZE; i++) // Reset l2cap in buffer as it sometimes read it as a button has been pressed + l2capinbuf[i] = 0; + ButtonState = 0; + OldButtonState = 0; - l2cap_state = L2CAP_HID_PS3_LED; - } else - l2cap_state = L2CAP_HID_ENABLE_SIXAXIS; - timer = millis(); - } - break; + l2cap_state = L2CAP_HID_PS3_LED; + } else + l2cap_state = L2CAP_HID_ENABLE_SIXAXIS; + timer = millis(); + } + break; - /* These states are handled in Run() */ + /* These states are handled in Run() */ - case L2CAP_INTERRUPT_DISCONNECT: - if (l2cap_disconnect_response_interrupt_flag) { + case L2CAP_INTERRUPT_DISCONNECT: + if (l2cap_disconnect_response_interrupt_flag) { #ifdef DEBUG - Notify(PSTR("\r\nDisconnected Interrupt Channel"), 0x80); + Notify(PSTR("\r\nDisconnected Interrupt Channel"), 0x80); #endif - identifier++; - pBtd->l2cap_disconnection_request(hci_handle, identifier, control_scid, control_dcid); - l2cap_state = L2CAP_CONTROL_DISCONNECT; - } - break; + identifier++; + pBtd->l2cap_disconnection_request(hci_handle, identifier, control_scid, control_dcid); + l2cap_state = L2CAP_CONTROL_DISCONNECT; + } + break; - case L2CAP_CONTROL_DISCONNECT: - if (l2cap_disconnect_response_control_flag) { + case L2CAP_CONTROL_DISCONNECT: + if (l2cap_disconnect_response_control_flag) { #ifdef DEBUG - Notify(PSTR("\r\nDisconnected Control Channel"), 0x80); + Notify(PSTR("\r\nDisconnected Control Channel"), 0x80); #endif - pBtd->hci_disconnect(hci_handle); - hci_handle = -1; // Reset handle - l2cap_event_flag = 0; // Reset flags - l2cap_state = L2CAP_WAIT; - } - break; - } + pBtd->hci_disconnect(hci_handle); + hci_handle = -1; // Reset handle + l2cap_event_flag = 0; // Reset flags + l2cap_state = L2CAP_WAIT; + } + break; + } } + void PS3BT::Run() { - switch (l2cap_state) { - case L2CAP_HID_ENABLE_SIXAXIS: - if(millis() - timer > 1000) { // loop 1 second before sending the command - for (uint8_t i = 0; i < BULK_MAXPKTSIZE; i++) // Reset l2cap in buffer as it sometimes read it as a button has been pressed - l2capinbuf[i] = 0; - ButtonState = 0; - OldButtonState = 0; + switch (l2cap_state) { + case L2CAP_HID_ENABLE_SIXAXIS: + if (millis() - timer > 1000) { // loop 1 second before sending the command + for (uint8_t i = 0; i < BULK_MAXPKTSIZE; i++) // Reset l2cap in buffer as it sometimes read it as a button has been pressed + l2capinbuf[i] = 0; + ButtonState = 0; + OldButtonState = 0; - enable_sixaxis(); - for (uint8_t i = 15; i < 19; i++) - l2capinbuf[i] = 0x7F; // Set the analog joystick values to center position - l2cap_state = L2CAP_HID_PS3_LED; - timer = millis(); - } - break; + enable_sixaxis(); + for (uint8_t i = 15; i < 19; i++) + l2capinbuf[i] = 0x7F; // Set the analog joystick values to center position + l2cap_state = L2CAP_HID_PS3_LED; + timer = millis(); + } + break; - case L2CAP_HID_PS3_LED: - if(millis() - timer > 1000) { // loop 1 second before sending the command - if (remote_name[0] == 'P') { // First letter in PLAYSTATION(R)3 Controller ('P') - setLedOn(LED1); + case L2CAP_HID_PS3_LED: + if (millis() - timer > 1000) { // loop 1 second before sending the command + if (remote_name[0] == 'P') { // First letter in PLAYSTATION(R)3 Controller ('P') + setLedOn(LED1); #ifdef DEBUG - Notify(PSTR("\r\nDualshock 3 Controller Enabled\r\n"), 0x80); + Notify(PSTR("\r\nDualshock 3 Controller Enabled\r\n"), 0x80); #endif - PS3Connected = true; - } else if (remote_name[0] == 'N') { // First letter in Navigation Controller ('N') - setLedOn(LED1); // This just turns LED constantly on, on the Navigation controller + PS3Connected = true; + } else if (remote_name[0] == 'N') { // First letter in Navigation Controller ('N') + setLedOn(LED1); // This just turns LED constantly on, on the Navigation controller #ifdef DEBUG - Notify(PSTR("\r\nNavigation Controller Enabled\r\n"), 0x80); + Notify(PSTR("\r\nNavigation Controller Enabled\r\n"), 0x80); #endif - PS3NavigationConnected = true; - } else if(remote_name[0] == 'M') { // First letter in Motion Controller ('M') - moveSetBulb(Red); - timerBulbRumble = millis(); + PS3NavigationConnected = true; + } else if (remote_name[0] == 'M') { // First letter in Motion Controller ('M') + moveSetBulb(Red); + timerBulbRumble = millis(); #ifdef DEBUG - Notify(PSTR("\r\nMotion Controller Enabled\r\n"), 0x80); + Notify(PSTR("\r\nMotion Controller Enabled\r\n"), 0x80); #endif - PS3MoveConnected = true; - } - l2cap_state = L2CAP_DONE; - } - break; + PS3MoveConnected = true; + } + l2cap_state = L2CAP_DONE; + } + break; - case L2CAP_DONE: - if (PS3MoveConnected) { //The Bulb and rumble values, has to be send at aproximatly every 5th second for it to stay on - if (millis() - timerBulbRumble > 4000) { //Send at least every 4th second - HIDMove_Command(HIDMoveBuffer, HID_BUFFERSIZE);//The Bulb and rumble values, has to be written again and again, for it to stay turned on - timerBulbRumble = millis(); - } - } - break; - } + case L2CAP_DONE: + if (PS3MoveConnected) { //The Bulb and rumble values, has to be send at aproximatly every 5th second for it to stay on + if (millis() - timerBulbRumble > 4000) { //Send at least every 4th second + HIDMove_Command(HIDMoveBuffer, HID_BUFFERSIZE); //The Bulb and rumble values, has to be written again and again, for it to stay turned on + timerBulbRumble = millis(); + } + } + break; + } } /************************************************************/ @@ -562,96 +564,107 @@ void PS3BT::Run() { /************************************************************/ //Playstation Sixaxis Dualshock and Navigation Controller commands + void PS3BT::HID_Command(uint8_t* data, uint8_t nbytes) { - if (millis() - timerHID <= 250)// Check if is has been more than 250ms since last command - delay((uint32_t)(250 - (millis() - timerHID)));//There have to be a delay between commands - pBtd->L2CAP_Command(hci_handle,data,nbytes,control_scid[0],control_scid[1]); // Both the Navigation and Dualshock controller sends data via the control channel - timerHID = millis(); + if (millis() - timerHID <= 250)// Check if is has been more than 250ms since last command + delay((uint32_t)(250 - (millis() - timerHID))); //There have to be a delay between commands + pBtd->L2CAP_Command(hci_handle, data, nbytes, control_scid[0], control_scid[1]); // Both the Navigation and Dualshock controller sends data via the control channel + timerHID = millis(); } + void PS3BT::setAllOff() { - for (uint8_t i = 0; i < OUTPUT_REPORT_BUFFER_SIZE; i++) - HIDBuffer[i + 2] = pgm_read_byte(&OUTPUT_REPORT_BUFFER[i]);//First two bytes reserved for report type and ID + for (uint8_t i = 0; i < OUTPUT_REPORT_BUFFER_SIZE; i++) + HIDBuffer[i + 2] = pgm_read_byte(&OUTPUT_REPORT_BUFFER[i]); //First two bytes reserved for report type and ID - HID_Command(HIDBuffer, HID_BUFFERSIZE); -} -void PS3BT::setRumbleOff() { - HIDBuffer[3] = 0x00; - HIDBuffer[4] = 0x00;//low mode off - HIDBuffer[5] = 0x00; - HIDBuffer[6] = 0x00;//high mode off - - HID_Command(HIDBuffer, HID_BUFFERSIZE); -} -void PS3BT::setRumbleOn(Rumble mode) { - /* Still not totally sure how it works, maybe something like this instead? - * 3 - duration_right - * 4 - power_right - * 5 - duration_left - * 6 - power_left - */ - if ((mode & 0x30) > 0) { - HIDBuffer[3] = 0xfe; - HIDBuffer[5] = 0xfe; - if (mode == RumbleHigh) { - HIDBuffer[4] = 0;//low mode off - HIDBuffer[6] = 0xff;//high mode on - } - else { - HIDBuffer[4] = 0xff;//low mode on - HIDBuffer[6] = 0;//high mode off - } HID_Command(HIDBuffer, HID_BUFFERSIZE); - } } -void PS3BT::setLedOff(LED a) { - HIDBuffer[11] &= ~((uint8_t)((pgm_read_byte(&LEDS[(uint8_t)a]) & 0x0f) << 1)); - HID_Command(HIDBuffer, HID_BUFFERSIZE); -} -void PS3BT::setLedOn(LED a) { - HIDBuffer[11] |= (uint8_t)((pgm_read_byte(&LEDS[(uint8_t)a]) & 0x0f) << 1); - HID_Command(HIDBuffer, HID_BUFFERSIZE); -} -void PS3BT::setLedToggle(LED a) { - HIDBuffer[11] ^= (uint8_t)((pgm_read_byte(&LEDS[(uint8_t)a]) & 0x0f) << 1); - HID_Command(HIDBuffer, HID_BUFFERSIZE); -} -void PS3BT::enable_sixaxis() { //Command used to enable the Dualshock 3 and Navigation controller to send data via USB - uint8_t cmd_buf[6]; - cmd_buf[0] = 0x53;// HID BT Set_report (0x50) | Report Type (Feature 0x03) - cmd_buf[1] = 0xF4;// Report ID - cmd_buf[2] = 0x42;// Special PS3 Controller enable commands - cmd_buf[3] = 0x03; - cmd_buf[4] = 0x00; - cmd_buf[5] = 0x00; - HID_Command(cmd_buf, 6); +void PS3BT::setRumbleOff() { + HIDBuffer[3] = 0x00; + HIDBuffer[4] = 0x00; //low mode off + HIDBuffer[5] = 0x00; + HIDBuffer[6] = 0x00; //high mode off + + HID_Command(HIDBuffer, HID_BUFFERSIZE); +} + +void PS3BT::setRumbleOn(Rumble mode) { + /* Still not totally sure how it works, maybe something like this instead? + * 3 - duration_right + * 4 - power_right + * 5 - duration_left + * 6 - power_left + */ + if ((mode & 0x30) > 0) { + HIDBuffer[3] = 0xfe; + HIDBuffer[5] = 0xfe; + if (mode == RumbleHigh) { + HIDBuffer[4] = 0; //low mode off + HIDBuffer[6] = 0xff; //high mode on + } else { + HIDBuffer[4] = 0xff; //low mode on + HIDBuffer[6] = 0; //high mode off + } + HID_Command(HIDBuffer, HID_BUFFERSIZE); + } +} + +void PS3BT::setLedOff(LED a) { + HIDBuffer[11] &= ~((uint8_t)((pgm_read_byte(&LEDS[(uint8_t)a]) & 0x0f) << 1)); + HID_Command(HIDBuffer, HID_BUFFERSIZE); +} + +void PS3BT::setLedOn(LED a) { + HIDBuffer[11] |= (uint8_t)((pgm_read_byte(&LEDS[(uint8_t)a]) & 0x0f) << 1); + HID_Command(HIDBuffer, HID_BUFFERSIZE); +} + +void PS3BT::setLedToggle(LED a) { + HIDBuffer[11] ^= (uint8_t)((pgm_read_byte(&LEDS[(uint8_t)a]) & 0x0f) << 1); + HID_Command(HIDBuffer, HID_BUFFERSIZE); +} + +void PS3BT::enable_sixaxis() { //Command used to enable the Dualshock 3 and Navigation controller to send data via USB + uint8_t cmd_buf[6]; + cmd_buf[0] = 0x53; // HID BT Set_report (0x50) | Report Type (Feature 0x03) + cmd_buf[1] = 0xF4; // Report ID + cmd_buf[2] = 0x42; // Special PS3 Controller enable commands + cmd_buf[3] = 0x03; + cmd_buf[4] = 0x00; + cmd_buf[5] = 0x00; + + HID_Command(cmd_buf, 6); } //Playstation Move Controller commands -void PS3BT::HIDMove_Command(uint8_t* data,uint8_t nbytes) { - if (millis() - timerHID <= 250)// Check if is has been less than 200ms since last command - delay((uint32_t)(250 - (millis() - timerHID)));//There have to be a delay between commands - pBtd->L2CAP_Command(hci_handle,data,nbytes,interrupt_scid[0],interrupt_scid[1]); // The Move controller sends it's data via the intterrupt channel - timerHID = millis(); -} -void PS3BT::moveSetBulb(uint8_t r, uint8_t g, uint8_t b) { //Use this to set the Color using RGB values - //set the Bulb's values into the write buffer - HIDMoveBuffer[3] = r; - HIDMoveBuffer[4] = g; - HIDMoveBuffer[5] = b; - HIDMove_Command(HIDMoveBuffer, HID_BUFFERSIZE); +void PS3BT::HIDMove_Command(uint8_t* data, uint8_t nbytes) { + if (millis() - timerHID <= 250)// Check if is has been less than 200ms since last command + delay((uint32_t)(250 - (millis() - timerHID))); //There have to be a delay between commands + pBtd->L2CAP_Command(hci_handle, data, nbytes, interrupt_scid[0], interrupt_scid[1]); // The Move controller sends it's data via the intterrupt channel + timerHID = millis(); } + +void PS3BT::moveSetBulb(uint8_t r, uint8_t g, uint8_t b) { //Use this to set the Color using RGB values + //set the Bulb's values into the write buffer + HIDMoveBuffer[3] = r; + HIDMoveBuffer[4] = g; + HIDMoveBuffer[5] = b; + + HIDMove_Command(HIDMoveBuffer, HID_BUFFERSIZE); +} + void PS3BT::moveSetBulb(Colors color) { //Use this to set the Color using the predefined colors in enum - moveSetBulb((uint8_t)(color >> 16),(uint8_t)(color >> 8),(uint8_t)(color)); + moveSetBulb((uint8_t)(color >> 16), (uint8_t)(color >> 8), (uint8_t)(color)); } + void PS3BT::moveSetRumble(uint8_t rumble) { #ifdef DEBUG - if(rumble < 64 && rumble != 0) // The rumble value has to at least 64, or approximately 25% (64/255*100) - Notify(PSTR("\r\nThe rumble value has to at least 64, or approximately 25%"), 0x80); + if (rumble < 64 && rumble != 0) // The rumble value has to at least 64, or approximately 25% (64/255*100) + Notify(PSTR("\r\nThe rumble value has to at least 64, or approximately 25%"), 0x80); #endif - //set the rumble value into the write buffer - HIDMoveBuffer[7] = rumble; + //set the rumble value into the write buffer + HIDMoveBuffer[7] = rumble; - HIDMove_Command(HIDMoveBuffer, HID_BUFFERSIZE); + HIDMove_Command(HIDMoveBuffer, HID_BUFFERSIZE); } \ No newline at end of file diff --git a/PS3BT.h b/PS3BT.h index 75bd4d6e..4b5ed90f 100644 --- a/PS3BT.h +++ b/PS3BT.h @@ -1,15 +1,15 @@ /* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved. - + This software may be distributed and modified under the terms of the GNU General Public License version 2 (GPL2) as published by the Free Software Foundation and appearing in the file GPL2.TXT included in the packaging of this file. Please note that GPL2 Section 2[b] requires that all works based on this software must also be made publicly available under the terms of the GPL2 ("Copyleft"). - + Contact information ------------------- - + Kristian Lauszus, TKJ Electronics Web : http://www.tkjelectronics.com e-mail : kristianl@tkjelectronics.com @@ -60,187 +60,187 @@ /** * This BluetoothService class implements support for all the official PS3 Controllers: * Dualshock 3, Navigation or a Motion controller via Bluetooth. - * + * * Information about the protocol can be found at the wiki: https://github.com/felis/USB_Host_Shield_2.0/wiki/PS3-Information. */ class PS3BT : public BluetoothService { public: - /** - * Constructor for the PS3BT class. - * @param pBtd Pointer to BTD class instance. - * @param btadr5,btadr4,btadr3,btadr2,btadr1,btadr0 - * Pass your dongles Bluetooth address into the constructor, - * This will set BTD#my_bdaddr, so you don't have to plug in the dongle before pairing with your controller. - */ - PS3BT(BTD *pBtd, uint8_t btadr5=0, uint8_t btadr4=0, uint8_t btadr3=0, uint8_t btadr2=0, uint8_t btadr1=0, uint8_t btadr0=0); - - /** @name BluetoothService implementation */ - /** - * Used to pass acldata to the services. - * @param ACLData Incoming acldata. - */ - virtual void ACLData(uint8_t* ACLData); - /** Used to run part of the state maschine. */ - virtual void Run(); - /** Use this to reset the service. */ - virtual void Reset(); - /** Used this to disconnect any of the controllers. */ - virtual void disconnect(); - /**@}*/ - - /** @name PS3 Controller functions */ - /** - * getButtonPress(Button b) will return true as long as the button is held down. - * - * While getButtonClick(Button b) will only return it once. - * - * So you instance if you need to increase a variable once you would use getButtonClick(Button b), - * but if you need to drive a robot forward you would use getButtonPress(Button b). - */ - bool getButtonPress(Button b); - bool getButtonClick(Button b); - /**@}*/ - /** @name PS3 Controller functions */ - /** - * Used to get the analog value from button presses. - * @param a The ::Button to read. - * The supported buttons are: - * ::UP, ::RIGHT, ::DOWN, ::LEFT, ::L1, ::L2, ::R1, ::R2, - * ::TRIANGLE, ::CIRCLE, ::CROSS, ::SQUARE, and ::T. - * @return Analog value in the range of 0-255. - */ - uint8_t getAnalogButton(Button a); - /** - * Used to read the analog joystick. - * @param a ::LeftHatX, ::LeftHatY, ::RightHatX, and ::RightHatY. - * @return Return the analog value in the range of 0-255. - */ - uint8_t getAnalogHat(AnalogHat a); - /** - * Used to read the sensors inside the Dualshock 3 and Move controller. - * @param a - * The Dualshock 3 has a 3-axis accelerometer and a 1-axis gyro inside. - * The Move controller has a 3-axis accelerometer, a 3-axis gyro, a 3-axis magnetometer - * and a temperature sensor inside. - * @return Return the raw sensor value. - */ - int16_t getSensor(Sensor a); - /** - * Use this to get ::Pitch and ::Roll calculated using the accelerometer. - * @param a Either ::Pitch or ::Roll. - * @return Return the angle in the range of 0-360. - */ - double getAngle(Angle a); - /** - * Read the sensors inside the Move controller. - * @param a ::aXmove, ::aYmove, ::aZmove, ::gXmove, ::gYmove, ::gZmove, ::mXmove, ::mYmove, and ::mXmove. - * @return The value in SI units. - */ - double get9DOFValues(Sensor a); - /** - * Get the ::Status from the controller. - * @param c The ::Status you want to read. - * @return True if correct and false if not. - */ - bool getStatus(Status c); - /** - * Read all the available ::Status from the controller. - * @return One large string with all the information. - */ - String getStatusString(); - /** - * Read the temperature from the Move controller. - * @return The temperature in degrees celsius. - */ - String getTemperature(); - - /** Used to set all LEDs and ::Rumble off. */ - void setAllOff(); - /** Turn off ::Rumble. */ - void setRumbleOff(); - /** - * Turn on ::Rumble. - * @param mode Either ::RumbleHigh or ::RumbleLow. - */ - void setRumbleOn(Rumble mode); - /** - * Turn the specific ::LED off. - * @param a The ::LED to turn off. - */ - void setLedOff(LED a); - /** - * Turn the specific ::LED on. - * @param a The ::LED to turn on. - */ - void setLedOn(LED a); - /** - * Toggle the specific ::LED. - * @param a The ::LED to toggle. - */ - void setLedToggle(LED a); - - /** - * Use this to set the Color using RGB values. - * @param r,g,b RGB value. - */ - void moveSetBulb(uint8_t r, uint8_t g, uint8_t b); - /** - * Use this to set the color using the predefined colors in ::Colors. - * @param color The desired color. - */ - void moveSetBulb(Colors color); - /** - * Set the rumble value inside the Move controller. - * @param rumble The desired value in the range from 64-255. - */ - void moveSetRumble(uint8_t rumble); - /**@}*/ - - /** Variable used to indicate if the normal playstation controller is successfully connected. */ - bool PS3Connected; - /** Variable used to indicate if the move controller is successfully connected. */ - bool PS3MoveConnected; - /** Variable used to indicate if the navigation controller is successfully connected. */ - bool PS3NavigationConnected; - + /** + * Constructor for the PS3BT class. + * @param pBtd Pointer to BTD class instance. + * @param btadr5,btadr4,btadr3,btadr2,btadr1,btadr0 + * Pass your dongles Bluetooth address into the constructor, + * This will set BTD#my_bdaddr, so you don't have to plug in the dongle before pairing with your controller. + */ + PS3BT(BTD *pBtd, uint8_t btadr5 = 0, uint8_t btadr4 = 0, uint8_t btadr3 = 0, uint8_t btadr2 = 0, uint8_t btadr1 = 0, uint8_t btadr0 = 0); + + /** @name BluetoothService implementation */ + /** + * Used to pass acldata to the services. + * @param ACLData Incoming acldata. + */ + virtual void ACLData(uint8_t* ACLData); + /** Used to run part of the state maschine. */ + virtual void Run(); + /** Use this to reset the service. */ + virtual void Reset(); + /** Used this to disconnect any of the controllers. */ + virtual void disconnect(); + /**@}*/ + + /** @name PS3 Controller functions */ + /** + * getButtonPress(Button b) will return true as long as the button is held down. + * + * While getButtonClick(Button b) will only return it once. + * + * So you instance if you need to increase a variable once you would use getButtonClick(Button b), + * but if you need to drive a robot forward you would use getButtonPress(Button b). + */ + bool getButtonPress(Button b); + bool getButtonClick(Button b); + /**@}*/ + /** @name PS3 Controller functions */ + /** + * Used to get the analog value from button presses. + * @param a The ::Button to read. + * The supported buttons are: + * ::UP, ::RIGHT, ::DOWN, ::LEFT, ::L1, ::L2, ::R1, ::R2, + * ::TRIANGLE, ::CIRCLE, ::CROSS, ::SQUARE, and ::T. + * @return Analog value in the range of 0-255. + */ + uint8_t getAnalogButton(Button a); + /** + * Used to read the analog joystick. + * @param a ::LeftHatX, ::LeftHatY, ::RightHatX, and ::RightHatY. + * @return Return the analog value in the range of 0-255. + */ + uint8_t getAnalogHat(AnalogHat a); + /** + * Used to read the sensors inside the Dualshock 3 and Move controller. + * @param a + * The Dualshock 3 has a 3-axis accelerometer and a 1-axis gyro inside. + * The Move controller has a 3-axis accelerometer, a 3-axis gyro, a 3-axis magnetometer + * and a temperature sensor inside. + * @return Return the raw sensor value. + */ + int16_t getSensor(Sensor a); + /** + * Use this to get ::Pitch and ::Roll calculated using the accelerometer. + * @param a Either ::Pitch or ::Roll. + * @return Return the angle in the range of 0-360. + */ + double getAngle(Angle a); + /** + * Read the sensors inside the Move controller. + * @param a ::aXmove, ::aYmove, ::aZmove, ::gXmove, ::gYmove, ::gZmove, ::mXmove, ::mYmove, and ::mXmove. + * @return The value in SI units. + */ + double get9DOFValues(Sensor a); + /** + * Get the ::Status from the controller. + * @param c The ::Status you want to read. + * @return True if correct and false if not. + */ + bool getStatus(Status c); + /** + * Read all the available ::Status from the controller. + * @return One large string with all the information. + */ + String getStatusString(); + /** + * Read the temperature from the Move controller. + * @return The temperature in degrees celsius. + */ + String getTemperature(); + + /** Used to set all LEDs and ::Rumble off. */ + void setAllOff(); + /** Turn off ::Rumble. */ + void setRumbleOff(); + /** + * Turn on ::Rumble. + * @param mode Either ::RumbleHigh or ::RumbleLow. + */ + void setRumbleOn(Rumble mode); + /** + * Turn the specific ::LED off. + * @param a The ::LED to turn off. + */ + void setLedOff(LED a); + /** + * Turn the specific ::LED on. + * @param a The ::LED to turn on. + */ + void setLedOn(LED a); + /** + * Toggle the specific ::LED. + * @param a The ::LED to toggle. + */ + void setLedToggle(LED a); + + /** + * Use this to set the Color using RGB values. + * @param r,g,b RGB value. + */ + void moveSetBulb(uint8_t r, uint8_t g, uint8_t b); + /** + * Use this to set the color using the predefined colors in ::Colors. + * @param color The desired color. + */ + void moveSetBulb(Colors color); + /** + * Set the rumble value inside the Move controller. + * @param rumble The desired value in the range from 64-255. + */ + void moveSetRumble(uint8_t rumble); + /**@}*/ + + /** Variable used to indicate if the normal playstation controller is successfully connected. */ + bool PS3Connected; + /** Variable used to indicate if the move controller is successfully connected. */ + bool PS3MoveConnected; + /** Variable used to indicate if the navigation controller is successfully connected. */ + bool PS3NavigationConnected; + private: - /* mandatory members */ - BTD *pBtd; - - void L2CAP_task(); // L2CAP state machine - - /* Variables filled from HCI event management */ - int16_t hci_handle; - uint8_t remote_name[30]; // First 30 chars of remote name - bool activeConnection; // Used to indicate if it's already has established a connection - - /* variables used by high level L2CAP task */ - uint8_t l2cap_state; - uint16_t l2cap_event_flag; // L2CAP flags of received bluetooth events - - unsigned long timer; - - uint32_t ButtonState; - uint32_t OldButtonState; - uint32_t ButtonClickState; - - uint32_t timerHID; // Timer used see if there has to be a delay before a new HID command - uint32_t timerBulbRumble;// used to continuously set PS3 Move controller Bulb and rumble values - - uint8_t l2capinbuf[BULK_MAXPKTSIZE]; // General purpose buffer for L2CAP in data - uint8_t HIDBuffer[HID_BUFFERSIZE]; // Used to store HID commands - uint8_t HIDMoveBuffer[HID_BUFFERSIZE]; // Used to store HID commands for the Move controller - - /* L2CAP Channels */ - uint8_t control_scid[2]; // L2CAP source CID for HID_Control - uint8_t control_dcid[2]; // 0x0040 - uint8_t interrupt_scid[2]; // L2CAP source CID for HID_Interrupt - uint8_t interrupt_dcid[2]; // 0x0041 - uint8_t identifier; // Identifier for connection - - /* HID Commands */ - void HID_Command(uint8_t* data, uint8_t nbytes); - void HIDMove_Command(uint8_t* data, uint8_t nbytes); - void enable_sixaxis(); // Command used to enable the Dualshock 3 and Navigation controller to send data via Bluetooth + /* mandatory members */ + BTD *pBtd; + + void L2CAP_task(); // L2CAP state machine + + /* Variables filled from HCI event management */ + int16_t hci_handle; + uint8_t remote_name[30]; // First 30 chars of remote name + bool activeConnection; // Used to indicate if it's already has established a connection + + /* variables used by high level L2CAP task */ + uint8_t l2cap_state; + uint16_t l2cap_event_flag; // L2CAP flags of received bluetooth events + + unsigned long timer; + + uint32_t ButtonState; + uint32_t OldButtonState; + uint32_t ButtonClickState; + + uint32_t timerHID; // Timer used see if there has to be a delay before a new HID command + uint32_t timerBulbRumble; // used to continuously set PS3 Move controller Bulb and rumble values + + uint8_t l2capinbuf[BULK_MAXPKTSIZE]; // General purpose buffer for L2CAP in data + uint8_t HIDBuffer[HID_BUFFERSIZE]; // Used to store HID commands + uint8_t HIDMoveBuffer[HID_BUFFERSIZE]; // Used to store HID commands for the Move controller + + /* L2CAP Channels */ + uint8_t control_scid[2]; // L2CAP source CID for HID_Control + uint8_t control_dcid[2]; // 0x0040 + uint8_t interrupt_scid[2]; // L2CAP source CID for HID_Interrupt + uint8_t interrupt_dcid[2]; // 0x0041 + uint8_t identifier; // Identifier for connection + + /* HID Commands */ + void HID_Command(uint8_t* data, uint8_t nbytes); + void HIDMove_Command(uint8_t* data, uint8_t nbytes); + void enable_sixaxis(); // Command used to enable the Dualshock 3 and Navigation controller to send data via Bluetooth }; #endif \ No newline at end of file diff --git a/PS3Enums.h b/PS3Enums.h index 449f93b9..d42f7903 100644 --- a/PS3Enums.h +++ b/PS3Enums.h @@ -1,15 +1,15 @@ /* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved. - + This software may be distributed and modified under the terms of the GNU General Public License version 2 (GPL2) as published by the Free Software Foundation and appearing in the file GPL2.TXT included in the packaging of this file. Please note that GPL2 Section 2[b] requires that all works based on this software must also be made publicly available under the terms of the GPL2 ("Copyleft"). - + Contact information ------------------- - + Kristian Lauszus, TKJ Electronics Web : http://www.tkjelectronics.com e-mail : kristianl@tkjelectronics.com @@ -22,17 +22,17 @@ /** Used to set the LEDs on the controllers */ const uint8_t LEDS[] PROGMEM = { - 0x01, // LED1 - 0x02, // LED2 - 0x04, // LED3 - 0x08, // LED4 - - 0x09, // LED5 - 0x0A, // LED6 - 0x0C, // LED7 - 0x0D, // LED8 - 0x0E, // LED9 - 0x0F // LED10 + 0x01, // LED1 + 0x02, // LED2 + 0x04, // LED3 + 0x08, // LED4 + + 0x09, // LED5 + 0x0A, // LED6 + 0x0C, // LED7 + 0x0D, // LED8 + 0x0E, // LED9 + 0x0F // LED10 }; /** @@ -41,29 +41,29 @@ const uint8_t LEDS[] PROGMEM = { * Note: that the location is shiftet 9 when it's connected via USB. */ const uint32_t BUTTONS[] PROGMEM = { - 0x10, // UP - 0x20, // RIGHT - 0x40, // DOWN - 0x80, // LEFT + 0x10, // UP + 0x20, // RIGHT + 0x40, // DOWN + 0x80, // LEFT - 0x01, // SELECT - 0x08, // START - 0x02, // L3 - 0x04, // R3 - - 0x0100, // L2 - 0x0200, // R2 - 0x0400, // L1 - 0x0800, // R1 + 0x01, // SELECT + 0x08, // START + 0x02, // L3 + 0x04, // R3 - 0x1000, // TRIANGLE - 0x2000, // CIRCLE - 0x4000, // CROSS - 0x8000, // SQUARE - - 0x010000, // PS - 0x080000, // MOVE - covers 12 bits - we only need to read the top 8 - 0x100000 // T - covers 12 bits - we only need to read the top 8 + 0x0100, // L2 + 0x0200, // R2 + 0x0400, // L1 + 0x0800, // R1 + + 0x1000, // TRIANGLE + 0x2000, // CIRCLE + 0x4000, // CROSS + 0x8000, // SQUARE + + 0x010000, // PS + 0x080000, // MOVE - covers 12 bits - we only need to read the top 8 + 0x100000 // T - covers 12 bits - we only need to read the top 8 }; /** @@ -72,122 +72,125 @@ const uint32_t BUTTONS[] PROGMEM = { * Note: that the location is shiftet 9 when it's connected via USB. */ const uint8_t ANALOGBUTTONS[] PROGMEM = { - 23, // UP_ANALOG - 24, // RIGHT_ANALOG - 25, // DOWN_ANALOG - 26, // LEFT_ANALOG - 0,0,0,0, // Skip SELECT, L3, R3 and START - - 27, // L2_ANALOG - 28, // R2_ANALOG - 29, // L1_ANALOG - 30, // R1_ANALOG - 31, // TRIANGLE_ANALOG - 32, // CIRCLE_ANALOG - 33, // CROSS_ANALOG - 34, // SQUARE_ANALOG - 0,0, // Skip PS and MOVE - - // Playstation Move Controller - 15 // T_ANALOG - Both at byte 14 (last reading) and byte 15 (current reading) + 23, // UP_ANALOG + 24, // RIGHT_ANALOG + 25, // DOWN_ANALOG + 26, // LEFT_ANALOG + 0, 0, 0, 0, // Skip SELECT, L3, R3 and START + + 27, // L2_ANALOG + 28, // R2_ANALOG + 29, // L1_ANALOG + 30, // R1_ANALOG + 31, // TRIANGLE_ANALOG + 32, // CIRCLE_ANALOG + 33, // CROSS_ANALOG + 34, // SQUARE_ANALOG + 0, 0, // Skip PS and MOVE + + // Playstation Move Controller + 15 // T_ANALOG - Both at byte 14 (last reading) and byte 15 (current reading) }; /** Used to set the colors of the move controller. */ enum Colors { - /** r = 255, g = 0, b = 0 */ - Red = 0xFF0000, - /** r = 0, g = 255, b = 0 */ - Green = 0xFF00, - /** r = 0, g = 0, b = 255 */ - Blue = 0xFF, - - /** r = 255, g = 235, b = 4 */ - Yellow = 0xFFEB04, - /** r = 0, g = 255, b = 255 */ - Lightblue = 0xFFFF, - /** r = 255, g = 0, b = 255 */ - Purble = 0xFF00FF, - - /** r = 255, g = 255, b = 255 */ - White = 0xFFFFFF, - /** r = 0, g = 0, b = 0 */ - Off = 0x00, + /** r = 255, g = 0, b = 0 */ + Red = 0xFF0000, + /** r = 0, g = 255, b = 0 */ + Green = 0xFF00, + /** r = 0, g = 0, b = 255 */ + Blue = 0xFF, + + /** r = 255, g = 235, b = 4 */ + Yellow = 0xFFEB04, + /** r = 0, g = 255, b = 255 */ + Lightblue = 0xFFFF, + /** r = 255, g = 0, b = 255 */ + Purble = 0xFF00FF, + + /** r = 255, g = 255, b = 255 */ + White = 0xFFFFFF, + /** r = 0, g = 0, b = 0 */ + Off = 0x00, }; /** * Sensors inside the Sixaxis Dualshock 3 and Move controller. - * + * * Note: that the location is shiftet 9 when it's connected via USB. */ enum Sensor { - /** Accelerometer x-axis */ - aX = 50, - /** Accelerometer y-axis */ - aY = 52, - /** Accelerometer z-axis */ - aZ = 54, - /** Gyro z-axis */ - gZ = 56, + /** Accelerometer x-axis */ + aX = 50, + /** Accelerometer y-axis */ + aY = 52, + /** Accelerometer z-axis */ + aZ = 54, + /** Gyro z-axis */ + gZ = 56, - /** Accelerometer x-axis */ - aXmove = 28, - /** Accelerometer z-axis */ - aZmove = 30, - /** Accelerometer y-axis */ - aYmove = 32, - - /** Gyro x-axis */ - gXmove = 40, - /** Gyro z-axis */ - gZmove = 42, - /** Gyro y-axis */ - gYmove = 44, - - /** Temperature sensor */ - tempMove = 46, - - /** Magnetometer x-axis */ - mXmove = 47, - /** Magnetometer z-axis */ - mZmove = 49, - /** Magnetometer y-axis */ - mYmove = 50, + /** Accelerometer x-axis */ + aXmove = 28, + /** Accelerometer z-axis */ + aZmove = 30, + /** Accelerometer y-axis */ + aYmove = 32, + + /** Gyro x-axis */ + gXmove = 40, + /** Gyro z-axis */ + gZmove = 42, + /** Gyro y-axis */ + gYmove = 44, + + /** Temperature sensor */ + tempMove = 46, + + /** Magnetometer x-axis */ + mXmove = 47, + /** Magnetometer z-axis */ + mZmove = 49, + /** Magnetometer y-axis */ + mYmove = 50, }; + /** Used to get the angle calculated using the accelerometer. */ enum Angle { - Pitch = 0x01, - Roll = 0x02, + Pitch = 0x01, + Roll = 0x02, }; + enum Status { - // Note that the location is shiftet 9 when it's connected via USB - // Byte location | bit location - Plugged = (38 << 8) | 0x02, - Unplugged = (38 << 8) | 0x03, - - Charging = (39 << 8) | 0xEE, - NotCharging = (39 << 8) | 0xF1, - Shutdown = (39 << 8) | 0x01, - Dying = (39 << 8) | 0x02, - Low = (39 << 8) | 0x03, - High = (39 << 8) | 0x04, - Full = (39 << 8) | 0x05, - - MoveCharging = (21 << 8) | 0xEE, - MoveNotCharging = (21 << 8) | 0xF1, - MoveShutdown = (21 << 8) | 0x01, - MoveDying = (21 << 8) | 0x02, - MoveLow = (21 << 8) | 0x03, - MoveHigh = (21 << 8) | 0x04, - MoveFull = (21 << 8) | 0x05, - - CableRumble = (40 << 8) | 0x10,//Opperating by USB and rumble is turned on - Cable = (40 << 8) | 0x12,//Opperating by USB and rumble is turned off - BluetoothRumble = (40 << 8) | 0x14,//Opperating by bluetooth and rumble is turned on - Bluetooth = (40 << 8) | 0x16,//Opperating by bluetooth and rumble is turned off + // Note that the location is shiftet 9 when it's connected via USB + // Byte location | bit location + Plugged = (38 << 8) | 0x02, + Unplugged = (38 << 8) | 0x03, + + Charging = (39 << 8) | 0xEE, + NotCharging = (39 << 8) | 0xF1, + Shutdown = (39 << 8) | 0x01, + Dying = (39 << 8) | 0x02, + Low = (39 << 8) | 0x03, + High = (39 << 8) | 0x04, + Full = (39 << 8) | 0x05, + + MoveCharging = (21 << 8) | 0xEE, + MoveNotCharging = (21 << 8) | 0xF1, + MoveShutdown = (21 << 8) | 0x01, + MoveDying = (21 << 8) | 0x02, + MoveLow = (21 << 8) | 0x03, + MoveHigh = (21 << 8) | 0x04, + MoveFull = (21 << 8) | 0x05, + + CableRumble = (40 << 8) | 0x10, //Opperating by USB and rumble is turned on + Cable = (40 << 8) | 0x12, //Opperating by USB and rumble is turned off + BluetoothRumble = (40 << 8) | 0x14, //Opperating by bluetooth and rumble is turned on + Bluetooth = (40 << 8) | 0x16, //Opperating by bluetooth and rumble is turned off }; -enum Rumble { - RumbleHigh = 0x10, - RumbleLow = 0x20, + +enum Rumble { + RumbleHigh = 0x10, + RumbleLow = 0x20, }; #endif \ No newline at end of file diff --git a/PS3USB.cpp b/PS3USB.cpp index 13d835db..a7ca846a 100644 --- a/PS3USB.cpp +++ b/PS3USB.cpp @@ -21,531 +21,547 @@ //#define PRINTREPORT // Uncomment to print the report send by the PS3 Controllers const uint8_t PS3_REPORT_BUFFER[] PROGMEM = { - 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, - 0xff, 0x27, 0x10, 0x00, 0x32, - 0xff, 0x27, 0x10, 0x00, 0x32, - 0xff, 0x27, 0x10, 0x00, 0x32, - 0xff, 0x27, 0x10, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0x27, 0x10, 0x00, 0x32, + 0xff, 0x27, 0x10, 0x00, 0x32, + 0xff, 0x27, 0x10, 0x00, 0x32, + 0xff, 0x27, 0x10, 0x00, 0x32, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; const uint8_t MOVE_REPORT_BUFFER[] PROGMEM = { - 0x02, 0x00, // Always 0x02, 0x00, - 0x00, 0x00, 0x00, // r, g, b, - 0x00, // Always 0x00, - 0x00 // Rumble + 0x02, 0x00, // Always 0x02, 0x00, + 0x00, 0x00, 0x00, // r, g, b, + 0x00, // Always 0x00, + 0x00 // Rumble }; -PS3USB::PS3USB(USB *p, uint8_t btadr5, uint8_t btadr4, uint8_t btadr3, uint8_t btadr2, uint8_t btadr1, uint8_t btadr0): +PS3USB::PS3USB(USB *p, uint8_t btadr5, uint8_t btadr4, uint8_t btadr3, uint8_t btadr2, uint8_t btadr1, uint8_t btadr0) : pUsb(p), // pointer to USB class instance - mandatory bAddress(0), // device address - mandatory bPollEnable(false) // don't start polling before dongle is connected { - for(uint8_t i=0; iRegisterDeviceClass(this); //set devConfig[] entry + if (pUsb) // register in USB subsystem + pUsb->RegisterDeviceClass(this); //set devConfig[] entry - my_bdaddr[5] = btadr5; // Change to your dongle's Bluetooth address instead - my_bdaddr[4] = btadr4; - my_bdaddr[3] = btadr3; - my_bdaddr[2] = btadr2; - my_bdaddr[1] = btadr1; - my_bdaddr[0] = btadr0; + my_bdaddr[5] = btadr5; // Change to your dongle's Bluetooth address instead + my_bdaddr[4] = btadr4; + my_bdaddr[3] = btadr3; + my_bdaddr[2] = btadr2; + my_bdaddr[1] = btadr1; + my_bdaddr[0] = btadr0; } uint8_t PS3USB::Init(uint8_t parent, uint8_t port, bool lowspeed) { - uint8_t buf[sizeof(USB_DEVICE_DESCRIPTOR)]; - uint8_t rcode; - UsbDevice *p = NULL; - EpInfo *oldep_ptr = NULL; - uint16_t PID; - uint16_t VID; + uint8_t buf[sizeof (USB_DEVICE_DESCRIPTOR)]; + uint8_t rcode; + UsbDevice *p = NULL; + EpInfo *oldep_ptr = NULL; + uint16_t PID; + uint16_t VID; - // get memory address of USB device address pool - AddressPool &addrPool = pUsb->GetAddressPool(); + // get memory address of USB device address pool + AddressPool &addrPool = pUsb->GetAddressPool(); #ifdef EXTRADEBUG - Notify(PSTR("\r\nPS3USB Init"), 0x80); + Notify(PSTR("\r\nPS3USB Init"), 0x80); #endif - // check if address has already been assigned to an instance - if (bAddress) { + // check if address has already been assigned to an instance + if (bAddress) { #ifdef DEBUG - Notify(PSTR("\r\nAddress in use"), 0x80); + Notify(PSTR("\r\nAddress in use"), 0x80); #endif - return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE; - } - - // Get pointer to pseudo device with address 0 assigned - p = addrPool.GetUsbDevicePtr(0); - - if (!p) { -#ifdef DEBUG - Notify(PSTR("\r\nAddress not found"), 0x80); -#endif - return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; - } - - if (!p->epinfo) { -#ifdef DEBUG - Notify(PSTR("\r\nepinfo is null"), 0x80); -#endif - return USB_ERROR_EPINFO_IS_NULL; - } - - // Save old pointer to EP_RECORD of address 0 - oldep_ptr = p->epinfo; - - // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence - p->epinfo = epInfo; - - p->lowspeed = lowspeed; - - // Get device descriptor - rcode = pUsb->getDevDescr(0, 0, sizeof(USB_DEVICE_DESCRIPTOR), (uint8_t*)buf);// Get device descriptor - addr, ep, nbytes, data - // Restore p->epinfo - p->epinfo = oldep_ptr; - - if(rcode) - goto FailGetDevDescr; - - VID = ((USB_DEVICE_DESCRIPTOR*)buf)->idVendor; - PID = ((USB_DEVICE_DESCRIPTOR*)buf)->idProduct; - - if(VID != PS3_VID || (PID != PS3_PID && PID != PS3NAVIGATION_PID && PID != PS3MOVE_PID)) - goto FailUnknownDevice; - - // Allocate new address according to device class - bAddress = addrPool.AllocAddress(parent, false, port); - - if (!bAddress) - return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; - - // Extract Max Packet Size from device descriptor - epInfo[0].maxPktSize = (uint8_t)((USB_DEVICE_DESCRIPTOR*)buf)->bMaxPacketSize0; - - // Assign new address to the device - rcode = pUsb->setAddr( 0, 0, bAddress ); - if (rcode) { - p->lowspeed = false; - addrPool.FreeAddress(bAddress); - bAddress = 0; -#ifdef DEBUG - Notify(PSTR("\r\nsetAddr: "), 0x80); -#endif - PrintHex(rcode, 0x80); - return rcode; - } -#ifdef EXTRADEBUG - Notify(PSTR("\r\nAddr: "), 0x80); - PrintHex(bAddress, 0x80); -#endif - p->lowspeed = false; - - //get pointer to assigned address record - p = addrPool.GetUsbDevicePtr(bAddress); - if (!p) - return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; - - p->lowspeed = lowspeed; - - // Assign epInfo to epinfo pointer - only EP0 is known - rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); - if (rcode) - goto FailSetDevTblEntry; - - - /* The application will work in reduced host mode, so we can save program and data - memory space. After verifying the PID and VID we will use known values for the - configuration values for device, interface, endpoints and HID for the PS3 Controllers */ - - /* Initialize data structures for endpoints of device */ - epInfo[ PS3_OUTPUT_PIPE ].epAddr = 0x02; // PS3 output endpoint - epInfo[ PS3_OUTPUT_PIPE ].epAttribs = EP_INTERRUPT; - epInfo[ PS3_OUTPUT_PIPE ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints - epInfo[ PS3_OUTPUT_PIPE ].maxPktSize = EP_MAXPKTSIZE; - epInfo[ PS3_OUTPUT_PIPE ].bmSndToggle = bmSNDTOG0; - epInfo[ PS3_OUTPUT_PIPE ].bmRcvToggle = bmRCVTOG0; - epInfo[ PS3_INPUT_PIPE ].epAddr = 0x01; // PS3 report endpoint - epInfo[ PS3_INPUT_PIPE ].epAttribs = EP_INTERRUPT; - epInfo[ PS3_INPUT_PIPE ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints - epInfo[ PS3_INPUT_PIPE ].maxPktSize = EP_MAXPKTSIZE; - epInfo[ PS3_INPUT_PIPE ].bmSndToggle = bmSNDTOG0; - epInfo[ PS3_INPUT_PIPE ].bmRcvToggle = bmRCVTOG0; - - rcode = pUsb->setEpInfoEntry(bAddress, 3, epInfo); - if( rcode ) - goto FailSetDevTblEntry; - - delay(200);//Give time for address change - - rcode = pUsb->setConf(bAddress, epInfo[ PS3_CONTROL_PIPE ].epAddr, 1); - if( rcode ) - goto FailSetConf; - - if(PID == PS3_PID || PID == PS3NAVIGATION_PID) { - if(PID == PS3_PID) { -#ifdef DEBUG - Notify(PSTR("\r\nDualshock 3 Controller Connected"), 0x80); -#endif - PS3Connected = true; - } else { // must be a navigation controller -#ifdef DEBUG - Notify(PSTR("\r\nNavigation Controller Connected"), 0x80); -#endif - PS3NavigationConnected = true; + return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE; } - /* Set internal bluetooth address and request for data */ - setBdaddr(my_bdaddr); - enable_sixaxis(); - setLedOn(LED1); - // Needed for PS3 Dualshock and Navigation commands to work - for (uint8_t i = 0; i < PS3_REPORT_BUFFER_SIZE; i++) - writeBuf[i] = pgm_read_byte(&PS3_REPORT_BUFFER[i]); + // Get pointer to pseudo device with address 0 assigned + p = addrPool.GetUsbDevicePtr(0); - for (uint8_t i = 6; i < 10; i++) - readBuf[i] = 0x7F; // Set the analog joystick values to center position - } - else { // must be a Motion controller + if (!p) { #ifdef DEBUG - Notify(PSTR("\r\nMotion Controller Connected"), 0x80); + Notify(PSTR("\r\nAddress not found"), 0x80); #endif - PS3MoveConnected = true; - setMoveBdaddr(my_bdaddr); // Set internal bluetooth address - moveSetBulb(Red); + return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; + } - // Needed for Move commands to work - for (uint8_t i = 0; i < MOVE_REPORT_BUFFER_SIZE; i++) - writeBuf[i] = pgm_read_byte(&MOVE_REPORT_BUFFER[i]); - } + if (!p->epinfo) { +#ifdef DEBUG + Notify(PSTR("\r\nepinfo is null"), 0x80); +#endif + return USB_ERROR_EPINFO_IS_NULL; + } - bPollEnable = true; - Notify(PSTR("\r\n"), 0x80); - timer = millis(); - return 0; // successful configuration + // Save old pointer to EP_RECORD of address 0 + oldep_ptr = p->epinfo; - /* diagnostic messages */ + // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence + p->epinfo = epInfo; + + p->lowspeed = lowspeed; + + // Get device descriptor + rcode = pUsb->getDevDescr(0, 0, sizeof (USB_DEVICE_DESCRIPTOR), (uint8_t*)buf); // Get device descriptor - addr, ep, nbytes, data + // Restore p->epinfo + p->epinfo = oldep_ptr; + + if (rcode) + goto FailGetDevDescr; + + VID = ((USB_DEVICE_DESCRIPTOR*)buf)->idVendor; + PID = ((USB_DEVICE_DESCRIPTOR*)buf)->idProduct; + + if (VID != PS3_VID || (PID != PS3_PID && PID != PS3NAVIGATION_PID && PID != PS3MOVE_PID)) + goto FailUnknownDevice; + + // Allocate new address according to device class + bAddress = addrPool.AllocAddress(parent, false, port); + + if (!bAddress) + return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; + + // Extract Max Packet Size from device descriptor + epInfo[0].maxPktSize = (uint8_t)((USB_DEVICE_DESCRIPTOR*)buf)->bMaxPacketSize0; + + // Assign new address to the device + rcode = pUsb->setAddr(0, 0, bAddress); + if (rcode) { + p->lowspeed = false; + addrPool.FreeAddress(bAddress); + bAddress = 0; +#ifdef DEBUG + Notify(PSTR("\r\nsetAddr: "), 0x80); +#endif + PrintHex (rcode, 0x80); + return rcode; + } +#ifdef EXTRADEBUG + Notify(PSTR("\r\nAddr: "), 0x80); + PrintHex (bAddress, 0x80); +#endif + p->lowspeed = false; + + //get pointer to assigned address record + p = addrPool.GetUsbDevicePtr(bAddress); + if (!p) + return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; + + p->lowspeed = lowspeed; + + // Assign epInfo to epinfo pointer - only EP0 is known + rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); + if (rcode) + goto FailSetDevTblEntry; + + + /* The application will work in reduced host mode, so we can save program and data + memory space. After verifying the PID and VID we will use known values for the + configuration values for device, interface, endpoints and HID for the PS3 Controllers */ + + /* Initialize data structures for endpoints of device */ + epInfo[ PS3_OUTPUT_PIPE ].epAddr = 0x02; // PS3 output endpoint + epInfo[ PS3_OUTPUT_PIPE ].epAttribs = EP_INTERRUPT; + epInfo[ PS3_OUTPUT_PIPE ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints + epInfo[ PS3_OUTPUT_PIPE ].maxPktSize = EP_MAXPKTSIZE; + epInfo[ PS3_OUTPUT_PIPE ].bmSndToggle = bmSNDTOG0; + epInfo[ PS3_OUTPUT_PIPE ].bmRcvToggle = bmRCVTOG0; + epInfo[ PS3_INPUT_PIPE ].epAddr = 0x01; // PS3 report endpoint + epInfo[ PS3_INPUT_PIPE ].epAttribs = EP_INTERRUPT; + epInfo[ PS3_INPUT_PIPE ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints + epInfo[ PS3_INPUT_PIPE ].maxPktSize = EP_MAXPKTSIZE; + epInfo[ PS3_INPUT_PIPE ].bmSndToggle = bmSNDTOG0; + epInfo[ PS3_INPUT_PIPE ].bmRcvToggle = bmRCVTOG0; + + rcode = pUsb->setEpInfoEntry(bAddress, 3, epInfo); + if (rcode) + goto FailSetDevTblEntry; + + delay(200); //Give time for address change + + rcode = pUsb->setConf(bAddress, epInfo[ PS3_CONTROL_PIPE ].epAddr, 1); + if (rcode) + goto FailSetConf; + + if (PID == PS3_PID || PID == PS3NAVIGATION_PID) { + if (PID == PS3_PID) { +#ifdef DEBUG + Notify(PSTR("\r\nDualshock 3 Controller Connected"), 0x80); +#endif + PS3Connected = true; + } else { // must be a navigation controller +#ifdef DEBUG + Notify(PSTR("\r\nNavigation Controller Connected"), 0x80); +#endif + PS3NavigationConnected = true; + } + /* Set internal bluetooth address and request for data */ + setBdaddr(my_bdaddr); + enable_sixaxis(); + setLedOn(LED1); + + // Needed for PS3 Dualshock and Navigation commands to work + for (uint8_t i = 0; i < PS3_REPORT_BUFFER_SIZE; i++) + writeBuf[i] = pgm_read_byte(&PS3_REPORT_BUFFER[i]); + + for (uint8_t i = 6; i < 10; i++) + readBuf[i] = 0x7F; // Set the analog joystick values to center position + } else { // must be a Motion controller +#ifdef DEBUG + Notify(PSTR("\r\nMotion Controller Connected"), 0x80); +#endif + PS3MoveConnected = true; + setMoveBdaddr(my_bdaddr); // Set internal bluetooth address + moveSetBulb(Red); + + // Needed for Move commands to work + for (uint8_t i = 0; i < MOVE_REPORT_BUFFER_SIZE; i++) + writeBuf[i] = pgm_read_byte(&MOVE_REPORT_BUFFER[i]); + } + + bPollEnable = true; + Notify(PSTR("\r\n"), 0x80); + timer = millis(); + return 0; // successful configuration + + /* diagnostic messages */ FailGetDevDescr: #ifdef DEBUG - Notify(PSTR("\r\ngetDevDescr:"), 0x80); + Notify(PSTR("\r\ngetDevDescr:"), 0x80); #endif - goto Fail; + goto Fail; FailSetDevTblEntry: #ifdef DEBUG - Notify(PSTR("\r\nsetDevTblEn:"), 0x80); + Notify(PSTR("\r\nsetDevTblEn:"), 0x80); #endif - goto Fail; + goto Fail; FailSetConf: #ifdef DEBUG - Notify(PSTR("\r\nsetConf:"), 0x80); + Notify(PSTR("\r\nsetConf:"), 0x80); #endif - goto Fail; + goto Fail; FailUnknownDevice: #ifdef DEBUG - Notify(PSTR("\r\nUnknown Device Connected - VID: "), 0x80); - PrintHex(VID, 0x80); - Notify(PSTR(" PID: "), 0x80); - PrintHex(PID, 0x80); + Notify(PSTR("\r\nUnknown Device Connected - VID: "), 0x80); + PrintHex (VID, 0x80); + Notify(PSTR(" PID: "), 0x80); + PrintHex (PID, 0x80); #endif - rcode = USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; - goto Fail; + rcode = USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; + goto Fail; Fail: #ifdef DEBUG - Notify(PSTR("\r\nPS3 Init Failed, error code: "), 0x80); - Serial.print(rcode,HEX); + Notify(PSTR("\r\nPS3 Init Failed, error code: "), 0x80); + Serial.print(rcode, HEX); #endif - Release(); - return rcode; + Release(); + return rcode; } /* Performs a cleanup after failed Init() attempt */ uint8_t PS3USB::Release() { - PS3Connected = false; - PS3MoveConnected = false; - PS3NavigationConnected = false; - pUsb->GetAddressPool().FreeAddress(bAddress); - bAddress = 0; - bPollEnable = false; - return 0; + PS3Connected = false; + PS3MoveConnected = false; + PS3NavigationConnected = false; + pUsb->GetAddressPool().FreeAddress(bAddress); + bAddress = 0; + bPollEnable = false; + return 0; } -uint8_t PS3USB::Poll() { - if (!bPollEnable) - return 0; - if(PS3Connected || PS3NavigationConnected) { - uint16_t BUFFER_SIZE = EP_MAXPKTSIZE; - pUsb->inTransfer(bAddress, epInfo[ PS3_INPUT_PIPE ].epAddr, &BUFFER_SIZE, readBuf); // input on endpoint 1 - if(millis() - timer > 100) { // Loop 100ms before processing data - readReport(); +uint8_t PS3USB::Poll() { + if (!bPollEnable) + return 0; + + if (PS3Connected || PS3NavigationConnected) { + uint16_t BUFFER_SIZE = EP_MAXPKTSIZE; + pUsb->inTransfer(bAddress, epInfo[ PS3_INPUT_PIPE ].epAddr, &BUFFER_SIZE, readBuf); // input on endpoint 1 + if (millis() - timer > 100) { // Loop 100ms before processing data + readReport(); #ifdef PRINTREPORT - printReport(); // Uncomment "#define PRINTREPORT" to print the report send by the PS3 Controllers + printReport(); // Uncomment "#define PRINTREPORT" to print the report send by the PS3 Controllers #endif + } + } else if (PS3MoveConnected) { // One can only set the color of the bulb, set the rumble, set and get the bluetooth address and calibrate the magnetometer via USB + if (millis() - timer > 4000) // Send at least every 4th second + { + Move_Command(writeBuf, MOVE_REPORT_BUFFER_SIZE); // The Bulb and rumble values, has to be written again and again, for it to stay turned on + timer = millis(); + } } - } - else if(PS3MoveConnected) { // One can only set the color of the bulb, set the rumble, set and get the bluetooth address and calibrate the magnetometer via USB - if (millis() - timer > 4000) // Send at least every 4th second - { - Move_Command(writeBuf, MOVE_REPORT_BUFFER_SIZE); // The Bulb and rumble values, has to be written again and again, for it to stay turned on - timer = millis(); - } - } - return 0; + return 0; } void PS3USB::readReport() { - if (readBuf == NULL) - return; + if (readBuf == NULL) + return; - ButtonState = (uint32_t)(readBuf[2] | ((uint16_t)readBuf[3] << 8) | ((uint32_t)readBuf[4] << 16)); + ButtonState = (uint32_t)(readBuf[2] | ((uint16_t)readBuf[3] << 8) | ((uint32_t)readBuf[4] << 16)); - //Notify(PSTR("\r\nButtonState", 0x80); - //PrintHex(ButtonState, 0x80); + //Notify(PSTR("\r\nButtonState", 0x80); + //PrintHex(ButtonState, 0x80); - if(ButtonState != OldButtonState) { - ButtonClickState = ButtonState & ~OldButtonState; // Update click state variable - OldButtonState = ButtonState; - } + if (ButtonState != OldButtonState) { + ButtonClickState = ButtonState & ~OldButtonState; // Update click state variable + OldButtonState = ButtonState; + } } void PS3USB::printReport() { //Uncomment "#define PRINTREPORT" to print the report send by the PS3 Controllers #ifdef PRINTREPORT - if (readBuf == NULL) - return; - for(uint8_t i = 0; i < PS3_REPORT_BUFFER_SIZE;i++) { - PrintHex(readBuf[i], 0x80); - Serial.print(" "); - } - Serial.println(); + if (readBuf == NULL) + return; + for (uint8_t i = 0; i < PS3_REPORT_BUFFER_SIZE; i++) { + PrintHex (readBuf[i], 0x80); + Serial.print(" "); + } + Serial.println(); #endif } bool PS3USB::getButtonPress(Button b) { - return (ButtonState & pgm_read_dword(&BUTTONS[(uint8_t)b])); + return (ButtonState & pgm_read_dword(&BUTTONS[(uint8_t)b])); } + bool PS3USB::getButtonClick(Button b) { - uint32_t button = pgm_read_dword(&BUTTONS[(uint8_t)b]); - bool click = (ButtonClickState & button); - ButtonClickState &= ~button; // clear "click" event - return click; + uint32_t button = pgm_read_dword(&BUTTONS[(uint8_t)b]); + bool click = (ButtonClickState & button); + ButtonClickState &= ~button; // clear "click" event + return click; } + uint8_t PS3USB::getAnalogButton(Button a) { - if (readBuf == NULL) - return 0; - return (uint8_t)(readBuf[(pgm_read_byte(&ANALOGBUTTONS[(uint8_t)a]))-9]); + if (readBuf == NULL) + return 0; + return (uint8_t)(readBuf[(pgm_read_byte(&ANALOGBUTTONS[(uint8_t)a])) - 9]); } + uint8_t PS3USB::getAnalogHat(AnalogHat a) { - if (readBuf == NULL) - return 0; - return (uint8_t)(readBuf[((uint8_t)a+6)]); + if (readBuf == NULL) + return 0; + return (uint8_t)(readBuf[((uint8_t)a + 6)]); } + uint16_t PS3USB::getSensor(Sensor a) { - if (readBuf == NULL) - return 0; - return ((readBuf[((uint16_t)a)-9] << 8) | readBuf[((uint16_t)a + 1)-9]); + if (readBuf == NULL) + return 0; + return ((readBuf[((uint16_t)a) - 9] << 8) | readBuf[((uint16_t)a + 1) - 9]); } + double PS3USB::getAngle(Angle a) { - if(PS3Connected) { - double accXval; - double accYval; - double accZval; + if (PS3Connected) { + double accXval; + double accYval; + double accZval; - // Data for the Kionix KXPC4 used in the DualShock 3 - const double zeroG = 511.5; // 1.65/3.3*1023 (1,65V) - accXval = -((double)getSensor(aX)-zeroG); - accYval = -((double)getSensor(aY)-zeroG); - accZval = -((double)getSensor(aZ)-zeroG); + // Data for the Kionix KXPC4 used in the DualShock 3 + const double zeroG = 511.5; // 1.65/3.3*1023 (1,65V) + accXval = -((double)getSensor(aX) - zeroG); + accYval = -((double)getSensor(aY) - zeroG); + accZval = -((double)getSensor(aZ) - zeroG); - // Convert to 360 degrees resolution - // atan2 outputs the value of -π to π (radians) - // We are then converting it to 0 to 2π and then to degrees - if (a == Pitch) { - double angle = (atan2(accYval,accZval)+PI)*RAD_TO_DEG; - return angle; - } else { - double angle = (atan2(accXval,accZval)+PI)*RAD_TO_DEG; - return angle; - } - } else - return 0; + // Convert to 360 degrees resolution + // atan2 outputs the value of -π to π (radians) + // We are then converting it to 0 to 2π and then to degrees + if (a == Pitch) { + double angle = (atan2(accYval, accZval) + PI) * RAD_TO_DEG; + return angle; + } else { + double angle = (atan2(accXval, accZval) + PI) * RAD_TO_DEG; + return angle; + } + } else + return 0; } + bool PS3USB::getStatus(Status c) { - if (readBuf == NULL) + if (readBuf == NULL) + return false; + if (readBuf[((uint16_t)c >> 8) - 9] == ((uint8_t)c & 0xff)) + return true; return false; - if (readBuf[((uint16_t)c >> 8)-9] == ((uint8_t)c & 0xff)) - return true; - return false; } + String PS3USB::getStatusString() { - if (PS3Connected || PS3NavigationConnected) { - char statusOutput[100]; + if (PS3Connected || PS3NavigationConnected) { + char statusOutput[100]; - strcpy(statusOutput,"ConnectionStatus: "); + strcpy(statusOutput, "ConnectionStatus: "); - if (getStatus(Plugged)) strcat(statusOutput,"Plugged"); - else if (getStatus(Unplugged)) strcat(statusOutput,"Unplugged"); - else strcat(statusOutput,"Error"); + if (getStatus(Plugged)) strcat(statusOutput, "Plugged"); + else if (getStatus(Unplugged)) strcat(statusOutput, "Unplugged"); + else strcat(statusOutput, "Error"); - strcat(statusOutput," - PowerRating: "); + strcat(statusOutput, " - PowerRating: "); - if (getStatus(Charging)) strcat(statusOutput,"Charging"); - else if (getStatus(NotCharging)) strcat(statusOutput,"Not Charging"); - else if (getStatus(Shutdown)) strcat(statusOutput,"Shutdown"); - else if (getStatus(Dying)) strcat(statusOutput,"Dying"); - else if (getStatus(Low)) strcat(statusOutput,"Low"); - else if (getStatus(High)) strcat(statusOutput,"High"); - else if (getStatus(Full)) strcat(statusOutput,"Full"); - else strcat(statusOutput,"Error"); + if (getStatus(Charging)) strcat(statusOutput, "Charging"); + else if (getStatus(NotCharging)) strcat(statusOutput, "Not Charging"); + else if (getStatus(Shutdown)) strcat(statusOutput, "Shutdown"); + else if (getStatus(Dying)) strcat(statusOutput, "Dying"); + else if (getStatus(Low)) strcat(statusOutput, "Low"); + else if (getStatus(High)) strcat(statusOutput, "High"); + else if (getStatus(Full)) strcat(statusOutput, "Full"); + else strcat(statusOutput, "Error"); - strcat(statusOutput," - WirelessStatus: "); + strcat(statusOutput, " - WirelessStatus: "); - if (getStatus(CableRumble)) strcat(statusOutput,"Cable - Rumble is on"); - else if (getStatus(Cable)) strcat(statusOutput,"Cable - Rumble is off"); - else if (getStatus(BluetoothRumble)) strcat(statusOutput,"Bluetooth - Rumble is on"); - else if (getStatus(Bluetooth)) strcat(statusOutput,"Bluetooth - Rumble is off"); - else strcat(statusOutput,"Error"); + if (getStatus(CableRumble)) strcat(statusOutput, "Cable - Rumble is on"); + else if (getStatus(Cable)) strcat(statusOutput, "Cable - Rumble is off"); + else if (getStatus(BluetoothRumble)) strcat(statusOutput, "Bluetooth - Rumble is on"); + else if (getStatus(Bluetooth)) strcat(statusOutput, "Bluetooth - Rumble is off"); + else strcat(statusOutput, "Error"); - return statusOutput; - } + return statusOutput; + } } /* Playstation Sixaxis Dualshock and Navigation Controller commands */ void PS3USB::PS3_Command(uint8_t* data, uint16_t nbytes) { - //bmRequest = Host to device (0x00) | Class (0x20) | Interface (0x01) = 0x21, bRequest = Set Report (0x09), Report ID (0x01), Report Type (Output 0x02), interface (0x00), datalength, datalength, data) - pUsb->ctrlReq(bAddress,epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0x01, 0x02, 0x00, nbytes, nbytes, data, NULL); + //bmRequest = Host to device (0x00) | Class (0x20) | Interface (0x01) = 0x21, bRequest = Set Report (0x09), Report ID (0x01), Report Type (Output 0x02), interface (0x00), datalength, datalength, data) + pUsb->ctrlReq(bAddress, epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0x01, 0x02, 0x00, nbytes, nbytes, data, NULL); } + void PS3USB::setAllOff() { - for (uint8_t i = 0; i < PS3_REPORT_BUFFER_SIZE; i++) - writeBuf[i] = pgm_read_byte(&PS3_REPORT_BUFFER[i]); // Reset buffer + for (uint8_t i = 0; i < PS3_REPORT_BUFFER_SIZE; i++) + writeBuf[i] = pgm_read_byte(&PS3_REPORT_BUFFER[i]); // Reset buffer - PS3_Command(writeBuf, PS3_REPORT_BUFFER_SIZE); -} -void PS3USB::setRumbleOff() { - writeBuf[1] = 0x00; - writeBuf[2] = 0x00;//low mode off - writeBuf[3] = 0x00; - writeBuf[4] = 0x00;//high mode off - - PS3_Command(writeBuf, PS3_REPORT_BUFFER_SIZE); -} -void PS3USB::setRumbleOn(Rumble mode) { - /* Still not totally sure how it works, maybe something like this instead? - * 3 - duration_right - * 4 - power_right - * 5 - duration_left - * 6 - power_left - */ - if ((mode & 0x30) > 0) { - writeBuf[1] = 0xfe; - writeBuf[3] = 0xfe; - if (mode == RumbleHigh) { - writeBuf[2] = 0;//low mode off - writeBuf[4] = 0xff;//high mode on - } - else { - writeBuf[2] = 0xff;//low mode on - writeBuf[4] = 0;//high mode off - } PS3_Command(writeBuf, PS3_REPORT_BUFFER_SIZE); - } } + +void PS3USB::setRumbleOff() { + writeBuf[1] = 0x00; + writeBuf[2] = 0x00; //low mode off + writeBuf[3] = 0x00; + writeBuf[4] = 0x00; //high mode off + + PS3_Command(writeBuf, PS3_REPORT_BUFFER_SIZE); +} + +void PS3USB::setRumbleOn(Rumble mode) { + /* Still not totally sure how it works, maybe something like this instead? + * 3 - duration_right + * 4 - power_right + * 5 - duration_left + * 6 - power_left + */ + if ((mode & 0x30) > 0) { + writeBuf[1] = 0xfe; + writeBuf[3] = 0xfe; + if (mode == RumbleHigh) { + writeBuf[2] = 0; //low mode off + writeBuf[4] = 0xff; //high mode on + } else { + writeBuf[2] = 0xff; //low mode on + writeBuf[4] = 0; //high mode off + } + PS3_Command(writeBuf, PS3_REPORT_BUFFER_SIZE); + } +} + void PS3USB::setLedOff(LED a) { - writeBuf[9] &= ~((uint8_t)((pgm_read_byte(&LEDS[(uint8_t)a]) & 0x0f) << 1)); - PS3_Command(writeBuf, PS3_REPORT_BUFFER_SIZE); + writeBuf[9] &= ~((uint8_t)((pgm_read_byte(&LEDS[(uint8_t)a]) & 0x0f) << 1)); + PS3_Command(writeBuf, PS3_REPORT_BUFFER_SIZE); } + void PS3USB::setLedOn(LED a) { - writeBuf[9] |= (uint8_t)((pgm_read_byte(&LEDS[(uint8_t)a]) & 0x0f) << 1); - PS3_Command(writeBuf, PS3_REPORT_BUFFER_SIZE); + writeBuf[9] |= (uint8_t)((pgm_read_byte(&LEDS[(uint8_t)a]) & 0x0f) << 1); + PS3_Command(writeBuf, PS3_REPORT_BUFFER_SIZE); } + void PS3USB::setLedToggle(LED a) { - writeBuf[9] ^= (uint8_t)((pgm_read_byte(&LEDS[(uint8_t)a]) & 0x0f) << 1); - PS3_Command(writeBuf, PS3_REPORT_BUFFER_SIZE); + writeBuf[9] ^= (uint8_t)((pgm_read_byte(&LEDS[(uint8_t)a]) & 0x0f) << 1); + PS3_Command(writeBuf, PS3_REPORT_BUFFER_SIZE); } + void PS3USB::setBdaddr(uint8_t* BDADDR) { - /* Set the internal bluetooth address */ - uint8_t buf[8]; - buf[0] = 0x01; - buf[1] = 0x00; - for (uint8_t i = 0; i < 6; i++) - buf[i+2] = BDADDR[5 - i];//Copy into buffer, has to be written reversed + /* Set the internal bluetooth address */ + uint8_t buf[8]; + buf[0] = 0x01; + buf[1] = 0x00; + for (uint8_t i = 0; i < 6; i++) + buf[i + 2] = BDADDR[5 - i]; //Copy into buffer, has to be written reversed - //bmRequest = Host to device (0x00) | Class (0x20) | Interface (0x01) = 0x21, bRequest = Set Report (0x09), Report ID (0xF5), Report Type (Feature 0x03), interface (0x00), datalength, datalength, data) - pUsb->ctrlReq(bAddress,epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0xF5, 0x03, 0x00, 8, 8, buf, NULL); + //bmRequest = Host to device (0x00) | Class (0x20) | Interface (0x01) = 0x21, bRequest = Set Report (0x09), Report ID (0xF5), Report Type (Feature 0x03), interface (0x00), datalength, datalength, data) + pUsb->ctrlReq(bAddress, epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0xF5, 0x03, 0x00, 8, 8, buf, NULL); #ifdef DEBUG - Notify(PSTR("\r\nBluetooth Address was set to: "), 0x80); - for(int8_t i = 5; i > 0; i--) { - PrintHex(my_bdaddr[i], 0x80); - Serial.print(":"); - } - PrintHex(my_bdaddr[0], 0x80); + Notify(PSTR("\r\nBluetooth Address was set to: "), 0x80); + for (int8_t i = 5; i > 0; i--) { + PrintHex (my_bdaddr[i], 0x80); + Serial.print(":"); + } + PrintHex (my_bdaddr[0], 0x80); #endif - return; + return; } -void PS3USB::enable_sixaxis() { //Command used to enable the Dualshock 3 and Navigation controller to send data via USB - uint8_t cmd_buf[4]; - cmd_buf[0] = 0x42;// Special PS3 Controller enable commands - cmd_buf[1] = 0x0c; - cmd_buf[2] = 0x00; - cmd_buf[3] = 0x00; - //bmRequest = Host to device (0x00) | Class (0x20) | Interface (0x01) = 0x21, bRequest = Set Report (0x09), Report ID (0xF4), Report Type (Feature 0x03), interface (0x00), datalength, datalength, data) - pUsb->ctrlReq(bAddress,epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0xF4, 0x03, 0x00, 4, 4, cmd_buf, NULL); +void PS3USB::enable_sixaxis() { //Command used to enable the Dualshock 3 and Navigation controller to send data via USB + uint8_t cmd_buf[4]; + cmd_buf[0] = 0x42; // Special PS3 Controller enable commands + cmd_buf[1] = 0x0c; + cmd_buf[2] = 0x00; + cmd_buf[3] = 0x00; + + //bmRequest = Host to device (0x00) | Class (0x20) | Interface (0x01) = 0x21, bRequest = Set Report (0x09), Report ID (0xF4), Report Type (Feature 0x03), interface (0x00), datalength, datalength, data) + pUsb->ctrlReq(bAddress, epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0xF4, 0x03, 0x00, 4, 4, cmd_buf, NULL); } /* Playstation Move Controller commands */ void PS3USB::Move_Command(uint8_t* data, uint16_t nbytes) { - pUsb->outTransfer(bAddress, epInfo[ PS3_OUTPUT_PIPE ].epAddr, nbytes, data); + pUsb->outTransfer(bAddress, epInfo[ PS3_OUTPUT_PIPE ].epAddr, nbytes, data); } void PS3USB::moveSetBulb(uint8_t r, uint8_t g, uint8_t b) { //Use this to set the Color using RGB values - // set the Bulb's values into the write buffer - writeBuf[2] = r; - writeBuf[3] = g; - writeBuf[4] = b; + // set the Bulb's values into the write buffer + writeBuf[2] = r; + writeBuf[3] = g; + writeBuf[4] = b; - Move_Command(writeBuf, MOVE_REPORT_BUFFER_SIZE); + Move_Command(writeBuf, MOVE_REPORT_BUFFER_SIZE); } + void PS3USB::moveSetBulb(Colors color) { //Use this to set the Color using the predefined colors in "enums.h" - moveSetBulb((uint8_t)(color >> 16),(uint8_t)(color >> 8),(uint8_t)(color)); + moveSetBulb((uint8_t)(color >> 16), (uint8_t)(color >> 8), (uint8_t)(color)); } + void PS3USB::moveSetRumble(uint8_t rumble) { #ifdef DEBUG - if(rumble < 64 && rumble != 0) // The rumble value has to at least 64, or approximately 25% (64/255*100) - Notify(PSTR("\r\nThe rumble value has to at least 64, or approximately 25%"), 0x80); + if (rumble < 64 && rumble != 0) // The rumble value has to at least 64, or approximately 25% (64/255*100) + Notify(PSTR("\r\nThe rumble value has to at least 64, or approximately 25%"), 0x80); #endif - //set the rumble value into the write buffer - writeBuf[6] = rumble; + //set the rumble value into the write buffer + writeBuf[6] = rumble; - Move_Command(writeBuf, MOVE_REPORT_BUFFER_SIZE); + Move_Command(writeBuf, MOVE_REPORT_BUFFER_SIZE); } + void PS3USB::setMoveBdaddr(uint8_t* BDADDR) { - /* Set the internal bluetooth address */ - uint8_t buf[11]; - buf[0] = 0x05; - buf[7] = 0x10; - buf[8] = 0x01; - buf[9] = 0x02; - buf[10] = 0x12; + /* Set the internal bluetooth address */ + uint8_t buf[11]; + buf[0] = 0x05; + buf[7] = 0x10; + buf[8] = 0x01; + buf[9] = 0x02; + buf[10] = 0x12; - for (uint8_t i = 0; i < 6; i++) - buf[i + 1] = BDADDR[i]; + for (uint8_t i = 0; i < 6; i++) + buf[i + 1] = BDADDR[i]; - //bmRequest = Host to device (0x00) | Class (0x20) | Interface (0x01) = 0x21, bRequest = Set Report (0x09), Report ID (0x05), Report Type (Feature 0x03), interface (0x00), datalength, datalength, data) - pUsb->ctrlReq(bAddress,epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0x05, 0x03, 0x00,11,11, buf, NULL); + //bmRequest = Host to device (0x00) | Class (0x20) | Interface (0x01) = 0x21, bRequest = Set Report (0x09), Report ID (0x05), Report Type (Feature 0x03), interface (0x00), datalength, datalength, data) + pUsb->ctrlReq(bAddress, epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0x05, 0x03, 0x00, 11, 11, buf, NULL); #ifdef DEBUG - Notify(PSTR("\r\nBluetooth Address was set to: "), 0x80); - for(int8_t i = 5; i > 0; i--) { - PrintHex(my_bdaddr[i], 0x80); - Serial.print(":"); - } - PrintHex(my_bdaddr[0], 0x80); + Notify(PSTR("\r\nBluetooth Address was set to: "), 0x80); + for (int8_t i = 5; i > 0; i--) { + PrintHex (my_bdaddr[i], 0x80); + Serial.print(":"); + } + PrintHex (my_bdaddr[0], 0x80); #endif - return; + return; } \ No newline at end of file diff --git a/PS3USB.h b/PS3USB.h index b313b05e..adaa47e1 100644 --- a/PS3USB.h +++ b/PS3USB.h @@ -1,15 +1,15 @@ /* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved. - + This software may be distributed and modified under the terms of the GNU General Public License version 2 (GPL2) as published by the Free Software Foundation and appearing in the file GPL2.TXT included in the packaging of this file. Please note that GPL2 Section 2[b] requires that all works based on this software must also be made publicly available under the terms of the GPL2 ("Copyleft"). - + Contact information ------------------- - + Kristian Lauszus, TKJ Electronics Web : http://www.tkjelectronics.com e-mail : kristianl@tkjelectronics.com @@ -56,193 +56,199 @@ /** * This class implements support for all the official PS3 Controllers: * Dualshock 3, Navigation or a Motion controller via USB. - * + * * One can only set the color of the bulb, set the rumble, set and get the bluetooth address and calibrate the magnetometer via USB on the Move controller. - * + * * Information about the protocol can be found at the wiki: https://github.com/felis/USB_Host_Shield_2.0/wiki/PS3-Information. */ class PS3USB : public USBDeviceConfig { public: - /** - * Constructor for the PS3USB class. - * @param pUsb Pointer to USB class instance. - * @param btadr5,btadr4,btadr3,btadr2,btadr1,btadr0 - * Pass your dongles Bluetooth address into the constructor, - * so you are able to pair the controller with a Bluetooth dongle. - */ - PS3USB(USB *pUsb, uint8_t btadr5=0, uint8_t btadr4=0, uint8_t btadr3=0, uint8_t btadr2=0, uint8_t btadr1=0, uint8_t btadr0=0); - - /** @name USBDeviceConfig implementation */ - /** - * Initialize the PS3 Controller. - * @param parent Hub number. - * @param port Port number on the hub. - * @param lowspeed Speed of the device. - * @return 0 on success. - */ - virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed); - /** - * Release the USB device. - * @return 0 on success. - */ - virtual uint8_t Release(); - /** - * Poll the USB Input endpoins and run the state machines. - * @return 0 on success. - */ - virtual uint8_t Poll(); - /** - * Get the device address. - * @return The device address. - */ - virtual uint8_t GetAddress() { return bAddress; }; - /** - * Used to check if the controller has been initialized. - * @return True if it's ready. - */ - virtual bool isReady() { return bPollEnable; }; - /**@}*/ + /** + * Constructor for the PS3USB class. + * @param pUsb Pointer to USB class instance. + * @param btadr5,btadr4,btadr3,btadr2,btadr1,btadr0 + * Pass your dongles Bluetooth address into the constructor, + * so you are able to pair the controller with a Bluetooth dongle. + */ + PS3USB(USB *pUsb, uint8_t btadr5 = 0, uint8_t btadr4 = 0, uint8_t btadr3 = 0, uint8_t btadr2 = 0, uint8_t btadr1 = 0, uint8_t btadr0 = 0); - /** - * Used to set the Bluetooth address inside the Dualshock 3 and Navigation controller. - * @param BDADDR Your dongles Bluetooth address. - */ - void setBdaddr(uint8_t* BDADDR); - /** - * Used to set the Bluetooth address inside the Move controller. - * @param BDADDR Your dongles Bluetooth address. - */ - void setMoveBdaddr(uint8_t* BDADDR); + /** @name USBDeviceConfig implementation */ + /** + * Initialize the PS3 Controller. + * @param parent Hub number. + * @param port Port number on the hub. + * @param lowspeed Speed of the device. + * @return 0 on success. + */ + virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed); + /** + * Release the USB device. + * @return 0 on success. + */ + virtual uint8_t Release(); + /** + * Poll the USB Input endpoins and run the state machines. + * @return 0 on success. + */ + virtual uint8_t Poll(); - /** @name PS3 Controller functions */ - /** - * getButtonPress(Button b) will return true as long as the button is held down. - * - * While getButtonClick(Button b) will only return it once. - * - * So you instance if you need to increase a variable once you would use getButtonClick(Button b), - * but if you need to drive a robot forward you would use getButtonPress(Button b). - */ - bool getButtonPress(Button b); - bool getButtonClick(Button b); - /**@}*/ - /** @name PS3 Controller functions */ - /** - * Used to get the analog value from button presses. - * @param a The ::Button to read. - * The supported buttons are: - * ::UP, ::RIGHT, ::DOWN, ::LEFT, ::L1, ::L2, ::R1, ::R2, - * ::TRIANGLE, ::CIRCLE, ::CROSS, ::SQUARE, and ::T. - * @return Analog value in the range of 0-255. - */ - uint8_t getAnalogButton(Button a); - /** - * Used to read the analog joystick. - * @param a ::LeftHatX, ::LeftHatY, ::RightHatX, and ::RightHatY. - * @return Return the analog value in the range of 0-255. - */ - uint8_t getAnalogHat(AnalogHat a); - /** - * Used to read the sensors inside the Dualshock 3 controller. - * @param a - * The Dualshock 3 has a 3-axis accelerometer and a 1-axis gyro inside. - * @return Return the raw sensor value. - */ - uint16_t getSensor(Sensor a); - /** - * Use this to get ::Pitch and ::Roll calculated using the accelerometer. - * @param a Either ::Pitch or ::Roll. - * @return Return the angle in the range of 0-360. - */ - double getAngle(Angle a); - /** - * Get the ::Status from the controller. - * @param c The ::Status you want to read. - * @return True if correct and false if not. - */ - bool getStatus(Status c); - /** - * Read all the available ::Status from the controller. - * @return One large string with all the information. - */ - String getStatusString(); + /** + * Get the device address. + * @return The device address. + */ + virtual uint8_t GetAddress() { + return bAddress; + }; - /** Used to set all LEDs and ::Rumble off. */ - void setAllOff(); - /** Turn off ::Rumble. */ - void setRumbleOff(); - /** - * Turn on ::Rumble. - * @param mode Either ::RumbleHigh or ::RumbleLow. - */ - void setRumbleOn(Rumble mode); - /** - * Turn the specific ::LED off. - * @param a The ::LED to turn off. - */ - void setLedOff(LED a); - /** - * Turn the specific ::LED on. - * @param a The ::LED to turn on. - */ - void setLedOn(LED a); - /** - * Toggle the specific ::LED. - * @param a The ::LED to toggle. - */ - void setLedToggle(LED a); - - /** - * Use this to set the Color using RGB values. - * @param r,g,b RGB value. - */ - void moveSetBulb(uint8_t r, uint8_t g, uint8_t b); - /** - * Use this to set the color using the predefined colors in ::Colors. - * @param color The desired color. - */ - void moveSetBulb(Colors color); - /** - * Set the rumble value inside the Move controller. - * @param rumble The desired value in the range from 64-255. - */ - void moveSetRumble(uint8_t rumble); - /**@}*/ + /** + * Used to check if the controller has been initialized. + * @return True if it's ready. + */ + virtual bool isReady() { + return bPollEnable; + }; + /**@}*/ - /** Variable used to indicate if the normal playstation controller is successfully connected. */ - bool PS3Connected; - /** Variable used to indicate if the move controller is successfully connected. */ - bool PS3MoveConnected; - /** Variable used to indicate if the navigation controller is successfully connected. */ - bool PS3NavigationConnected; - -protected: - /** Pointer to USB class instance. */ - USB *pUsb; - /** Device address. */ - uint8_t bAddress; - /** Endpoint info structure. */ - EpInfo epInfo[PS3_MAX_ENDPOINTS]; - -private: - bool bPollEnable; - - uint32_t timer; // used to continuously set PS3 Move controller Bulb and rumble values + /** + * Used to set the Bluetooth address inside the Dualshock 3 and Navigation controller. + * @param BDADDR Your dongles Bluetooth address. + */ + void setBdaddr(uint8_t* BDADDR); + /** + * Used to set the Bluetooth address inside the Move controller. + * @param BDADDR Your dongles Bluetooth address. + */ + void setMoveBdaddr(uint8_t* BDADDR); - uint32_t ButtonState; - uint32_t OldButtonState; - uint32_t ButtonClickState; - - uint8_t my_bdaddr[6]; // Change to your dongles Bluetooth address in the constructor - uint8_t readBuf[EP_MAXPKTSIZE]; // General purpose buffer for input data - uint8_t writeBuf[EP_MAXPKTSIZE]; // General purpose buffer for output data - - void readReport(); // read incoming data - void printReport(); // print incoming date - Uncomment for debugging + /** @name PS3 Controller functions */ + /** + * getButtonPress(Button b) will return true as long as the button is held down. + * + * While getButtonClick(Button b) will only return it once. + * + * So you instance if you need to increase a variable once you would use getButtonClick(Button b), + * but if you need to drive a robot forward you would use getButtonPress(Button b). + */ + bool getButtonPress(Button b); + bool getButtonClick(Button b); + /**@}*/ + /** @name PS3 Controller functions */ + /** + * Used to get the analog value from button presses. + * @param a The ::Button to read. + * The supported buttons are: + * ::UP, ::RIGHT, ::DOWN, ::LEFT, ::L1, ::L2, ::R1, ::R2, + * ::TRIANGLE, ::CIRCLE, ::CROSS, ::SQUARE, and ::T. + * @return Analog value in the range of 0-255. + */ + uint8_t getAnalogButton(Button a); + /** + * Used to read the analog joystick. + * @param a ::LeftHatX, ::LeftHatY, ::RightHatX, and ::RightHatY. + * @return Return the analog value in the range of 0-255. + */ + uint8_t getAnalogHat(AnalogHat a); + /** + * Used to read the sensors inside the Dualshock 3 controller. + * @param a + * The Dualshock 3 has a 3-axis accelerometer and a 1-axis gyro inside. + * @return Return the raw sensor value. + */ + uint16_t getSensor(Sensor a); + /** + * Use this to get ::Pitch and ::Roll calculated using the accelerometer. + * @param a Either ::Pitch or ::Roll. + * @return Return the angle in the range of 0-360. + */ + double getAngle(Angle a); + /** + * Get the ::Status from the controller. + * @param c The ::Status you want to read. + * @return True if correct and false if not. + */ + bool getStatus(Status c); + /** + * Read all the available ::Status from the controller. + * @return One large string with all the information. + */ + String getStatusString(); - /* Private commands */ - void PS3_Command(uint8_t* data, uint16_t nbytes); - void enable_sixaxis(); // Command used to enable the Dualshock 3 and Navigation controller to send data via USB - void Move_Command(uint8_t* data, uint16_t nbytes); + /** Used to set all LEDs and ::Rumble off. */ + void setAllOff(); + /** Turn off ::Rumble. */ + void setRumbleOff(); + /** + * Turn on ::Rumble. + * @param mode Either ::RumbleHigh or ::RumbleLow. + */ + void setRumbleOn(Rumble mode); + /** + * Turn the specific ::LED off. + * @param a The ::LED to turn off. + */ + void setLedOff(LED a); + /** + * Turn the specific ::LED on. + * @param a The ::LED to turn on. + */ + void setLedOn(LED a); + /** + * Toggle the specific ::LED. + * @param a The ::LED to toggle. + */ + void setLedToggle(LED a); + + /** + * Use this to set the Color using RGB values. + * @param r,g,b RGB value. + */ + void moveSetBulb(uint8_t r, uint8_t g, uint8_t b); + /** + * Use this to set the color using the predefined colors in ::Colors. + * @param color The desired color. + */ + void moveSetBulb(Colors color); + /** + * Set the rumble value inside the Move controller. + * @param rumble The desired value in the range from 64-255. + */ + void moveSetRumble(uint8_t rumble); + /**@}*/ + + /** Variable used to indicate if the normal playstation controller is successfully connected. */ + bool PS3Connected; + /** Variable used to indicate if the move controller is successfully connected. */ + bool PS3MoveConnected; + /** Variable used to indicate if the navigation controller is successfully connected. */ + bool PS3NavigationConnected; + +protected: + /** Pointer to USB class instance. */ + USB *pUsb; + /** Device address. */ + uint8_t bAddress; + /** Endpoint info structure. */ + EpInfo epInfo[PS3_MAX_ENDPOINTS]; + +private: + bool bPollEnable; + + uint32_t timer; // used to continuously set PS3 Move controller Bulb and rumble values + + uint32_t ButtonState; + uint32_t OldButtonState; + uint32_t ButtonClickState; + + uint8_t my_bdaddr[6]; // Change to your dongles Bluetooth address in the constructor + uint8_t readBuf[EP_MAXPKTSIZE]; // General purpose buffer for input data + uint8_t writeBuf[EP_MAXPKTSIZE]; // General purpose buffer for output data + + void readReport(); // read incoming data + void printReport(); // print incoming date - Uncomment for debugging + + /* Private commands */ + void PS3_Command(uint8_t* data, uint16_t nbytes); + void enable_sixaxis(); // Command used to enable the Dualshock 3 and Navigation controller to send data via USB + void Move_Command(uint8_t* data, uint16_t nbytes); }; #endif diff --git a/SPP.cpp b/SPP.cpp index 538d2193..8455d974 100644 --- a/SPP.cpp +++ b/SPP.cpp @@ -23,889 +23,914 @@ /* * CRC (reversed crc) lookup table as calculated by the table generator in ETSI TS 101 369 V6.3.0. */ -const uint8_t rfcomm_crc_table[256] PROGMEM = { /* reversed, 8-bit, poly=0x07 */ - 0x00, 0x91, 0xE3, 0x72, 0x07, 0x96, 0xE4, 0x75, 0x0E, 0x9F, 0xED, 0x7C, 0x09, 0x98, 0xEA, 0x7B, - 0x1C, 0x8D, 0xFF, 0x6E, 0x1B, 0x8A, 0xF8, 0x69, 0x12, 0x83, 0xF1, 0x60, 0x15, 0x84, 0xF6, 0x67, - 0x38, 0xA9, 0xDB, 0x4A, 0x3F, 0xAE, 0xDC, 0x4D, 0x36, 0xA7, 0xD5, 0x44, 0x31, 0xA0, 0xD2, 0x43, - 0x24, 0xB5, 0xC7, 0x56, 0x23, 0xB2, 0xC0, 0x51, 0x2A, 0xBB, 0xC9, 0x58, 0x2D, 0xBC, 0xCE, 0x5F, - 0x70, 0xE1, 0x93, 0x02, 0x77, 0xE6, 0x94, 0x05, 0x7E, 0xEF, 0x9D, 0x0C, 0x79, 0xE8, 0x9A, 0x0B, - 0x6C, 0xFD, 0x8F, 0x1E, 0x6B, 0xFA, 0x88, 0x19, 0x62, 0xF3, 0x81, 0x10, 0x65, 0xF4, 0x86, 0x17, - 0x48, 0xD9, 0xAB, 0x3A, 0x4F, 0xDE, 0xAC, 0x3D, 0x46, 0xD7, 0xA5, 0x34, 0x41, 0xD0, 0xA2, 0x33, - 0x54, 0xC5, 0xB7, 0x26, 0x53, 0xC2, 0xB0, 0x21, 0x5A, 0xCB, 0xB9, 0x28, 0x5D, 0xCC, 0xBE, 0x2F, - 0xE0, 0x71, 0x03, 0x92, 0xE7, 0x76, 0x04, 0x95, 0xEE, 0x7F, 0x0D, 0x9C, 0xE9, 0x78, 0x0A, 0x9B, - 0xFC, 0x6D, 0x1F, 0x8E, 0xFB, 0x6A, 0x18, 0x89, 0xF2, 0x63, 0x11, 0x80, 0xF5, 0x64, 0x16, 0x87, - 0xD8, 0x49, 0x3B, 0xAA, 0xDF, 0x4E, 0x3C, 0xAD, 0xD6, 0x47, 0x35, 0xA4, 0xD1, 0x40, 0x32, 0xA3, - 0xC4, 0x55, 0x27, 0xB6, 0xC3, 0x52, 0x20, 0xB1, 0xCA, 0x5B, 0x29, 0xB8, 0xCD, 0x5C, 0x2E, 0xBF, - 0x90, 0x01, 0x73, 0xE2, 0x97, 0x06, 0x74, 0xE5, 0x9E, 0x0F, 0x7D, 0xEC, 0x99, 0x08, 0x7A, 0xEB, - 0x8C, 0x1D, 0x6F, 0xFE, 0x8B, 0x1A, 0x68, 0xF9, 0x82, 0x13, 0x61, 0xF0, 0x85, 0x14, 0x66, 0xF7, - 0xA8, 0x39, 0x4B, 0xDA, 0xAF, 0x3E, 0x4C, 0xDD, 0xA6, 0x37, 0x45, 0xD4, 0xA1, 0x30, 0x42, 0xD3, - 0xB4, 0x25, 0x57, 0xC6, 0xB3, 0x22, 0x50, 0xC1, 0xBA, 0x2B, 0x59, 0xC8, 0xBD, 0x2C, 0x5E, 0xCF +const uint8_t rfcomm_crc_table[256] PROGMEM = {/* reversed, 8-bit, poly=0x07 */ + 0x00, 0x91, 0xE3, 0x72, 0x07, 0x96, 0xE4, 0x75, 0x0E, 0x9F, 0xED, 0x7C, 0x09, 0x98, 0xEA, 0x7B, + 0x1C, 0x8D, 0xFF, 0x6E, 0x1B, 0x8A, 0xF8, 0x69, 0x12, 0x83, 0xF1, 0x60, 0x15, 0x84, 0xF6, 0x67, + 0x38, 0xA9, 0xDB, 0x4A, 0x3F, 0xAE, 0xDC, 0x4D, 0x36, 0xA7, 0xD5, 0x44, 0x31, 0xA0, 0xD2, 0x43, + 0x24, 0xB5, 0xC7, 0x56, 0x23, 0xB2, 0xC0, 0x51, 0x2A, 0xBB, 0xC9, 0x58, 0x2D, 0xBC, 0xCE, 0x5F, + 0x70, 0xE1, 0x93, 0x02, 0x77, 0xE6, 0x94, 0x05, 0x7E, 0xEF, 0x9D, 0x0C, 0x79, 0xE8, 0x9A, 0x0B, + 0x6C, 0xFD, 0x8F, 0x1E, 0x6B, 0xFA, 0x88, 0x19, 0x62, 0xF3, 0x81, 0x10, 0x65, 0xF4, 0x86, 0x17, + 0x48, 0xD9, 0xAB, 0x3A, 0x4F, 0xDE, 0xAC, 0x3D, 0x46, 0xD7, 0xA5, 0x34, 0x41, 0xD0, 0xA2, 0x33, + 0x54, 0xC5, 0xB7, 0x26, 0x53, 0xC2, 0xB0, 0x21, 0x5A, 0xCB, 0xB9, 0x28, 0x5D, 0xCC, 0xBE, 0x2F, + 0xE0, 0x71, 0x03, 0x92, 0xE7, 0x76, 0x04, 0x95, 0xEE, 0x7F, 0x0D, 0x9C, 0xE9, 0x78, 0x0A, 0x9B, + 0xFC, 0x6D, 0x1F, 0x8E, 0xFB, 0x6A, 0x18, 0x89, 0xF2, 0x63, 0x11, 0x80, 0xF5, 0x64, 0x16, 0x87, + 0xD8, 0x49, 0x3B, 0xAA, 0xDF, 0x4E, 0x3C, 0xAD, 0xD6, 0x47, 0x35, 0xA4, 0xD1, 0x40, 0x32, 0xA3, + 0xC4, 0x55, 0x27, 0xB6, 0xC3, 0x52, 0x20, 0xB1, 0xCA, 0x5B, 0x29, 0xB8, 0xCD, 0x5C, 0x2E, 0xBF, + 0x90, 0x01, 0x73, 0xE2, 0x97, 0x06, 0x74, 0xE5, 0x9E, 0x0F, 0x7D, 0xEC, 0x99, 0x08, 0x7A, 0xEB, + 0x8C, 0x1D, 0x6F, 0xFE, 0x8B, 0x1A, 0x68, 0xF9, 0x82, 0x13, 0x61, 0xF0, 0x85, 0x14, 0x66, 0xF7, + 0xA8, 0x39, 0x4B, 0xDA, 0xAF, 0x3E, 0x4C, 0xDD, 0xA6, 0x37, 0x45, 0xD4, 0xA1, 0x30, 0x42, 0xD3, + 0xB4, 0x25, 0x57, 0xC6, 0xB3, 0x22, 0x50, 0xC1, 0xBA, 0x2B, 0x59, 0xC8, 0xBD, 0x2C, 0x5E, 0xCF }; -SPP::SPP(BTD *p, const char* name, const char* pin): +SPP::SPP(BTD *p, const char* name, const char* pin) : pBtd(p) // Pointer to BTD class instance - mandatory { - if (pBtd) - pBtd->registerServiceClass(this); // Register it as a Bluetooth service + if (pBtd) + pBtd->registerServiceClass(this); // Register it as a Bluetooth service - pBtd->btdName = name; - pBtd->btdPin = pin; + pBtd->btdName = name; + pBtd->btdPin = pin; - /* Set device cid for the SDP and RFCOMM channelse */ - sdp_dcid[0] = 0x50; // 0x0050 - sdp_dcid[1] = 0x00; - rfcomm_dcid[0] = 0x51; // 0x0051 - rfcomm_dcid[1] = 0x00; + /* Set device cid for the SDP and RFCOMM channelse */ + sdp_dcid[0] = 0x50; // 0x0050 + sdp_dcid[1] = 0x00; + rfcomm_dcid[0] = 0x51; // 0x0051 + rfcomm_dcid[1] = 0x00; - Reset(); + Reset(); } + void SPP::Reset() { - connected = false; - RFCOMMConnected = false; - SDPConnected = false; - l2cap_sdp_state = L2CAP_SDP_WAIT; - l2cap_rfcomm_state = L2CAP_RFCOMM_WAIT; - l2cap_event_flag = 0; + connected = false; + RFCOMMConnected = false; + SDPConnected = false; + l2cap_sdp_state = L2CAP_SDP_WAIT; + l2cap_rfcomm_state = L2CAP_RFCOMM_WAIT; + l2cap_event_flag = 0; } -void SPP::disconnect(){ - connected = false; - // First the two L2CAP channels has to be disconencted and then the HCI connection - if(RFCOMMConnected) - pBtd->l2cap_disconnection_request(hci_handle,0x0A, rfcomm_scid, rfcomm_dcid); - if(RFCOMMConnected && SDPConnected) - delay(1); // Add delay between commands - if(SDPConnected) - pBtd->l2cap_disconnection_request(hci_handle,0x0B, sdp_scid, sdp_dcid); - l2cap_sdp_state = L2CAP_DISCONNECT_RESPONSE; + +void SPP::disconnect() { + connected = false; + // First the two L2CAP channels has to be disconencted and then the HCI connection + if (RFCOMMConnected) + pBtd->l2cap_disconnection_request(hci_handle, 0x0A, rfcomm_scid, rfcomm_dcid); + if (RFCOMMConnected && SDPConnected) + delay(1); // Add delay between commands + if (SDPConnected) + pBtd->l2cap_disconnection_request(hci_handle, 0x0B, sdp_scid, sdp_dcid); + l2cap_sdp_state = L2CAP_DISCONNECT_RESPONSE; } + void SPP::ACLData(uint8_t* l2capinbuf) { - if(!connected) { - if (l2capinbuf[8] == L2CAP_CMD_CONNECTION_REQUEST) { - if((l2capinbuf[12] | (l2capinbuf[13] << 8)) == SDP_PSM && !pBtd->sdpConnectionClaimed) { - pBtd->sdpConnectionClaimed = true; - hci_handle = pBtd->hci_handle; // Store the HCI Handle for the connection - l2cap_sdp_state = L2CAP_SDP_WAIT; // Reset state - } else if((l2capinbuf[12] | (l2capinbuf[13] << 8)) == RFCOMM_PSM && !pBtd->rfcommConnectionClaimed) { - pBtd->rfcommConnectionClaimed = true; - hci_handle = pBtd->hci_handle; // Store the HCI Handle for the connection - l2cap_rfcomm_state = L2CAP_RFCOMM_WAIT; // Reset state - } + if (!connected) { + if (l2capinbuf[8] == L2CAP_CMD_CONNECTION_REQUEST) { + if ((l2capinbuf[12] | (l2capinbuf[13] << 8)) == SDP_PSM && !pBtd->sdpConnectionClaimed) { + pBtd->sdpConnectionClaimed = true; + hci_handle = pBtd->hci_handle; // Store the HCI Handle for the connection + l2cap_sdp_state = L2CAP_SDP_WAIT; // Reset state + } else if ((l2capinbuf[12] | (l2capinbuf[13] << 8)) == RFCOMM_PSM && !pBtd->rfcommConnectionClaimed) { + pBtd->rfcommConnectionClaimed = true; + hci_handle = pBtd->hci_handle; // Store the HCI Handle for the connection + l2cap_rfcomm_state = L2CAP_RFCOMM_WAIT; // Reset state + } + } } - } - if (((l2capinbuf[0] | (l2capinbuf[1] << 8)) == (hci_handle | 0x2000))) { // acl_handle_ok - if ((l2capinbuf[6] | (l2capinbuf[7] << 8)) == 0x0001) { //l2cap_control - Channel ID for ACL-U - if (l2capinbuf[8] == L2CAP_CMD_COMMAND_REJECT) { + if (((l2capinbuf[0] | (l2capinbuf[1] << 8)) == (hci_handle | 0x2000))) { // acl_handle_ok + if ((l2capinbuf[6] | (l2capinbuf[7] << 8)) == 0x0001) { //l2cap_control - Channel ID for ACL-U + if (l2capinbuf[8] == L2CAP_CMD_COMMAND_REJECT) { #ifdef DEBUG - Notify(PSTR("\r\nL2CAP Command Rejected - Reason: "), 0x80); - PrintHex(l2capinbuf[13], 0x80); - Notify(PSTR(" "), 0x80); - PrintHex(l2capinbuf[12], 0x80); - Notify(PSTR(" Data: "), 0x80); - PrintHex(l2capinbuf[17], 0x80); - Notify(PSTR(" "), 0x80); - PrintHex(l2capinbuf[16], 0x80); - Notify(PSTR(" "), 0x80); - PrintHex(l2capinbuf[15], 0x80); - Notify(PSTR(" "), 0x80); - PrintHex(l2capinbuf[14], 0x80); + Notify(PSTR("\r\nL2CAP Command Rejected - Reason: "), 0x80); + PrintHex (l2capinbuf[13], 0x80); + Notify(PSTR(" "), 0x80); + PrintHex (l2capinbuf[12], 0x80); + Notify(PSTR(" Data: "), 0x80); + PrintHex (l2capinbuf[17], 0x80); + Notify(PSTR(" "), 0x80); + PrintHex (l2capinbuf[16], 0x80); + Notify(PSTR(" "), 0x80); + PrintHex (l2capinbuf[15], 0x80); + Notify(PSTR(" "), 0x80); + PrintHex (l2capinbuf[14], 0x80); #endif - } else if (l2capinbuf[8] == L2CAP_CMD_CONNECTION_REQUEST) { + } else if (l2capinbuf[8] == L2CAP_CMD_CONNECTION_REQUEST) { #ifdef EXTRADEBUG - Notify(PSTR("\r\nL2CAP Connection Request - PSM: "), 0x80); - PrintHex(l2capinbuf[13], 0x80); - Notify(PSTR(" "), 0x80); - PrintHex(l2capinbuf[12], 0x80); - Notify(PSTR(" SCID: "), 0x80); - PrintHex(l2capinbuf[15], 0x80); - Notify(PSTR(" "), 0x80); - PrintHex(l2capinbuf[14], 0x80); - Notify(PSTR(" Identifier: "), 0x80); - PrintHex(l2capinbuf[9], 0x80); + Notify(PSTR("\r\nL2CAP Connection Request - PSM: "), 0x80); + PrintHex (l2capinbuf[13], 0x80); + Notify(PSTR(" "), 0x80); + PrintHex (l2capinbuf[12], 0x80); + Notify(PSTR(" SCID: "), 0x80); + PrintHex (l2capinbuf[15], 0x80); + Notify(PSTR(" "), 0x80); + PrintHex (l2capinbuf[14], 0x80); + Notify(PSTR(" Identifier: "), 0x80); + PrintHex (l2capinbuf[9], 0x80); #endif - if ((l2capinbuf[12] | (l2capinbuf[13] << 8)) == SDP_PSM) { // It doesn't matter if it receives another reqeust, since it waits for the channel to disconnect in the L2CAP_SDP_DONE state, and the l2cap_event_flag will be cleared if so - identifier = l2capinbuf[9]; - sdp_scid[0] = l2capinbuf[14]; - sdp_scid[1] = l2capinbuf[15]; - l2cap_event_flag |= L2CAP_FLAG_CONNECTION_SDP_REQUEST; - } else if ((l2capinbuf[12] | (l2capinbuf[13] << 8)) == RFCOMM_PSM) { // ----- || ----- - identifier = l2capinbuf[9]; - rfcomm_scid[0] = l2capinbuf[14]; - rfcomm_scid[1] = l2capinbuf[15]; - l2cap_event_flag |= L2CAP_FLAG_CONNECTION_RFCOMM_REQUEST; - } - } else if (l2capinbuf[8] == L2CAP_CMD_CONFIG_RESPONSE) { - if ((l2capinbuf[16] | (l2capinbuf[17] << 8)) == 0x0000) { // Success - if (l2capinbuf[12] == sdp_dcid[0] && l2capinbuf[13] == sdp_dcid[1]) { - //Serial.print("\r\nSDP Configuration Complete"); - l2cap_event_flag |= L2CAP_FLAG_CONFIG_SDP_SUCCESS; - } - else if (l2capinbuf[12] == rfcomm_dcid[0] && l2capinbuf[13] == rfcomm_dcid[1]) { - //Serial.print("\r\nRFCOMM Configuration Complete"); - l2cap_event_flag |= L2CAP_FLAG_CONFIG_RFCOMM_SUCCESS; - } - } - } else if (l2capinbuf[8] == L2CAP_CMD_CONFIG_REQUEST) { - if (l2capinbuf[12] == sdp_dcid[0] && l2capinbuf[13] == sdp_dcid[1]) { - //Serial.print("\r\nSDP Configuration Request"); - identifier = l2capinbuf[9]; - l2cap_event_flag |= L2CAP_FLAG_CONFIG_SDP_REQUEST; - } - else if (l2capinbuf[12] == rfcomm_dcid[0] && l2capinbuf[13] == rfcomm_dcid[1]) { - //Serial.print("\r\nRFCOMM Configuration Request"); - identifier = l2capinbuf[9]; - l2cap_event_flag |= L2CAP_FLAG_CONFIG_RFCOMM_REQUEST; - } - } else if (l2capinbuf[8] == L2CAP_CMD_DISCONNECT_REQUEST) { - if (l2capinbuf[12] == sdp_dcid[0] && l2capinbuf[13] == sdp_dcid[1]) { - //Notify(PSTR("\r\nDisconnect Request: SDP Channel"), 0x80); - identifier = l2capinbuf[9]; - l2cap_event_flag |= L2CAP_FLAG_DISCONNECT_SDP_REQUEST; - } else if (l2capinbuf[12] == rfcomm_dcid[0] && l2capinbuf[13] == rfcomm_dcid[1]) { - //Notify(PSTR("\r\nDisconnect Request: RFCOMM Channel"), 0x80); - identifier = l2capinbuf[9]; - l2cap_event_flag |= L2CAP_FLAG_DISCONNECT_RFCOMM_REQUEST; - } - } else if (l2capinbuf[8] == L2CAP_CMD_DISCONNECT_RESPONSE) { - if (l2capinbuf[12] == sdp_scid[0] && l2capinbuf[13] == sdp_scid[1]) { - //Serial.print("\r\nDisconnect Response: SDP Channel"); - identifier = l2capinbuf[9]; - l2cap_event_flag |= L2CAP_FLAG_DISCONNECT_RESPONSE; - } else if (l2capinbuf[12] == rfcomm_scid[0] && l2capinbuf[13] == rfcomm_scid[1]) { - //Serial.print("\r\nDisconnect Response: RFCOMM Channel"); - identifier = l2capinbuf[9]; - l2cap_event_flag |= L2CAP_FLAG_DISCONNECT_RESPONSE; - } - } else if (l2capinbuf[8] == L2CAP_CMD_INFORMATION_REQUEST) { + if ((l2capinbuf[12] | (l2capinbuf[13] << 8)) == SDP_PSM) { // It doesn't matter if it receives another reqeust, since it waits for the channel to disconnect in the L2CAP_SDP_DONE state, and the l2cap_event_flag will be cleared if so + identifier = l2capinbuf[9]; + sdp_scid[0] = l2capinbuf[14]; + sdp_scid[1] = l2capinbuf[15]; + l2cap_event_flag |= L2CAP_FLAG_CONNECTION_SDP_REQUEST; + } else if ((l2capinbuf[12] | (l2capinbuf[13] << 8)) == RFCOMM_PSM) { // ----- || ----- + identifier = l2capinbuf[9]; + rfcomm_scid[0] = l2capinbuf[14]; + rfcomm_scid[1] = l2capinbuf[15]; + l2cap_event_flag |= L2CAP_FLAG_CONNECTION_RFCOMM_REQUEST; + } + } else if (l2capinbuf[8] == L2CAP_CMD_CONFIG_RESPONSE) { + if ((l2capinbuf[16] | (l2capinbuf[17] << 8)) == 0x0000) { // Success + if (l2capinbuf[12] == sdp_dcid[0] && l2capinbuf[13] == sdp_dcid[1]) { + //Serial.print("\r\nSDP Configuration Complete"); + l2cap_event_flag |= L2CAP_FLAG_CONFIG_SDP_SUCCESS; + } else if (l2capinbuf[12] == rfcomm_dcid[0] && l2capinbuf[13] == rfcomm_dcid[1]) { + //Serial.print("\r\nRFCOMM Configuration Complete"); + l2cap_event_flag |= L2CAP_FLAG_CONFIG_RFCOMM_SUCCESS; + } + } + } else if (l2capinbuf[8] == L2CAP_CMD_CONFIG_REQUEST) { + if (l2capinbuf[12] == sdp_dcid[0] && l2capinbuf[13] == sdp_dcid[1]) { + //Serial.print("\r\nSDP Configuration Request"); + identifier = l2capinbuf[9]; + l2cap_event_flag |= L2CAP_FLAG_CONFIG_SDP_REQUEST; + } else if (l2capinbuf[12] == rfcomm_dcid[0] && l2capinbuf[13] == rfcomm_dcid[1]) { + //Serial.print("\r\nRFCOMM Configuration Request"); + identifier = l2capinbuf[9]; + l2cap_event_flag |= L2CAP_FLAG_CONFIG_RFCOMM_REQUEST; + } + } else if (l2capinbuf[8] == L2CAP_CMD_DISCONNECT_REQUEST) { + if (l2capinbuf[12] == sdp_dcid[0] && l2capinbuf[13] == sdp_dcid[1]) { + //Notify(PSTR("\r\nDisconnect Request: SDP Channel"), 0x80); + identifier = l2capinbuf[9]; + l2cap_event_flag |= L2CAP_FLAG_DISCONNECT_SDP_REQUEST; + } else if (l2capinbuf[12] == rfcomm_dcid[0] && l2capinbuf[13] == rfcomm_dcid[1]) { + //Notify(PSTR("\r\nDisconnect Request: RFCOMM Channel"), 0x80); + identifier = l2capinbuf[9]; + l2cap_event_flag |= L2CAP_FLAG_DISCONNECT_RFCOMM_REQUEST; + } + } else if (l2capinbuf[8] == L2CAP_CMD_DISCONNECT_RESPONSE) { + if (l2capinbuf[12] == sdp_scid[0] && l2capinbuf[13] == sdp_scid[1]) { + //Serial.print("\r\nDisconnect Response: SDP Channel"); + identifier = l2capinbuf[9]; + l2cap_event_flag |= L2CAP_FLAG_DISCONNECT_RESPONSE; + } else if (l2capinbuf[12] == rfcomm_scid[0] && l2capinbuf[13] == rfcomm_scid[1]) { + //Serial.print("\r\nDisconnect Response: RFCOMM Channel"); + identifier = l2capinbuf[9]; + l2cap_event_flag |= L2CAP_FLAG_DISCONNECT_RESPONSE; + } + } else if (l2capinbuf[8] == L2CAP_CMD_INFORMATION_REQUEST) { #ifdef DEBUG - Notify(PSTR("\r\nInformation request"), 0x80); + Notify(PSTR("\r\nInformation request"), 0x80); #endif - identifier = l2capinbuf[9]; - pBtd->l2cap_information_response(hci_handle,identifier,l2capinbuf[12],l2capinbuf[13]); - } + identifier = l2capinbuf[9]; + pBtd->l2cap_information_response(hci_handle, identifier, l2capinbuf[12], l2capinbuf[13]); + } #ifdef EXTRADEBUG - else { - Notify(PSTR("\r\nL2CAP Unknown Signaling Command: "), 0x80); - PrintHex(l2capinbuf[8], 0x80); - } + else { + Notify(PSTR("\r\nL2CAP Unknown Signaling Command: "), 0x80); + PrintHex (l2capinbuf[8], 0x80); + } #endif - } else if (l2capinbuf[6] == sdp_dcid[0] && l2capinbuf[7] == sdp_dcid[1]) { // SDP - if(l2capinbuf[8] == SDP_SERVICE_SEARCH_ATTRIBUTE_REQUEST_PDU) { - /* - Serial.print("\r\nUUID: 0x"); - Serial.print(l2capinbuf[16],HEX); - Serial.print(" "); - Serial.print(l2capinbuf[17],HEX); - */ - if ((l2capinbuf[16] << 8 | l2capinbuf[17]) == SERIALPORT_UUID) { - if(firstMessage) { - serialPortResponse1(l2capinbuf[9],l2capinbuf[10]); - firstMessage = false; - } else { - serialPortResponse2(l2capinbuf[9],l2capinbuf[10]); // Serialport continuation state - firstMessage = true; - } - } else if ((l2capinbuf[16] << 8 | l2capinbuf[17]) == L2CAP_UUID) { - if(firstMessage) { - l2capResponse1(l2capinbuf[9],l2capinbuf[10]); - firstMessage = false; - } else { - l2capResponse2(l2capinbuf[9],l2capinbuf[10]); // L2CAP continuation state - firstMessage = true; - } - } else - serviceNotSupported(l2capinbuf[9],l2capinbuf[10]); // The service is not supported - } - } else if (l2capinbuf[6] == rfcomm_dcid[0] && l2capinbuf[7] == rfcomm_dcid[1]) { // RFCOMM - rfcommChannel = l2capinbuf[8] & 0xF8; - rfcommDirection = l2capinbuf[8] & 0x04; - rfcommCommandResponse = l2capinbuf[8] & 0x02; - rfcommChannelType = l2capinbuf[9] & 0xEF; - rfcommPfBit = l2capinbuf[9] & 0x10; + } else if (l2capinbuf[6] == sdp_dcid[0] && l2capinbuf[7] == sdp_dcid[1]) { // SDP + if (l2capinbuf[8] == SDP_SERVICE_SEARCH_ATTRIBUTE_REQUEST_PDU) { + /* + Serial.print("\r\nUUID: 0x"); + Serial.print(l2capinbuf[16],HEX); + Serial.print(" "); + Serial.print(l2capinbuf[17],HEX); + */ + if ((l2capinbuf[16] << 8 | l2capinbuf[17]) == SERIALPORT_UUID) { + if (firstMessage) { + serialPortResponse1(l2capinbuf[9], l2capinbuf[10]); + firstMessage = false; + } else { + serialPortResponse2(l2capinbuf[9], l2capinbuf[10]); // Serialport continuation state + firstMessage = true; + } + } else if ((l2capinbuf[16] << 8 | l2capinbuf[17]) == L2CAP_UUID) { + if (firstMessage) { + l2capResponse1(l2capinbuf[9], l2capinbuf[10]); + firstMessage = false; + } else { + l2capResponse2(l2capinbuf[9], l2capinbuf[10]); // L2CAP continuation state + firstMessage = true; + } + } else + serviceNotSupported(l2capinbuf[9], l2capinbuf[10]); // The service is not supported + } + } else if (l2capinbuf[6] == rfcomm_dcid[0] && l2capinbuf[7] == rfcomm_dcid[1]) { // RFCOMM + rfcommChannel = l2capinbuf[8] & 0xF8; + rfcommDirection = l2capinbuf[8] & 0x04; + rfcommCommandResponse = l2capinbuf[8] & 0x02; + rfcommChannelType = l2capinbuf[9] & 0xEF; + rfcommPfBit = l2capinbuf[9] & 0x10; - if(rfcommChannel>>3 != 0x00) - rfcommChannelConnection = rfcommChannel; + if (rfcommChannel >> 3 != 0x00) + rfcommChannelConnection = rfcommChannel; #ifdef EXTRADEBUG - Notify(PSTR("\r\nRFCOMM Channel: "), 0x80); - Serial.print(rfcommChannel>>3,HEX); - Notify(PSTR(" Direction: "), 0x80); - Serial.print(rfcommDirection>>2,HEX); - Notify(PSTR(" CommandResponse: "), 0x80); - Serial.print(rfcommCommandResponse>>1,HEX); - Notify(PSTR(" ChannelType: "), 0x80); - Serial.print(rfcommChannelType,HEX); - Notify(PSTR(" PF_BIT: "), 0x80); - Serial.print(rfcommPfBit,HEX); + Notify(PSTR("\r\nRFCOMM Channel: "), 0x80); + Serial.print(rfcommChannel >> 3, HEX); + Notify(PSTR(" Direction: "), 0x80); + Serial.print(rfcommDirection >> 2, HEX); + Notify(PSTR(" CommandResponse: "), 0x80); + Serial.print(rfcommCommandResponse >> 1, HEX); + Notify(PSTR(" ChannelType: "), 0x80); + Serial.print(rfcommChannelType, HEX); + Notify(PSTR(" PF_BIT: "), 0x80); + Serial.print(rfcommPfBit, HEX); #endif - if (rfcommChannelType == RFCOMM_DISC) { + if (rfcommChannelType == RFCOMM_DISC) { #ifdef DEBUG - Notify(PSTR("\r\nReceived Disconnect RFCOMM Command on channel: "), 0x80); - Serial.print(rfcommChannel>>3,HEX); + Notify(PSTR("\r\nReceived Disconnect RFCOMM Command on channel: "), 0x80); + Serial.print(rfcommChannel >> 3, HEX); #endif - connected = false; - sendRfcomm(rfcommChannel,rfcommDirection,rfcommCommandResponse,RFCOMM_UA,rfcommPfBit,rfcommbuf,0x00); // UA Command - } - if(connected) { - /* Read the incoming message */ - if(rfcommChannelType == RFCOMM_UIH && rfcommChannel == rfcommChannelConnection) { - uint8_t length = l2capinbuf[10] >> 1; // Get length - uint8_t offset = l2capinbuf[4]-length-4; // See if there is credit - if(rfcommAvailable + length <= sizeof(rfcommDataBuffer)) { // Don't add data to buffer if it would be full - for(uint8_t i = 0; i < length; i++) - rfcommDataBuffer[rfcommAvailable+i] = l2capinbuf[11+i+offset]; - rfcommAvailable += length; - } + connected = false; + sendRfcomm(rfcommChannel, rfcommDirection, rfcommCommandResponse, RFCOMM_UA, rfcommPfBit, rfcommbuf, 0x00); // UA Command + } + if (connected) { + /* Read the incoming message */ + if (rfcommChannelType == RFCOMM_UIH && rfcommChannel == rfcommChannelConnection) { + uint8_t length = l2capinbuf[10] >> 1; // Get length + uint8_t offset = l2capinbuf[4] - length - 4; // See if there is credit + if (rfcommAvailable + length <= sizeof (rfcommDataBuffer)) { // Don't add data to buffer if it would be full + for (uint8_t i = 0; i < length; i++) + rfcommDataBuffer[rfcommAvailable + i] = l2capinbuf[11 + i + offset]; + rfcommAvailable += length; + } #ifdef EXTRADEBUG - Notify(PSTR("\r\nRFCOMM Data Available: "), 0x80); - Serial.print(rfcommAvailable); - if (offset) { - Notify(PSTR(" - Credit: 0x"), 0x80); - Serial.print(l2capinbuf[11],HEX); - } + Notify(PSTR("\r\nRFCOMM Data Available: "), 0x80); + Serial.print(rfcommAvailable); + if (offset) { + Notify(PSTR(" - Credit: 0x"), 0x80); + Serial.print(l2capinbuf[11], HEX); + } #endif #ifdef PRINTREPORT // Uncomment "#define PRINTREPORT" to print the report send to the Arduino via Bluetooth - for(uint8_t i = 0; i < length; i++) - Serial.write(l2capinbuf[i+11+offset]); + for (uint8_t i = 0; i < length; i++) + Serial.write(l2capinbuf[i + 11 + offset]); #endif - } else if (rfcommChannelType == RFCOMM_UIH && l2capinbuf[11] == BT_RFCOMM_RPN_CMD) { // UIH Remote Port Negotiation Command + } else if (rfcommChannelType == RFCOMM_UIH && l2capinbuf[11] == BT_RFCOMM_RPN_CMD) { // UIH Remote Port Negotiation Command #ifdef DEBUG - Notify(PSTR("\r\nReceived UIH Remote Port Negotiation Command"), 0x80); + Notify(PSTR("\r\nReceived UIH Remote Port Negotiation Command"), 0x80); #endif - rfcommbuf[0] = BT_RFCOMM_RPN_RSP; // Command - rfcommbuf[1] = l2capinbuf[12]; // Length and shiftet like so: length << 1 | 1 - rfcommbuf[2] = l2capinbuf[13]; // Channel: channel << 1 | 1 - rfcommbuf[3] = l2capinbuf[14]; // Pre difined for Bluetooth, see 5.5.3 of TS 07.10 Adaption for RFCOMM - rfcommbuf[4] = l2capinbuf[15]; // Priority - rfcommbuf[5] = l2capinbuf[16]; // Timer - rfcommbuf[6] = l2capinbuf[17]; // Max Fram Size LSB - rfcommbuf[7] = l2capinbuf[18]; // Max Fram Size MSB - rfcommbuf[8] = l2capinbuf[19]; // MaxRatransm. - rfcommbuf[9] = l2capinbuf[20]; // Number of Frames - sendRfcomm(rfcommChannel,rfcommDirection,0,RFCOMM_UIH,rfcommPfBit,rfcommbuf,0x0A); // UIH Remote Port Negotiation Response - } else if(rfcommChannelType == RFCOMM_UIH && l2capinbuf[11] == BT_RFCOMM_MSC_CMD) { // UIH Modem Status Command + rfcommbuf[0] = BT_RFCOMM_RPN_RSP; // Command + rfcommbuf[1] = l2capinbuf[12]; // Length and shiftet like so: length << 1 | 1 + rfcommbuf[2] = l2capinbuf[13]; // Channel: channel << 1 | 1 + rfcommbuf[3] = l2capinbuf[14]; // Pre difined for Bluetooth, see 5.5.3 of TS 07.10 Adaption for RFCOMM + rfcommbuf[4] = l2capinbuf[15]; // Priority + rfcommbuf[5] = l2capinbuf[16]; // Timer + rfcommbuf[6] = l2capinbuf[17]; // Max Fram Size LSB + rfcommbuf[7] = l2capinbuf[18]; // Max Fram Size MSB + rfcommbuf[8] = l2capinbuf[19]; // MaxRatransm. + rfcommbuf[9] = l2capinbuf[20]; // Number of Frames + sendRfcomm(rfcommChannel, rfcommDirection, 0, RFCOMM_UIH, rfcommPfBit, rfcommbuf, 0x0A); // UIH Remote Port Negotiation Response + } else if (rfcommChannelType == RFCOMM_UIH && l2capinbuf[11] == BT_RFCOMM_MSC_CMD) { // UIH Modem Status Command #ifdef DEBUG - Notify(PSTR("\r\nSend UIH Modem Status Response"), 0x80); + Notify(PSTR("\r\nSend UIH Modem Status Response"), 0x80); #endif - rfcommbuf[0] = BT_RFCOMM_MSC_RSP; // UIH Modem Status Response - rfcommbuf[1] = 2 << 1 | 1; // Length and shiftet like so: length << 1 | 1 - rfcommbuf[2] = l2capinbuf[13]; // Channel: (1 << 0) | (1 << 1) | (0 << 2) | (channel << 3) - rfcommbuf[3] = l2capinbuf[14]; - sendRfcomm(rfcommChannel,rfcommDirection,0,RFCOMM_UIH,rfcommPfBit,rfcommbuf,0x04); - } - } else { - if(rfcommChannelType == RFCOMM_SABM) { // SABM Command - this is sent twice: once for channel 0 and then for the channel to establish + rfcommbuf[0] = BT_RFCOMM_MSC_RSP; // UIH Modem Status Response + rfcommbuf[1] = 2 << 1 | 1; // Length and shiftet like so: length << 1 | 1 + rfcommbuf[2] = l2capinbuf[13]; // Channel: (1 << 0) | (1 << 1) | (0 << 2) | (channel << 3) + rfcommbuf[3] = l2capinbuf[14]; + sendRfcomm(rfcommChannel, rfcommDirection, 0, RFCOMM_UIH, rfcommPfBit, rfcommbuf, 0x04); + } + } else { + if (rfcommChannelType == RFCOMM_SABM) { // SABM Command - this is sent twice: once for channel 0 and then for the channel to establish #ifdef DEBUG - Notify(PSTR("\r\nReceived SABM Command"), 0x80); + Notify(PSTR("\r\nReceived SABM Command"), 0x80); #endif - sendRfcomm(rfcommChannel,rfcommDirection,rfcommCommandResponse,RFCOMM_UA,rfcommPfBit,rfcommbuf,0x00); // UA Command - } else if(rfcommChannelType == RFCOMM_UIH && l2capinbuf[11] == BT_RFCOMM_PN_CMD) { // UIH Parameter Negotiation Command + sendRfcomm(rfcommChannel, rfcommDirection, rfcommCommandResponse, RFCOMM_UA, rfcommPfBit, rfcommbuf, 0x00); // UA Command + } else if (rfcommChannelType == RFCOMM_UIH && l2capinbuf[11] == BT_RFCOMM_PN_CMD) { // UIH Parameter Negotiation Command #ifdef DEBUG - Notify(PSTR("\r\nReceived UIH Parameter Negotiation Command"), 0x80); + Notify(PSTR("\r\nReceived UIH Parameter Negotiation Command"), 0x80); #endif - rfcommbuf[0] = BT_RFCOMM_PN_RSP; // UIH Parameter Negotiation Response - rfcommbuf[1] = l2capinbuf[12]; // Length and shiftet like so: length << 1 | 1 - rfcommbuf[2] = l2capinbuf[13]; // Channel: channel << 1 | 1 - rfcommbuf[3] = 0xE0; // Pre difined for Bluetooth, see 5.5.3 of TS 07.10 Adaption for RFCOMM - rfcommbuf[4] = 0x00; // Priority - rfcommbuf[5] = 0x00; // Timer - rfcommbuf[6] = BULK_MAXPKTSIZE-14; // Max Fram Size LSB - set to the size of received data (50) - rfcommbuf[7] = 0x00; // Max Fram Size MSB - rfcommbuf[8] = 0x00; // MaxRatransm. - rfcommbuf[9] = 0x00; // Number of Frames - sendRfcomm(rfcommChannel,rfcommDirection,0,RFCOMM_UIH,rfcommPfBit,rfcommbuf,0x0A); - } else if(rfcommChannelType == RFCOMM_UIH && l2capinbuf[11] == BT_RFCOMM_MSC_CMD) { // UIH Modem Status Command + rfcommbuf[0] = BT_RFCOMM_PN_RSP; // UIH Parameter Negotiation Response + rfcommbuf[1] = l2capinbuf[12]; // Length and shiftet like so: length << 1 | 1 + rfcommbuf[2] = l2capinbuf[13]; // Channel: channel << 1 | 1 + rfcommbuf[3] = 0xE0; // Pre difined for Bluetooth, see 5.5.3 of TS 07.10 Adaption for RFCOMM + rfcommbuf[4] = 0x00; // Priority + rfcommbuf[5] = 0x00; // Timer + rfcommbuf[6] = BULK_MAXPKTSIZE - 14; // Max Fram Size LSB - set to the size of received data (50) + rfcommbuf[7] = 0x00; // Max Fram Size MSB + rfcommbuf[8] = 0x00; // MaxRatransm. + rfcommbuf[9] = 0x00; // Number of Frames + sendRfcomm(rfcommChannel, rfcommDirection, 0, RFCOMM_UIH, rfcommPfBit, rfcommbuf, 0x0A); + } else if (rfcommChannelType == RFCOMM_UIH && l2capinbuf[11] == BT_RFCOMM_MSC_CMD) { // UIH Modem Status Command #ifdef DEBUG - Notify(PSTR("\r\nSend UIH Modem Status Response"), 0x80); + Notify(PSTR("\r\nSend UIH Modem Status Response"), 0x80); #endif - rfcommbuf[0] = BT_RFCOMM_MSC_RSP; // UIH Modem Status Response - rfcommbuf[1] = 2 << 1 | 1; // Length and shiftet like so: length << 1 | 1 - rfcommbuf[2] = l2capinbuf[13]; // Channel: (1 << 0) | (1 << 1) | (0 << 2) | (channel << 3) - rfcommbuf[3] = l2capinbuf[14]; - sendRfcomm(rfcommChannel,rfcommDirection,0,RFCOMM_UIH,rfcommPfBit,rfcommbuf,0x04); + rfcommbuf[0] = BT_RFCOMM_MSC_RSP; // UIH Modem Status Response + rfcommbuf[1] = 2 << 1 | 1; // Length and shiftet like so: length << 1 | 1 + rfcommbuf[2] = l2capinbuf[13]; // Channel: (1 << 0) | (1 << 1) | (0 << 2) | (channel << 3) + rfcommbuf[3] = l2capinbuf[14]; + sendRfcomm(rfcommChannel, rfcommDirection, 0, RFCOMM_UIH, rfcommPfBit, rfcommbuf, 0x04); - delay(1); + delay(1); #ifdef DEBUG - Notify(PSTR("\r\nSend UIH Modem Status Command"), 0x80); + Notify(PSTR("\r\nSend UIH Modem Status Command"), 0x80); #endif - rfcommbuf[0] = BT_RFCOMM_MSC_CMD; // UIH Modem Status Command - rfcommbuf[1] = 2 << 1 | 1; // Length and shiftet like so: length << 1 | 1 - rfcommbuf[2] = l2capinbuf[13]; // Channel: (1 << 0) | (1 << 1) | (0 << 2) | (channel << 3) - rfcommbuf[3] = 0x8D; // Can receive frames (YES), Ready to Communicate (YES), Ready to Receive (YES), Incomig Call (NO), Data is Value (YES) + rfcommbuf[0] = BT_RFCOMM_MSC_CMD; // UIH Modem Status Command + rfcommbuf[1] = 2 << 1 | 1; // Length and shiftet like so: length << 1 | 1 + rfcommbuf[2] = l2capinbuf[13]; // Channel: (1 << 0) | (1 << 1) | (0 << 2) | (channel << 3) + rfcommbuf[3] = 0x8D; // Can receive frames (YES), Ready to Communicate (YES), Ready to Receive (YES), Incomig Call (NO), Data is Value (YES) - sendRfcomm(rfcommChannel,rfcommDirection,0,RFCOMM_UIH,rfcommPfBit,rfcommbuf,0x04); - } else if(rfcommChannelType == RFCOMM_UIH && l2capinbuf[11] == BT_RFCOMM_MSC_RSP) { // UIH Modem Status Response - if(!creditSent) { + sendRfcomm(rfcommChannel, rfcommDirection, 0, RFCOMM_UIH, rfcommPfBit, rfcommbuf, 0x04); + } else if (rfcommChannelType == RFCOMM_UIH && l2capinbuf[11] == BT_RFCOMM_MSC_RSP) { // UIH Modem Status Response + if (!creditSent) { #ifdef DEBUG - Notify(PSTR("\r\nSend UIH Command with credit"), 0x80); + Notify(PSTR("\r\nSend UIH Command with credit"), 0x80); #endif - sendRfcommCredit(rfcommChannelConnection,rfcommDirection,0,RFCOMM_UIH,0x10,sizeof(rfcommDataBuffer)); // Send credit - creditSent = true; - timer = millis(); - waitForLastCommand = true; - } - } else if(rfcommChannelType == RFCOMM_UIH && l2capinbuf[10] == 0x01) { // UIH Command with credit + sendRfcommCredit(rfcommChannelConnection, rfcommDirection, 0, RFCOMM_UIH, 0x10, sizeof (rfcommDataBuffer)); // Send credit + creditSent = true; + timer = millis(); + waitForLastCommand = true; + } + } else if (rfcommChannelType == RFCOMM_UIH && l2capinbuf[10] == 0x01) { // UIH Command with credit #ifdef DEBUG - Notify(PSTR("\r\nReceived UIH Command with credit"), 0x80); + Notify(PSTR("\r\nReceived UIH Command with credit"), 0x80); #endif - } else if(rfcommChannelType == RFCOMM_UIH && l2capinbuf[11] == BT_RFCOMM_RPN_CMD) { // UIH Remote Port Negotiation Command + } else if (rfcommChannelType == RFCOMM_UIH && l2capinbuf[11] == BT_RFCOMM_RPN_CMD) { // UIH Remote Port Negotiation Command #ifdef DEBUG - Notify(PSTR("\r\nReceived UIH Remote Port Negotiation Command"), 0x80); + Notify(PSTR("\r\nReceived UIH Remote Port Negotiation Command"), 0x80); #endif - rfcommbuf[0] = BT_RFCOMM_RPN_RSP; // Command - rfcommbuf[1] = l2capinbuf[12]; // Length and shiftet like so: length << 1 | 1 - rfcommbuf[2] = l2capinbuf[13]; // Channel: channel << 1 | 1 - rfcommbuf[3] = l2capinbuf[14]; // Pre difined for Bluetooth, see 5.5.3 of TS 07.10 Adaption for RFCOMM - rfcommbuf[4] = l2capinbuf[15]; // Priority - rfcommbuf[5] = l2capinbuf[16]; // Timer - rfcommbuf[6] = l2capinbuf[17]; // Max Fram Size LSB - rfcommbuf[7] = l2capinbuf[18]; // Max Fram Size MSB - rfcommbuf[8] = l2capinbuf[19]; // MaxRatransm. - rfcommbuf[9] = l2capinbuf[20]; // Number of Frames - sendRfcomm(rfcommChannel,rfcommDirection,0,RFCOMM_UIH,rfcommPfBit,rfcommbuf,0x0A); // UIH Remote Port Negotiation Response + rfcommbuf[0] = BT_RFCOMM_RPN_RSP; // Command + rfcommbuf[1] = l2capinbuf[12]; // Length and shiftet like so: length << 1 | 1 + rfcommbuf[2] = l2capinbuf[13]; // Channel: channel << 1 | 1 + rfcommbuf[3] = l2capinbuf[14]; // Pre difined for Bluetooth, see 5.5.3 of TS 07.10 Adaption for RFCOMM + rfcommbuf[4] = l2capinbuf[15]; // Priority + rfcommbuf[5] = l2capinbuf[16]; // Timer + rfcommbuf[6] = l2capinbuf[17]; // Max Fram Size LSB + rfcommbuf[7] = l2capinbuf[18]; // Max Fram Size MSB + rfcommbuf[8] = l2capinbuf[19]; // MaxRatransm. + rfcommbuf[9] = l2capinbuf[20]; // Number of Frames + sendRfcomm(rfcommChannel, rfcommDirection, 0, RFCOMM_UIH, rfcommPfBit, rfcommbuf, 0x0A); // UIH Remote Port Negotiation Response #ifdef DEBUG - Notify(PSTR("\r\nRFCOMM Connection is now established\r\n"), 0x80); + Notify(PSTR("\r\nRFCOMM Connection is now established\r\n"), 0x80); #endif - waitForLastCommand = false; - creditSent = false; - connected = true; // The RFCOMM channel is now established + waitForLastCommand = false; + creditSent = false; + connected = true; // The RFCOMM channel is now established + } +#ifdef DEBUG + else if (rfcommChannelType != RFCOMM_DISC) { + Notify(PSTR("\r\nUnsupported RFCOMM Data - ChannelType: "), 0x80); + PrintHex (rfcommChannelType, 0x80); + Notify(PSTR(" Command: "), 0x80); + PrintHex (l2capinbuf[11], 0x80); + } +#endif + } } -#ifdef DEBUG - else if(rfcommChannelType != RFCOMM_DISC) { - Notify(PSTR("\r\nUnsupported RFCOMM Data - ChannelType: "), 0x80); - PrintHex(rfcommChannelType, 0x80); - Notify(PSTR(" Command: "), 0x80); - PrintHex(l2capinbuf[11], 0x80); - } -#endif - } - } #ifdef EXTRADEBUG - else { - Notify(PSTR("\r\nUnsupported L2CAP Data - Channel ID: "), 0x80); - PrintHex(l2capinbuf[7], 0x80); - Notify(PSTR(" "), 0x80); - PrintHex(l2capinbuf[6], 0x80); + else { + Notify(PSTR("\r\nUnsupported L2CAP Data - Channel ID: "), 0x80); + PrintHex (l2capinbuf[7], 0x80); + Notify(PSTR(" "), 0x80); + PrintHex (l2capinbuf[6], 0x80); + } +#endif + SDP_task(); + RFCOMM_task(); } -#endif - SDP_task(); - RFCOMM_task(); - } } + void SPP::Run() { - if(waitForLastCommand && (millis() - timer) > 100) { // We will only wait 100ms and see if the UIH Remote Port Negotiation Command is send, as some deviced don't send it + if (waitForLastCommand && (millis() - timer) > 100) { // We will only wait 100ms and see if the UIH Remote Port Negotiation Command is send, as some deviced don't send it #ifdef DEBUG - Notify(PSTR("\r\nRFCOMM Connection is now established - Automatic\r\n"), 0x80); + Notify(PSTR("\r\nRFCOMM Connection is now established - Automatic\r\n"), 0x80); #endif - creditSent = false; - waitForLastCommand = false; - connected = true; // The RFCOMM channel is now established - } + creditSent = false; + waitForLastCommand = false; + connected = true; // The RFCOMM channel is now established + } } + void SPP::SDP_task() { - switch (l2cap_sdp_state) - { - case L2CAP_SDP_WAIT: - if (l2cap_connection_request_sdp_flag) { - l2cap_event_flag &= ~L2CAP_FLAG_CONNECTION_SDP_REQUEST; // Clear flag + switch (l2cap_sdp_state) { + case L2CAP_SDP_WAIT: + if (l2cap_connection_request_sdp_flag) { + l2cap_event_flag &= ~L2CAP_FLAG_CONNECTION_SDP_REQUEST; // Clear flag #ifdef DEBUG - Notify(PSTR("\r\nSDP Incoming Connection Request"), 0x80); + Notify(PSTR("\r\nSDP Incoming Connection Request"), 0x80); #endif - pBtd->l2cap_connection_response(hci_handle,identifier, sdp_dcid, sdp_scid, PENDING); - delay(1); - pBtd->l2cap_connection_response(hci_handle,identifier, sdp_dcid, sdp_scid, SUCCESSFUL); - identifier++; - delay(1); - pBtd->l2cap_config_request(hci_handle,identifier, sdp_scid); - l2cap_sdp_state = L2CAP_SDP_REQUEST; - } - break; - case L2CAP_SDP_REQUEST: - if (l2cap_config_request_sdp_flag) { - l2cap_event_flag &= ~L2CAP_FLAG_CONFIG_SDP_REQUEST; // Clear flag + pBtd->l2cap_connection_response(hci_handle, identifier, sdp_dcid, sdp_scid, PENDING); + delay(1); + pBtd->l2cap_connection_response(hci_handle, identifier, sdp_dcid, sdp_scid, SUCCESSFUL); + identifier++; + delay(1); + pBtd->l2cap_config_request(hci_handle, identifier, sdp_scid); + l2cap_sdp_state = L2CAP_SDP_REQUEST; + } + break; + case L2CAP_SDP_REQUEST: + if (l2cap_config_request_sdp_flag) { + l2cap_event_flag &= ~L2CAP_FLAG_CONFIG_SDP_REQUEST; // Clear flag #ifdef DEBUG - Notify(PSTR("\r\nSDP Configuration Request"), 0x80); + Notify(PSTR("\r\nSDP Configuration Request"), 0x80); #endif - pBtd->l2cap_config_response(hci_handle,identifier, sdp_scid); - l2cap_sdp_state = L2CAP_SDP_SUCCESS; - } - break; - case L2CAP_SDP_SUCCESS: - if (l2cap_config_success_sdp_flag) { - l2cap_event_flag &= ~L2CAP_FLAG_CONFIG_SDP_SUCCESS; // Clear flag + pBtd->l2cap_config_response(hci_handle, identifier, sdp_scid); + l2cap_sdp_state = L2CAP_SDP_SUCCESS; + } + break; + case L2CAP_SDP_SUCCESS: + if (l2cap_config_success_sdp_flag) { + l2cap_event_flag &= ~L2CAP_FLAG_CONFIG_SDP_SUCCESS; // Clear flag #ifdef DEBUG - Notify(PSTR("\r\nSDP Successfully Configured"), 0x80); + Notify(PSTR("\r\nSDP Successfully Configured"), 0x80); #endif - firstMessage = true; // Reset bool - SDPConnected = true; - l2cap_sdp_state = L2CAP_SDP_DONE; - } - break; - case L2CAP_SDP_DONE: - if(l2cap_disconnect_request_sdp_flag) { - l2cap_event_flag &= ~L2CAP_FLAG_DISCONNECT_SDP_REQUEST; // Clear flag - SDPConnected = false; + firstMessage = true; // Reset bool + SDPConnected = true; + l2cap_sdp_state = L2CAP_SDP_DONE; + } + break; + case L2CAP_SDP_DONE: + if (l2cap_disconnect_request_sdp_flag) { + l2cap_event_flag &= ~L2CAP_FLAG_DISCONNECT_SDP_REQUEST; // Clear flag + SDPConnected = false; #ifdef DEBUG - Notify(PSTR("\r\nDisconnected SDP Channel"), 0x80); + Notify(PSTR("\r\nDisconnected SDP Channel"), 0x80); #endif - pBtd->l2cap_disconnection_response(hci_handle,identifier,sdp_dcid,sdp_scid); - l2cap_sdp_state = L2CAP_SDP_WAIT; - } else if(l2cap_connection_request_sdp_flag) - l2cap_rfcomm_state = L2CAP_SDP_WAIT; - break; - case L2CAP_DISCONNECT_RESPONSE: // This is for both disconnection response from the RFCOMM and SDP channel if they were connected - if (l2cap_disconnect_response_flag) { + pBtd->l2cap_disconnection_response(hci_handle, identifier, sdp_dcid, sdp_scid); + l2cap_sdp_state = L2CAP_SDP_WAIT; + } else if (l2cap_connection_request_sdp_flag) + l2cap_rfcomm_state = L2CAP_SDP_WAIT; + break; + case L2CAP_DISCONNECT_RESPONSE: // This is for both disconnection response from the RFCOMM and SDP channel if they were connected + if (l2cap_disconnect_response_flag) { #ifdef DEBUG - Notify(PSTR("\r\nDisconnected L2CAP Connection"), 0x80); + Notify(PSTR("\r\nDisconnected L2CAP Connection"), 0x80); #endif - RFCOMMConnected = false; - SDPConnected = false; - pBtd->hci_disconnect(hci_handle); - hci_handle = -1; // Reset handle - l2cap_event_flag = 0; // Reset flags - l2cap_sdp_state = L2CAP_SDP_WAIT; - l2cap_rfcomm_state = L2CAP_RFCOMM_WAIT; - } - break; - } + RFCOMMConnected = false; + SDPConnected = false; + pBtd->hci_disconnect(hci_handle); + hci_handle = -1; // Reset handle + l2cap_event_flag = 0; // Reset flags + l2cap_sdp_state = L2CAP_SDP_WAIT; + l2cap_rfcomm_state = L2CAP_RFCOMM_WAIT; + } + break; + } } -void SPP::RFCOMM_task() -{ - switch (l2cap_rfcomm_state) - { - case L2CAP_RFCOMM_WAIT: - if(l2cap_connection_request_rfcomm_flag) { - l2cap_event_flag &= ~L2CAP_FLAG_CONNECTION_RFCOMM_REQUEST; // Clear flag + +void SPP::RFCOMM_task() { + switch (l2cap_rfcomm_state) { + case L2CAP_RFCOMM_WAIT: + if (l2cap_connection_request_rfcomm_flag) { + l2cap_event_flag &= ~L2CAP_FLAG_CONNECTION_RFCOMM_REQUEST; // Clear flag #ifdef DEBUG - Notify(PSTR("\r\nRFCOMM Incoming Connection Request"), 0x80); + Notify(PSTR("\r\nRFCOMM Incoming Connection Request"), 0x80); #endif - pBtd->l2cap_connection_response(hci_handle,identifier, rfcomm_dcid, rfcomm_scid, PENDING); - delay(1); - pBtd->l2cap_connection_response(hci_handle,identifier, rfcomm_dcid, rfcomm_scid, SUCCESSFUL); - identifier++; - delay(1); - pBtd->l2cap_config_request(hci_handle,identifier, rfcomm_scid); - l2cap_rfcomm_state = L2CAP_RFCOMM_REQUEST; - } - break; - case L2CAP_RFCOMM_REQUEST: - if (l2cap_config_request_rfcomm_flag) { - l2cap_event_flag &= ~L2CAP_FLAG_CONFIG_RFCOMM_REQUEST; // Clear flag + pBtd->l2cap_connection_response(hci_handle, identifier, rfcomm_dcid, rfcomm_scid, PENDING); + delay(1); + pBtd->l2cap_connection_response(hci_handle, identifier, rfcomm_dcid, rfcomm_scid, SUCCESSFUL); + identifier++; + delay(1); + pBtd->l2cap_config_request(hci_handle, identifier, rfcomm_scid); + l2cap_rfcomm_state = L2CAP_RFCOMM_REQUEST; + } + break; + case L2CAP_RFCOMM_REQUEST: + if (l2cap_config_request_rfcomm_flag) { + l2cap_event_flag &= ~L2CAP_FLAG_CONFIG_RFCOMM_REQUEST; // Clear flag #ifdef DEBUG - Notify(PSTR("\r\nRFCOMM Configuration Request"), 0x80); + Notify(PSTR("\r\nRFCOMM Configuration Request"), 0x80); #endif - pBtd->l2cap_config_response(hci_handle,identifier, rfcomm_scid); - l2cap_rfcomm_state = L2CAP_RFCOMM_SUCCESS; - } - break; - case L2CAP_RFCOMM_SUCCESS: - if (l2cap_config_success_rfcomm_flag) { - l2cap_event_flag &= ~L2CAP_FLAG_CONFIG_RFCOMM_SUCCESS; // Clear flag + pBtd->l2cap_config_response(hci_handle, identifier, rfcomm_scid); + l2cap_rfcomm_state = L2CAP_RFCOMM_SUCCESS; + } + break; + case L2CAP_RFCOMM_SUCCESS: + if (l2cap_config_success_rfcomm_flag) { + l2cap_event_flag &= ~L2CAP_FLAG_CONFIG_RFCOMM_SUCCESS; // Clear flag #ifdef DEBUG - Notify(PSTR("\r\nRFCOMM Successfully Configured"), 0x80); + Notify(PSTR("\r\nRFCOMM Successfully Configured"), 0x80); #endif - rfcommAvailable = 0; // Reset number of bytes available - bytesRead = 0; // Reset number of bytes received - RFCOMMConnected = true; - l2cap_rfcomm_state = L2CAP_RFCOMM_DONE; - } - break; - case L2CAP_RFCOMM_DONE: - if(l2cap_disconnect_request_rfcomm_flag) { - l2cap_event_flag &= ~L2CAP_FLAG_DISCONNECT_RFCOMM_REQUEST; // Clear flag - RFCOMMConnected = false; - connected = false; + rfcommAvailable = 0; // Reset number of bytes available + bytesRead = 0; // Reset number of bytes received + RFCOMMConnected = true; + l2cap_rfcomm_state = L2CAP_RFCOMM_DONE; + } + break; + case L2CAP_RFCOMM_DONE: + if (l2cap_disconnect_request_rfcomm_flag) { + l2cap_event_flag &= ~L2CAP_FLAG_DISCONNECT_RFCOMM_REQUEST; // Clear flag + RFCOMMConnected = false; + connected = false; #ifdef DEBUG - Notify(PSTR("\r\nDisconnected RFCOMM Channel"), 0x80); + Notify(PSTR("\r\nDisconnected RFCOMM Channel"), 0x80); #endif - pBtd->l2cap_disconnection_response(hci_handle,identifier,rfcomm_dcid,rfcomm_scid); - l2cap_rfcomm_state = L2CAP_RFCOMM_WAIT; - } else if(l2cap_connection_request_rfcomm_flag) - l2cap_rfcomm_state = L2CAP_RFCOMM_WAIT; - break; - } + pBtd->l2cap_disconnection_response(hci_handle, identifier, rfcomm_dcid, rfcomm_scid); + l2cap_rfcomm_state = L2CAP_RFCOMM_WAIT; + } else if (l2cap_connection_request_rfcomm_flag) + l2cap_rfcomm_state = L2CAP_RFCOMM_WAIT; + break; + } } /************************************************************/ /* SDP Commands */ + /************************************************************/ void SPP::SDP_Command(uint8_t* data, uint8_t nbytes) { // See page 223 in the Bluetooth specs - pBtd->L2CAP_Command(hci_handle,data,nbytes,sdp_scid[0],sdp_scid[1]); + pBtd->L2CAP_Command(hci_handle, data, nbytes, sdp_scid[0], sdp_scid[1]); } + void SPP::serviceNotSupported(uint8_t transactionIDHigh, uint8_t transactionIDLow) { // See page 235 in the Bluetooth specs - l2capoutbuf[0] = SDP_SERVICE_SEARCH_ATTRIBUTE_RESPONSE_PDU; - l2capoutbuf[1] = transactionIDHigh; - l2capoutbuf[2] = transactionIDLow; - l2capoutbuf[3] = 0x00; // Parameter Length - l2capoutbuf[4] = 0x05; // Parameter Length - l2capoutbuf[5] = 0x00; // AttributeListsByteCount - l2capoutbuf[6] = 0x02; // AttributeListsByteCount + l2capoutbuf[0] = SDP_SERVICE_SEARCH_ATTRIBUTE_RESPONSE_PDU; + l2capoutbuf[1] = transactionIDHigh; + l2capoutbuf[2] = transactionIDLow; + l2capoutbuf[3] = 0x00; // Parameter Length + l2capoutbuf[4] = 0x05; // Parameter Length + l2capoutbuf[5] = 0x00; // AttributeListsByteCount + l2capoutbuf[6] = 0x02; // AttributeListsByteCount - /* Attribute ID/Value Sequence: */ - l2capoutbuf[7] = 0x35; - l2capoutbuf[8] = 0x00; - l2capoutbuf[9] = 0x00; + /* Attribute ID/Value Sequence: */ + l2capoutbuf[7] = 0x35; + l2capoutbuf[8] = 0x00; + l2capoutbuf[9] = 0x00; - SDP_Command(l2capoutbuf,10); + SDP_Command(l2capoutbuf, 10); } + void SPP::serialPortResponse1(uint8_t transactionIDHigh, uint8_t transactionIDLow) { - l2capoutbuf[0] = SDP_SERVICE_SEARCH_ATTRIBUTE_RESPONSE_PDU; - l2capoutbuf[1] = transactionIDHigh; - l2capoutbuf[2] = transactionIDLow; - l2capoutbuf[3] = 0x00; // Parameter Length - l2capoutbuf[4] = 0x2B; // Parameter Length - l2capoutbuf[5] = 0x00; // AttributeListsByteCount - l2capoutbuf[6] = 0x26; // AttributeListsByteCount + l2capoutbuf[0] = SDP_SERVICE_SEARCH_ATTRIBUTE_RESPONSE_PDU; + l2capoutbuf[1] = transactionIDHigh; + l2capoutbuf[2] = transactionIDLow; + l2capoutbuf[3] = 0x00; // Parameter Length + l2capoutbuf[4] = 0x2B; // Parameter Length + l2capoutbuf[5] = 0x00; // AttributeListsByteCount + l2capoutbuf[6] = 0x26; // AttributeListsByteCount - /* Attribute ID/Value Sequence: */ - l2capoutbuf[7] = 0x36; - l2capoutbuf[8] = 0x00; - l2capoutbuf[9] = 0x3C; - l2capoutbuf[10] = 0x36; - l2capoutbuf[11] = 0x00; + /* Attribute ID/Value Sequence: */ + l2capoutbuf[7] = 0x36; + l2capoutbuf[8] = 0x00; + l2capoutbuf[9] = 0x3C; + l2capoutbuf[10] = 0x36; + l2capoutbuf[11] = 0x00; - l2capoutbuf[12] = 0x39; - l2capoutbuf[13] = 0x09; - l2capoutbuf[14] = 0x00; - l2capoutbuf[15] = 0x00; - l2capoutbuf[16] = 0x0A; - l2capoutbuf[17] = 0x00; - l2capoutbuf[18] = 0x01; - l2capoutbuf[19] = 0x00; - l2capoutbuf[20] = 0x06; - l2capoutbuf[21] = 0x09; - l2capoutbuf[22] = 0x00; - l2capoutbuf[23] = 0x01; - l2capoutbuf[24] = 0x35; - l2capoutbuf[25] = 0x03; - l2capoutbuf[26] = 0x19; - l2capoutbuf[27] = 0x11; + l2capoutbuf[12] = 0x39; + l2capoutbuf[13] = 0x09; + l2capoutbuf[14] = 0x00; + l2capoutbuf[15] = 0x00; + l2capoutbuf[16] = 0x0A; + l2capoutbuf[17] = 0x00; + l2capoutbuf[18] = 0x01; + l2capoutbuf[19] = 0x00; + l2capoutbuf[20] = 0x06; + l2capoutbuf[21] = 0x09; + l2capoutbuf[22] = 0x00; + l2capoutbuf[23] = 0x01; + l2capoutbuf[24] = 0x35; + l2capoutbuf[25] = 0x03; + l2capoutbuf[26] = 0x19; + l2capoutbuf[27] = 0x11; - l2capoutbuf[28] = 0x01; - l2capoutbuf[29] = 0x09; - l2capoutbuf[30] = 0x00; - l2capoutbuf[31] = 0x04; - l2capoutbuf[32] = 0x35; - l2capoutbuf[33] = 0x0C; - l2capoutbuf[34] = 0x35; - l2capoutbuf[35] = 0x03; - l2capoutbuf[36] = 0x19; - l2capoutbuf[37] = 0x01; - l2capoutbuf[38] = 0x00; - l2capoutbuf[39] = 0x35; - l2capoutbuf[40] = 0x05; - l2capoutbuf[41] = 0x19; - l2capoutbuf[42] = 0x00; - l2capoutbuf[43] = 0x03; + l2capoutbuf[28] = 0x01; + l2capoutbuf[29] = 0x09; + l2capoutbuf[30] = 0x00; + l2capoutbuf[31] = 0x04; + l2capoutbuf[32] = 0x35; + l2capoutbuf[33] = 0x0C; + l2capoutbuf[34] = 0x35; + l2capoutbuf[35] = 0x03; + l2capoutbuf[36] = 0x19; + l2capoutbuf[37] = 0x01; + l2capoutbuf[38] = 0x00; + l2capoutbuf[39] = 0x35; + l2capoutbuf[40] = 0x05; + l2capoutbuf[41] = 0x19; + l2capoutbuf[42] = 0x00; + l2capoutbuf[43] = 0x03; - l2capoutbuf[44] = 0x08; - l2capoutbuf[45] = 0x02; // Two extra bytes - l2capoutbuf[46] = 0x00; // 25 (0x19) more bytes to come - l2capoutbuf[47] = 0x19; + l2capoutbuf[44] = 0x08; + l2capoutbuf[45] = 0x02; // Two extra bytes + l2capoutbuf[46] = 0x00; // 25 (0x19) more bytes to come + l2capoutbuf[47] = 0x19; - SDP_Command(l2capoutbuf,48); + SDP_Command(l2capoutbuf, 48); } + void SPP::serialPortResponse2(uint8_t transactionIDHigh, uint8_t transactionIDLow) { - l2capoutbuf[0] = SDP_SERVICE_SEARCH_ATTRIBUTE_RESPONSE_PDU; - l2capoutbuf[1] = transactionIDHigh; - l2capoutbuf[2] = transactionIDLow; - l2capoutbuf[3] = 0x00; // Parameter Length - l2capoutbuf[4] = 0x1C; // Parameter Length - l2capoutbuf[5] = 0x00; // AttributeListsByteCount - l2capoutbuf[6] = 0x19; // AttributeListsByteCount + l2capoutbuf[0] = SDP_SERVICE_SEARCH_ATTRIBUTE_RESPONSE_PDU; + l2capoutbuf[1] = transactionIDHigh; + l2capoutbuf[2] = transactionIDLow; + l2capoutbuf[3] = 0x00; // Parameter Length + l2capoutbuf[4] = 0x1C; // Parameter Length + l2capoutbuf[5] = 0x00; // AttributeListsByteCount + l2capoutbuf[6] = 0x19; // AttributeListsByteCount - /* Attribute ID/Value Sequence: */ - l2capoutbuf[7] = 0x01; - l2capoutbuf[8] = 0x09; - l2capoutbuf[9] = 0x00; - l2capoutbuf[10] = 0x06; - l2capoutbuf[11] = 0x35; + /* Attribute ID/Value Sequence: */ + l2capoutbuf[7] = 0x01; + l2capoutbuf[8] = 0x09; + l2capoutbuf[9] = 0x00; + l2capoutbuf[10] = 0x06; + l2capoutbuf[11] = 0x35; - l2capoutbuf[12] = 0x09; - l2capoutbuf[13] = 0x09; - l2capoutbuf[14] = 0x65; - l2capoutbuf[15] = 0x6E; - l2capoutbuf[16] = 0x09; - l2capoutbuf[17] = 0x00; - l2capoutbuf[18] = 0x6A; - l2capoutbuf[19] = 0x09; - l2capoutbuf[20] = 0x01; - l2capoutbuf[21] = 0x00; - l2capoutbuf[22] = 0x09; - l2capoutbuf[23] = 0x01; - l2capoutbuf[24] = 0x00; - l2capoutbuf[25] = 0x25; + l2capoutbuf[12] = 0x09; + l2capoutbuf[13] = 0x09; + l2capoutbuf[14] = 0x65; + l2capoutbuf[15] = 0x6E; + l2capoutbuf[16] = 0x09; + l2capoutbuf[17] = 0x00; + l2capoutbuf[18] = 0x6A; + l2capoutbuf[19] = 0x09; + l2capoutbuf[20] = 0x01; + l2capoutbuf[21] = 0x00; + l2capoutbuf[22] = 0x09; + l2capoutbuf[23] = 0x01; + l2capoutbuf[24] = 0x00; + l2capoutbuf[25] = 0x25; - l2capoutbuf[26] = 0x05; // Name length - l2capoutbuf[27] = 'T'; - l2capoutbuf[28] = 'K'; - l2capoutbuf[29] = 'J'; - l2capoutbuf[30] = 'S'; - l2capoutbuf[31] = 'P'; - l2capoutbuf[32] = 0x00; // No more data + l2capoutbuf[26] = 0x05; // Name length + l2capoutbuf[27] = 'T'; + l2capoutbuf[28] = 'K'; + l2capoutbuf[29] = 'J'; + l2capoutbuf[30] = 'S'; + l2capoutbuf[31] = 'P'; + l2capoutbuf[32] = 0x00; // No more data - SDP_Command(l2capoutbuf,33); + SDP_Command(l2capoutbuf, 33); } + void SPP::l2capResponse1(uint8_t transactionIDHigh, uint8_t transactionIDLow) { - serialPortResponse1(transactionIDHigh,transactionIDLow); // These has to send all the supported functions, since it only supports virtual serialport it just sends the message again + serialPortResponse1(transactionIDHigh, transactionIDLow); // These has to send all the supported functions, since it only supports virtual serialport it just sends the message again } + void SPP::l2capResponse2(uint8_t transactionIDHigh, uint8_t transactionIDLow) { - serialPortResponse2(transactionIDHigh,transactionIDLow); // Same data as serialPortResponse2 + serialPortResponse2(transactionIDHigh, transactionIDLow); // Same data as serialPortResponse2 } /************************************************************/ /* RFCOMM Commands */ + /************************************************************/ void SPP::RFCOMM_Command(uint8_t* data, uint8_t nbytes) { - pBtd->L2CAP_Command(hci_handle,data,nbytes,rfcomm_scid[0],rfcomm_scid[1]); + pBtd->L2CAP_Command(hci_handle, data, nbytes, rfcomm_scid[0], rfcomm_scid[1]); } void SPP::sendRfcomm(uint8_t channel, uint8_t direction, uint8_t CR, uint8_t channelType, uint8_t pfBit, uint8_t* data, uint8_t length) { - l2capoutbuf[0] = channel | direction | CR | extendAddress; // RFCOMM Address - l2capoutbuf[1] = channelType | pfBit; // RFCOMM Control - l2capoutbuf[2] = length << 1 | 0x01; // Length and format (allways 0x01 bytes format) - uint8_t i = 0; - for(; i < length; i++) - l2capoutbuf[i+3] = data[i]; - l2capoutbuf[i+3] = calcFcs(l2capoutbuf); + l2capoutbuf[0] = channel | direction | CR | extendAddress; // RFCOMM Address + l2capoutbuf[1] = channelType | pfBit; // RFCOMM Control + l2capoutbuf[2] = length << 1 | 0x01; // Length and format (allways 0x01 bytes format) + uint8_t i = 0; + for (; i < length; i++) + l2capoutbuf[i + 3] = data[i]; + l2capoutbuf[i + 3] = calcFcs(l2capoutbuf); #ifdef EXTRADEBUG - Notify(PSTR(" - RFCOMM Data: "), 0x80); - for(i = 0; i < length+4; i++) { - Serial.print(l2capoutbuf[i],HEX); - Notify(PSTR(" "), 0x80); - } + Notify(PSTR(" - RFCOMM Data: "), 0x80); + for (i = 0; i < length + 4; i++) { + Serial.print(l2capoutbuf[i], HEX); + Notify(PSTR(" "), 0x80); + } #endif - RFCOMM_Command(l2capoutbuf,length+4); + RFCOMM_Command(l2capoutbuf, length + 4); } void SPP::sendRfcommCredit(uint8_t channel, uint8_t direction, uint8_t CR, uint8_t channelType, uint8_t pfBit, uint8_t credit) { - l2capoutbuf[0] = channel | direction | CR | extendAddress; // RFCOMM Address - l2capoutbuf[1] = channelType | pfBit; // RFCOMM Control - l2capoutbuf[2] = 0x01; // Length = 0 - l2capoutbuf[3] = credit; // Credit - l2capoutbuf[4] = calcFcs(l2capoutbuf); + l2capoutbuf[0] = channel | direction | CR | extendAddress; // RFCOMM Address + l2capoutbuf[1] = channelType | pfBit; // RFCOMM Control + l2capoutbuf[2] = 0x01; // Length = 0 + l2capoutbuf[3] = credit; // Credit + l2capoutbuf[4] = calcFcs(l2capoutbuf); #ifdef EXTRADEBUG - Notify(PSTR(" - RFCOMM Credit Data: "), 0x80); - for(uint8_t i = 0; i < 5; i++) { - Serial.print(l2capoutbuf[i],HEX); - Notify(PSTR(" "), 0x80); - } + Notify(PSTR(" - RFCOMM Credit Data: "), 0x80); + for (uint8_t i = 0; i < 5; i++) { + Serial.print(l2capoutbuf[i], HEX); + Notify(PSTR(" "), 0x80); + } #endif - RFCOMM_Command(l2capoutbuf,5); + RFCOMM_Command(l2capoutbuf, 5); } /* CRC on 2 bytes */ uint8_t SPP::__crc(uint8_t* data) { - return(pgm_read_byte(&rfcomm_crc_table[pgm_read_byte(&rfcomm_crc_table[0xff ^ data[0]]) ^ data[1]])); + return (pgm_read_byte(&rfcomm_crc_table[pgm_read_byte(&rfcomm_crc_table[0xff ^ data[0]]) ^ data[1]])); } /* Calculate FCS - we never actually check if the host sends correct FCS to the Arduino */ uint8_t SPP::calcFcs(uint8_t *data) { - if((data[1] & 0xEF) == RFCOMM_UIH) - return (0xff - __crc(data)); // FCS on 2 bytes - else - return (0xff - pgm_read_byte(&rfcomm_crc_table[__crc(data) ^ data[2]])); // FCS on 3 bytes + if ((data[1] & 0xEF) == RFCOMM_UIH) + return (0xff - __crc(data)); // FCS on 2 bytes + else + return (0xff - pgm_read_byte(&rfcomm_crc_table[__crc(data) ^ data[2]])); // FCS on 3 bytes } /* Serial commands */ void SPP::print(const String &str) { - if(!connected) - return; - uint8_t length = str.length(); - if(length > (sizeof(l2capoutbuf)-4)) - length = sizeof(l2capoutbuf)-4; - l2capoutbuf[0] = rfcommChannelConnection | 0 | 0 | extendAddress;; // RFCOMM Address - l2capoutbuf[1] = RFCOMM_UIH; // RFCOMM Control - l2capoutbuf[2] = length << 1 | 1; // Length - uint8_t i = 0; - for(; i < length; i++) - l2capoutbuf[i+3] = str[i]; - l2capoutbuf[i+3] = calcFcs(l2capoutbuf); + if (!connected) + return; + uint8_t length = str.length(); + if (length > (sizeof (l2capoutbuf) - 4)) + length = sizeof (l2capoutbuf) - 4; + l2capoutbuf[0] = rfcommChannelConnection | 0 | 0 | extendAddress; + ; // RFCOMM Address + l2capoutbuf[1] = RFCOMM_UIH; // RFCOMM Control + l2capoutbuf[2] = length << 1 | 1; // Length + uint8_t i = 0; + for (; i < length; i++) + l2capoutbuf[i + 3] = str[i]; + l2capoutbuf[i + 3] = calcFcs(l2capoutbuf); - RFCOMM_Command(l2capoutbuf,length+4); + RFCOMM_Command(l2capoutbuf, length + 4); } + void SPP::print(const char* str) { - if(!connected) - return; - uint8_t length = strlen(str); - if(length > (sizeof(l2capoutbuf)-4)) - length = sizeof(l2capoutbuf)-4; - l2capoutbuf[0] = rfcommChannelConnection | 0 | 0 | extendAddress;; // RFCOMM Address - l2capoutbuf[1] = RFCOMM_UIH; // RFCOMM Control - l2capoutbuf[2] = length << 1 | 1; // Length - uint8_t i = 0; - for(; i < length; i++) - l2capoutbuf[i+3] = str[i]; - l2capoutbuf[i+3] = calcFcs(l2capoutbuf); + if (!connected) + return; + uint8_t length = strlen(str); + if (length > (sizeof (l2capoutbuf) - 4)) + length = sizeof (l2capoutbuf) - 4; + l2capoutbuf[0] = rfcommChannelConnection | 0 | 0 | extendAddress; + ; // RFCOMM Address + l2capoutbuf[1] = RFCOMM_UIH; // RFCOMM Control + l2capoutbuf[2] = length << 1 | 1; // Length + uint8_t i = 0; + for (; i < length; i++) + l2capoutbuf[i + 3] = str[i]; + l2capoutbuf[i + 3] = calcFcs(l2capoutbuf); - RFCOMM_Command(l2capoutbuf,length+4); + RFCOMM_Command(l2capoutbuf, length + 4); } + void SPP::print(uint8_t* array, uint8_t length) { - if(!connected) - return; - if(length > (sizeof(l2capoutbuf)-4)) - length = sizeof(l2capoutbuf)-4; - l2capoutbuf[0] = rfcommChannelConnection | 0 | 0 | extendAddress;; // RFCOMM Address - l2capoutbuf[1] = RFCOMM_UIH; // RFCOMM Control - l2capoutbuf[2] = length << 1 | 1; // Length - uint8_t i = 0; - for(; i < length; i++) - l2capoutbuf[i+3] = array[i]; - l2capoutbuf[i+3] = calcFcs(l2capoutbuf); + if (!connected) + return; + if (length > (sizeof (l2capoutbuf) - 4)) + length = sizeof (l2capoutbuf) - 4; + l2capoutbuf[0] = rfcommChannelConnection | 0 | 0 | extendAddress; + ; // RFCOMM Address + l2capoutbuf[1] = RFCOMM_UIH; // RFCOMM Control + l2capoutbuf[2] = length << 1 | 1; // Length + uint8_t i = 0; + for (; i < length; i++) + l2capoutbuf[i + 3] = array[i]; + l2capoutbuf[i + 3] = calcFcs(l2capoutbuf); - RFCOMM_Command(l2capoutbuf,length+4); + RFCOMM_Command(l2capoutbuf, length + 4); } + void SPP::println(const String &str) { - String output = str + "\r\n"; - print(output); + String output = str + "\r\n"; + print(output); } + void SPP::println(const char* str) { - char output[strlen(str)+3]; - strcpy(output,str); - strcat(output,"\r\n"); - print(output); + char output[strlen(str) + 3]; + strcpy(output, str); + strcat(output, "\r\n"); + print(output); } + void SPP::println(uint8_t data) { - uint8_t buf[3] = {data, '\r', '\n'}; - print(buf,3); + uint8_t buf[3] = {data, '\r', '\n'}; + print(buf, 3); } + void SPP::println(uint8_t* array, uint8_t length) { - uint8_t buf[length+2]; - memcpy(buf,array,length); - buf[length] = '\r'; - buf[length+1] = '\n'; - print(buf,length+2); + uint8_t buf[length + 2]; + memcpy(buf, array, length); + buf[length] = '\r'; + buf[length + 1] = '\n'; + print(buf, length + 2); } + void SPP::printFlashString(const __FlashStringHelper *ifsh, bool newline) { - const char PROGMEM *p = (const char PROGMEM *)ifsh; - uint8_t size = 0; - while (1) { // Calculate the size of the string - uint8_t c = pgm_read_byte(p+size); - if (c == 0) - break; - size++; - } - uint8_t buf[size+2]; // Add two extra in case it needs to print a newline and carriage return + const char PROGMEM *p = (const char PROGMEM *)ifsh; + uint8_t size = 0; + while (1) { // Calculate the size of the string + uint8_t c = pgm_read_byte(p + size); + if (c == 0) + break; + size++; + } + uint8_t buf[size + 2]; // Add two extra in case it needs to print a newline and carriage return - for(uint8_t i = 0; i < size; i++) - buf[i] = pgm_read_byte(p++); + for (uint8_t i = 0; i < size; i++) + buf[i] = pgm_read_byte(p++); - if(newline) { - buf[size] = '\r'; - buf[size+1] = '\n'; - print(buf,size+2); - } else - print(buf,size); + if (newline) { + buf[size] = '\r'; + buf[size + 1] = '\n'; + print(buf, size + 2); + } else + print(buf, size); } + void SPP::println(void) { - uint8_t buf[2] = {'\r','\n'}; - print(buf,2); + uint8_t buf[2] = {'\r', '\n'}; + print(buf, 2); } /* These must be used to print numbers */ void SPP::printNumber(uint32_t n) { - char output[11]; - intToString(n,output); - print(output); + char output[11]; + intToString(n, output); + print(output); } + void SPP::printNumberln(uint32_t n) { - char output[13]; - intToString(n,output); - strcat(output,"\r\n"); - print(output); + char output[13]; + intToString(n, output); + strcat(output, "\r\n"); + print(output); } + void SPP::printNumber(int32_t n) { - char output[12]; - intToString(n,output); - print(output); + char output[12]; + intToString(n, output); + print(output); } + void SPP::printNumberln(int32_t n) { - char output[14]; - intToString(n,output); - strcat(output,"\r\n"); - print(output); + char output[14]; + intToString(n, output); + strcat(output, "\r\n"); + print(output); } + void SPP::intToString(int32_t input, char* output) { - if(input < 0) { - char buf[11]; - intToString((uint32_t)(input*-1),buf); - strcpy(output,"-"); - strcat(output,buf); - } else - intToString((uint32_t)input,output); + if (input < 0) { + char buf[11]; + intToString((uint32_t)(input*-1), buf); + strcpy(output, "-"); + strcat(output, buf); + } else + intToString((uint32_t)input, output); } + void SPP::intToString(uint32_t input, char* output) { - uint32_t temp = input; - uint8_t digits = 0; - while(temp) { - temp /= 10; - digits++; - } - if(digits == 0) - strcpy(output,"0"); - else { - for(uint8_t i = 1; i <= digits; i++) { - output[digits-i] = input%10 + '0'; // Get number and convert to ASCII Character - input /= 10; + uint32_t temp = input; + uint8_t digits = 0; + while (temp) { + temp /= 10; + digits++; + } + if (digits == 0) + strcpy(output, "0"); + else { + for (uint8_t i = 1; i <= digits; i++) { + output[digits - i] = input % 10 + '0'; // Get number and convert to ASCII Character + input /= 10; + } + output[digits] = '\0'; // Add null character } - output[digits] = '\0'; // Add null character - } } void SPP::printNumber(double n, uint8_t digits) { - char output[13+digits]; - doubleToString(n,output,digits); - print(output); + char output[13 + digits]; + doubleToString(n, output, digits); + print(output); } + void SPP::printNumberln(double n, uint8_t digits) { - char output[15+digits]; - doubleToString(n,output,digits); - strcat(output,"\r\n"); - print(output); + char output[15 + digits]; + doubleToString(n, output, digits); + strcat(output, "\r\n"); + print(output); } + void SPP::doubleToString(double input, char* output, uint8_t digits) { - char buffer[13+digits]; - if(input < 0) { - strcpy(output,"-"); - input = -input; - } - else - strcpy(output,""); + char buffer[13 + digits]; + if (input < 0) { + strcpy(output, "-"); + input = -input; + } else + strcpy(output, ""); - // Round correctly - double rounding = 0.5; - for (uint8_t i=0; i (sizeof(rfcommDataBuffer)-5)) { // We will send the command just before it runs out of credit - bytesRead = 0; - sendRfcommCredit(rfcommChannelConnection,rfcommDirection,0,RFCOMM_UIH,0x10,sizeof(rfcommDataBuffer)); // Send more credit + if (rfcommAvailable == 0) // Don't read if there is nothing in the buffer + return 0; + uint8_t output = rfcommDataBuffer[0]; + for (uint8_t i = 1; i < rfcommAvailable; i++) + rfcommDataBuffer[i - 1] = rfcommDataBuffer[i]; // Shift the buffer one left + rfcommAvailable--; + bytesRead++; + if (bytesRead > (sizeof (rfcommDataBuffer) - 5)) { // We will send the command just before it runs out of credit + bytesRead = 0; + sendRfcommCredit(rfcommChannelConnection, rfcommDirection, 0, RFCOMM_UIH, 0x10, sizeof (rfcommDataBuffer)); // Send more credit #ifdef EXTRADEBUG - Notify(PSTR("\r\nSent "), 0x80); - Serial.print(sizeof(rfcommDataBuffer)); - Notify(PSTR(" more credit"), 0x80); + Notify(PSTR("\r\nSent "), 0x80); + Serial.print(sizeof (rfcommDataBuffer)); + Notify(PSTR(" more credit"), 0x80); #endif - } - return output; + } + return output; } \ No newline at end of file diff --git a/SPP.h b/SPP.h index 070add5b..61a5a4c2 100644 --- a/SPP.h +++ b/SPP.h @@ -1,15 +1,15 @@ /* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved. - + This software may be distributed and modified under the terms of the GNU General Public License version 2 (GPL2) as published by the Free Software Foundation and appearing in the file GPL2.TXT included in the packaging of this file. Please note that GPL2 Section 2[b] requires that all works based on this software must also be made publicly available under the terms of the GPL2 ("Copyleft"). - + Contact information ------------------- - + Kristian Lauszus, TKJ Electronics Web : http://www.tkjelectronics.com e-mail : kristianl@tkjelectronics.com @@ -70,7 +70,7 @@ #define extendAddress 0x01 // Allways 1 -// Multiplexer message types +// Multiplexer message types #define BT_RFCOMM_PN_CMD 0x83 #define BT_RFCOMM_PN_RSP 0x81 #define BT_RFCOMM_MSC_CMD 0xE3 @@ -87,276 +87,310 @@ #define BT_RFCOMM_RLS_CMD 0x53 #define BT_RFCOMM_RLS_RSP 0x51 #define BT_RFCOMM_NSC_RSP 0x11 -*/ + */ /** This BluetoothService class implements the Serial Port Protocol (SPP). */ class SPP : public BluetoothService { public: - /** - * Constructor for the SPP class. - * @param p Pointer to BTD class instance. - * @param name Set the name to BTD#btdName. If argument is omitted, then "Arduino" will be used. - * @param pin Write the pin to BTD#btdPin. If argument is omitted, then "1234" will be used. - */ - SPP(BTD *p, const char* name = "Arduino", const char* pin = "1234"); + /** + * Constructor for the SPP class. + * @param p Pointer to BTD class instance. + * @param name Set the name to BTD#btdName. If argument is omitted, then "Arduino" will be used. + * @param pin Write the pin to BTD#btdPin. If argument is omitted, then "1234" will be used. + */ + SPP(BTD *p, const char* name = "Arduino", const char* pin = "1234"); - /** @name BluetoothService implementation */ - /** - * Used to pass acldata to the services. - * @param ACLData Incoming acldata. - */ - virtual void ACLData(uint8_t* ACLData); - /** Used to establish the connection automatically. */ - virtual void Run(); - /** Use this to reset the service. */ - virtual void Reset(); - /** Used this to disconnect the virtual serial port. */ - virtual void disconnect(); - /**@}*/ - - /** Variable used to indicate if the connection is established. */ - bool connected; - - /** @name Serial port profile (SPP) Print functions */ - /** - * Used to send Arduino String data type. - * @param str String to send. - */ - void print(const String &str); - /** - * Same as print(const String &str), but will include newline and carriage return. - * @param str String to send. - */ - void println(const String &str); - - /** - * Used to send standard strings. - * @param str String to send. - */ - void print(const char* str); - /** - * Same as print(const char* str), but will include newline and carriage return. - * @param str String to send. - */ - void println(const char* str); + /** @name BluetoothService implementation */ + /** + * Used to pass acldata to the services. + * @param ACLData Incoming acldata. + */ + virtual void ACLData(uint8_t* ACLData); + /** Used to establish the connection automatically. */ + virtual void Run(); + /** Use this to reset the service. */ + virtual void Reset(); + /** Used this to disconnect the virtual serial port. */ + virtual void disconnect(); + /**@}*/ - /** - * Used to send single bytes. - * @param data Data to send. - */ - void print(uint8_t data) { print(&data,1); }; - /** - * Same as print(uint8_t data), but will include newline and carriage return. - * @param data Data to send. - */ - void println(uint8_t data); + /** Variable used to indicate if the connection is established. */ + bool connected; - /** - * Used to send arrays. - * @param array Array to send. - * @param length Number of bytes to send. - */ - void print(uint8_t* array, uint8_t length); - /** - * Same as print(uint8_t* array, uint8_t length), but will include newline and carriage return. - * @param array Array to send. - * @param length Number of bytes to send. - */ - void println(uint8_t* array, uint8_t length); + /** @name Serial port profile (SPP) Print functions */ + /** + * Used to send Arduino String data type. + * @param str String to send. + */ + void print(const String &str); + /** + * Same as print(const String &str), but will include newline and carriage return. + * @param str String to send. + */ + void println(const String &str); - /** - * Used to print strings stored in flash. - * Use "SerialBT.print(F("String"));" to print a string stored in flash. - * @param ifsh String to send - see: http://playground.arduino.cc/Learning/Memory. - */ - void print(const __FlashStringHelper *ifsh) { printFlashString(ifsh,false); }; - /** - * Same as print(const __FlashStringHelper *ifsh), but will include newline and carriage return. - * @param ifsh String to send - see: http://playground.arduino.cc/Learning/Memory. - */ - void println(const __FlashStringHelper *ifsh) { printFlashString(ifsh,true); }; - /** - * Helper function to print a string stored in flash. - * @param ifsh String stored in flash you want to print. - * @param newline Set this to true to include newline and carriage return. - */ - void printFlashString(const __FlashStringHelper *ifsh, bool newline); + /** + * Used to send standard strings. + * @param str String to send. + */ + void print(const char* str); + /** + * Same as print(const char* str), but will include newline and carriage return. + * @param str String to send. + */ + void println(const char* str); + + /** + * Used to send single bytes. + * @param data Data to send. + */ + void print(uint8_t data) { + print(&data, 1); + }; + /** + * Same as print(uint8_t data), but will include newline and carriage return. + * @param data Data to send. + */ + void println(uint8_t data); + + /** + * Used to send arrays. + * @param array Array to send. + * @param length Number of bytes to send. + */ + void print(uint8_t* array, uint8_t length); + /** + * Same as print(uint8_t* array, uint8_t length), but will include newline and carriage return. + * @param array Array to send. + * @param length Number of bytes to send. + */ + void println(uint8_t* array, uint8_t length); + + /** + * Used to print strings stored in flash. + * Use "SerialBT.print(F("String"));" to print a string stored in flash. + * @param ifsh String to send - see: http://playground.arduino.cc/Learning/Memory. + */ + void print(const __FlashStringHelper *ifsh) { + printFlashString(ifsh, false); + }; + + /** + * Same as print(const __FlashStringHelper *ifsh), but will include newline and carriage return. + * @param ifsh String to send - see: http://playground.arduino.cc/Learning/Memory. + */ + void println(const __FlashStringHelper *ifsh) { + printFlashString(ifsh, true); + }; + /** + * Helper function to print a string stored in flash. + * @param ifsh String stored in flash you want to print. + * @param newline Set this to true to include newline and carriage return. + */ + void printFlashString(const __FlashStringHelper *ifsh, bool newline); - /** Use this to print newline and carriage return. */ - void println(void); + /** Use this to print newline and carriage return. */ + void println(void); - /** - * Used to print unsigned integers. - * @param n Unsigned integer to send. - */ - void printNumber(uint8_t n) { printNumber((uint32_t)n); }; - /** - * Same as printNumber(uint8_t n), but will include newline and carriage return. - * @param n Unsigned integer to send. - */ - void printNumberln(uint8_t n) { printNumberln((uint32_t)n); }; - /** - * Used to print signed integers. - * @param n Signed integer to send. - */ - void printNumber(int8_t n) { printNumber((int32_t)n); }; - /** - * Same as printNumber(int8_t n), but will include newline and carriage return. - * @param n Signed integer to send. - */ - void printNumberln(int8_t n) { printNumberln((int32_t)n); }; + /** + * Used to print unsigned integers. + * @param n Unsigned integer to send. + */ + void printNumber(uint8_t n) { + printNumber((uint32_t) n); + }; - /** - * Used to print unsigned integers. - * @param n Unsigned integer to send. - */ - void printNumber(uint16_t n) { printNumber((uint32_t)n); }; - /** - * Same as printNumber(uint16_t n), but will include newline and carriage return. - * @param n Unsigned integer to send. - */ - void printNumberln(uint16_t n) { printNumberln((uint32_t)n); }; - /** - * Used to print signed integers. - * @param n Signed integer to send. - */ - void printNumber(int16_t n) { printNumber((int32_t)n); }; - /** - * Same as printNumber(int16_t n), but will include newline and carriage return. - * @param n Signed integer to send. - */ - void printNumberln(int16_t n) { printNumberln((int32_t)n); }; + /** + * Same as printNumber(uint8_t n), but will include newline and carriage return. + * @param n Unsigned integer to send. + */ + void printNumberln(uint8_t n) { + printNumberln((uint32_t) n); + }; - /** - * Used to print unsigned integers. - * @param n Unsigned integer to send. - */ - void printNumber(uint32_t n); - /** - * Same as printNumber(uint32_t n), but will include newline and carriage return. - * @param n Unsigned integer to send. - */ - void printNumberln(uint32_t n); - - /** - * Used to print signed integers. - * @param n Signed integer to send. - */ - void printNumber(int32_t n); - /** - * Same as printNumber(int32_t n), but will include newline and carriage return. - * @param n Signed integer to send. - */ - void printNumberln(int32_t n); + /** + * Used to print signed integers. + * @param n Signed integer to send. + */ + void printNumber(int8_t n) { + printNumber((int32_t) n); + }; - /** - * Helper function to convert from an unsigned integer to a string. - * @param input Unsigned integer to convert. - * @param output Output buffer. - */ - void intToString(int32_t input, char* output); - /** - * Helper function to convert from a signed integer to a string. - * @param input Signed integer to convert. - * @param output Output buffer. - */ - void intToString(uint32_t input, char* output); + /** + * Same as printNumber(int8_t n), but will include newline and carriage return. + * @param n Signed integer to send. + */ + void printNumberln(int8_t n) { + printNumberln((int32_t) n); + }; + + /** + * Used to print unsigned integers. + * @param n Unsigned integer to send. + */ + void printNumber(uint16_t n) { + printNumber((uint32_t) n); + }; + + /** + * Same as printNumber(uint16_t n), but will include newline and carriage return. + * @param n Unsigned integer to send. + */ + void printNumberln(uint16_t n) { + printNumberln((uint32_t) n); + }; + + /** + * Used to print signed integers. + * @param n Signed integer to send. + */ + void printNumber(int16_t n) { + printNumber((int32_t) n); + }; + + /** + * Same as printNumber(int16_t n), but will include newline and carriage return. + * @param n Signed integer to send. + */ + void printNumberln(int16_t n) { + printNumberln((int32_t) n); + }; + + /** + * Used to print unsigned integers. + * @param n Unsigned integer to send. + */ + void printNumber(uint32_t n); + /** + * Same as printNumber(uint32_t n), but will include newline and carriage return. + * @param n Unsigned integer to send. + */ + void printNumberln(uint32_t n); + + /** + * Used to print signed integers. + * @param n Signed integer to send. + */ + void printNumber(int32_t n); + /** + * Same as printNumber(int32_t n), but will include newline and carriage return. + * @param n Signed integer to send. + */ + void printNumberln(int32_t n); + + /** + * Helper function to convert from an unsigned integer to a string. + * @param input Unsigned integer to convert. + * @param output Output buffer. + */ + void intToString(int32_t input, char* output); + /** + * Helper function to convert from a signed integer to a string. + * @param input Signed integer to convert. + * @param output Output buffer. + */ + void intToString(uint32_t input, char* output); + + /** + * Used to print floating-point numbers. + * @param n Floating-point number to print. + * @param digits Number of digits to send. If argument is omitted, then 2 digits will be used. + */ + void printNumber(double n, uint8_t digits = 2); + /** + * Same as printNumber(double n, uint8_t digits), but will include newline and carriage return. + * @param n Floating-point number to print. + * @param digits Number of digits to send. If argument is omitted, then 2 digits will be used. + */ + void printNumberln(double n, uint8_t digits = 2); + /** + * Helper function to convert from a double to a string. + * @param input Floating-point number to convert. + * @param output Output buffer. + * @param digits Number of digits to convert. If argument is omitted, then 2 digits will be used. + */ + void doubleToString(double input, char* output, uint8_t digits = 2); + + /** + * Get number of bytes waiting to be read. + * @return Return the number of bytes ready to be read. + */ + uint8_t available() { + return rfcommAvailable; + }; + /** + * Used to read the buffer. + * @return Return the byte. Will return 0 if no byte is available. + */ + uint8_t read(); + + /** Discard all the bytes in the buffer. */ + void flush() { + rfcommAvailable = 0; + }; + /**@}*/ - /** - * Used to print floating-point numbers. - * @param n Floating-point number to print. - * @param digits Number of digits to send. If argument is omitted, then 2 digits will be used. - */ - void printNumber(double n, uint8_t digits = 2); - /** - * Same as printNumber(double n, uint8_t digits), but will include newline and carriage return. - * @param n Floating-point number to print. - * @param digits Number of digits to send. If argument is omitted, then 2 digits will be used. - */ - void printNumberln(double n, uint8_t digits = 2); - /** - * Helper function to convert from a double to a string. - * @param input Floating-point number to convert. - * @param output Output buffer. - * @param digits Number of digits to convert. If argument is omitted, then 2 digits will be used. - */ - void doubleToString(double input, char* output, uint8_t digits = 2); - - /** - * Get number of bytes waiting to be read. - * @return Return the number of bytes ready to be read. - */ - uint8_t available() { return rfcommAvailable; }; - /** - * Used to read the buffer. - * @return Return the byte. Will return 0 if no byte is available. - */ - uint8_t read(); - /** Discard all the bytes in the buffer. */ - void flush() { rfcommAvailable = 0; }; - /**@}*/ - private: - /* Bluetooth dongle library pointer */ - BTD *pBtd; - - /* Set true when a channel is created */ - bool SDPConnected; - bool RFCOMMConnected; - - uint16_t hci_handle; // The HCI Handle for the connection - - /* Variables used by L2CAP state maschines */ - uint8_t l2cap_sdp_state; - uint8_t l2cap_rfcomm_state; - uint16_t l2cap_event_flag; // l2cap flags of received bluetooth events - - uint8_t l2capoutbuf[BULK_MAXPKTSIZE]; // General purpose buffer for l2cap out data - uint8_t rfcommbuf[10]; // Buffer for RFCOMM Commands - - /* L2CAP Channels */ - uint8_t sdp_scid[2]; // L2CAP source CID for SDP - uint8_t sdp_dcid[2]; // 0x0050 - uint8_t rfcomm_scid[2]; // L2CAP source CID for RFCOMM - uint8_t rfcomm_dcid[2]; // 0x0051 - uint8_t identifier; // Identifier for command + /* Bluetooth dongle library pointer */ + BTD *pBtd; - /* RFCOMM Variables */ - uint8_t rfcommChannel; - uint8_t rfcommChannelConnection; // This is the channel the SPP chanel will be running at - uint8_t rfcommDirection; - uint8_t rfcommCommandResponse; - uint8_t rfcommChannelType; - uint8_t rfcommPfBit; - - unsigned long timer; - bool waitForLastCommand; - bool creditSent; - - uint8_t rfcommDataBuffer[100]; // Create a 100 sized buffer for incoming data - uint8_t rfcommAvailable; - - bool firstMessage; // Used to see if it's the first SDP request received - uint8_t bytesRead; // Counter to see when it's time to send more credit - - /* State machines */ - void SDP_task(); // SDP state machine - void RFCOMM_task(); // RFCOMM state machine - - /* SDP Commands */ - void SDP_Command(uint8_t* data, uint8_t nbytes); - void serviceNotSupported(uint8_t transactionIDHigh, uint8_t transactionIDLow); - void serialPortResponse1(uint8_t transactionIDHigh, uint8_t transactionIDLow); - void serialPortResponse2(uint8_t transactionIDHigh, uint8_t transactionIDLow); - void l2capResponse1(uint8_t transactionIDHigh, uint8_t transactionIDLow); - void l2capResponse2(uint8_t transactionIDHigh, uint8_t transactionIDLow); - - /* RFCOMM Commands */ - void RFCOMM_Command(uint8_t* data, uint8_t nbytes); - void sendRfcomm(uint8_t channel, uint8_t direction, uint8_t CR, uint8_t channelType, uint8_t pfBit, uint8_t* data, uint8_t length); - void sendRfcommCredit(uint8_t channel, uint8_t direction, uint8_t CR, uint8_t channelType, uint8_t pfBit, uint8_t credit); - uint8_t calcFcs(uint8_t *data); - uint8_t __crc(uint8_t* data); + /* Set true when a channel is created */ + bool SDPConnected; + bool RFCOMMConnected; + + uint16_t hci_handle; // The HCI Handle for the connection + + /* Variables used by L2CAP state maschines */ + uint8_t l2cap_sdp_state; + uint8_t l2cap_rfcomm_state; + uint16_t l2cap_event_flag; // l2cap flags of received bluetooth events + + uint8_t l2capoutbuf[BULK_MAXPKTSIZE]; // General purpose buffer for l2cap out data + uint8_t rfcommbuf[10]; // Buffer for RFCOMM Commands + + /* L2CAP Channels */ + uint8_t sdp_scid[2]; // L2CAP source CID for SDP + uint8_t sdp_dcid[2]; // 0x0050 + uint8_t rfcomm_scid[2]; // L2CAP source CID for RFCOMM + uint8_t rfcomm_dcid[2]; // 0x0051 + uint8_t identifier; // Identifier for command + + /* RFCOMM Variables */ + uint8_t rfcommChannel; + uint8_t rfcommChannelConnection; // This is the channel the SPP chanel will be running at + uint8_t rfcommDirection; + uint8_t rfcommCommandResponse; + uint8_t rfcommChannelType; + uint8_t rfcommPfBit; + + unsigned long timer; + bool waitForLastCommand; + bool creditSent; + + uint8_t rfcommDataBuffer[100]; // Create a 100 sized buffer for incoming data + uint8_t rfcommAvailable; + + bool firstMessage; // Used to see if it's the first SDP request received + uint8_t bytesRead; // Counter to see when it's time to send more credit + + /* State machines */ + void SDP_task(); // SDP state machine + void RFCOMM_task(); // RFCOMM state machine + + /* SDP Commands */ + void SDP_Command(uint8_t* data, uint8_t nbytes); + void serviceNotSupported(uint8_t transactionIDHigh, uint8_t transactionIDLow); + void serialPortResponse1(uint8_t transactionIDHigh, uint8_t transactionIDLow); + void serialPortResponse2(uint8_t transactionIDHigh, uint8_t transactionIDLow); + void l2capResponse1(uint8_t transactionIDHigh, uint8_t transactionIDLow); + void l2capResponse2(uint8_t transactionIDHigh, uint8_t transactionIDLow); + + /* RFCOMM Commands */ + void RFCOMM_Command(uint8_t* data, uint8_t nbytes); + void sendRfcomm(uint8_t channel, uint8_t direction, uint8_t CR, uint8_t channelType, uint8_t pfBit, uint8_t* data, uint8_t length); + void sendRfcommCredit(uint8_t channel, uint8_t direction, uint8_t CR, uint8_t channelType, uint8_t pfBit, uint8_t credit); + uint8_t calcFcs(uint8_t *data); + uint8_t __crc(uint8_t* data); }; #endif \ No newline at end of file diff --git a/Usb.cpp b/Usb.cpp index 3a6ea5db..ec273f43 100644 --- a/Usb.cpp +++ b/Usb.cpp @@ -176,7 +176,7 @@ uint8_t USB::ctrlReq(uint8_t addr, uint8_t ep, uint8_t bmReqType, uint8_t bReque // Invoke callback function if inTransfer completed successfuly and callback function pointer is specified if (!rcode && p) - ((USBReadParser*) p)->Parse(read, dataptr, total - left); + ((USBReadParser*)p)->Parse(read, dataptr, total - left); left -= read; @@ -236,14 +236,14 @@ uint8_t USB::InTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t *nbytesptr, ui /* 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) { //printf("Problem! NO RCVDAVIRQ!\r\n"); - rcode = 0xf0; //receive error + rcode = 0xf0; //receive error break; } pktsize = regRd(rRCVBC); //number of received bytes //printf("Got %i bytes ", pktsize); assert(pktsize <= nbytes); - int16_t mem_left = (int16_t) nbytes - *((int16_t*) nbytesptr); + int16_t mem_left = (int16_t)nbytes - *((int16_t*)nbytesptr); if (mem_left < 0) mem_left = 0; @@ -591,7 +591,7 @@ uint8_t USB::getConfDescr(uint8_t addr, uint8_t ep, uint8_t conf, USBReadParser if (ret) return ret; - uint16_t total = ((USB_CONFIGURATION_DESCRIPTOR*) buf)->wTotalLength; + uint16_t total = ((USB_CONFIGURATION_DESCRIPTOR*)buf)->wTotalLength; //USBTRACE2("\r\ntotal conf.size:", total); diff --git a/Usb.h b/Usb.h index 15bc20f2..c27796d2 100644 --- a/Usb.h +++ b/Usb.h @@ -147,7 +147,7 @@ typedef struct { uint8_t recipient : 5; // Recipient of the request uint8_t type : 2; // Type of request uint8_t direction : 1; // Direction of data X-fer - }__attribute__((packed)); + } __attribute__((packed)); } ReqType_u; uint8_t bRequest; // 1 Request @@ -157,7 +157,7 @@ typedef struct { struct { uint8_t wValueLo; uint8_t wValueHi; - }__attribute__((packed)); + } __attribute__((packed)); } wVal_u; uint16_t wIndex; // 4 Depends on bRequest uint16_t wLength; // 6 Depends on bRequest @@ -190,12 +190,12 @@ public: }; AddressPool& GetAddressPool() { - return (AddressPool&) addrPool; + return(AddressPool&) addrPool; }; uint8_t RegisterDeviceClass(USBDeviceConfig *pdev) { - for (uint8_t i = 0; i < USB_NUMDEVICES; i++) { - if (!devConfig[i]) { + for(uint8_t i = 0; i < USB_NUMDEVICES; i++) { + if(!devConfig[i]) { devConfig[i] = pdev; return 0; } @@ -250,27 +250,27 @@ private: //get device descriptor 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 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 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 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 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)); } #endif // defined(USB_METHODS_INLINE) diff --git a/Wii.cpp b/Wii.cpp index c215bd54..a96e5a58 100755 --- a/Wii.cpp +++ b/Wii.cpp @@ -25,1030 +25,1037 @@ //#define PRINTREPORT // Uncomment to print the report send by the Wii controllers const uint8_t LEDS[] PROGMEM = { - 0x10, // LED1 - 0x20, // LED2 - 0x40, // LED3 - 0x80, // LED4 + 0x10, // LED1 + 0x20, // LED2 + 0x40, // LED3 + 0x80, // LED4 - 0x90, // LED5 - 0xA0, // LED6 - 0xC0, // LED7 - 0xD0, // LED8 - 0xE0, // LED9 - 0xF0 // LED10 - }; + 0x90, // LED5 + 0xA0, // LED6 + 0xC0, // LED7 + 0xD0, // LED8 + 0xE0, // LED9 + 0xF0 // LED10 +}; const uint32_t BUTTONS[] PROGMEM = { - 0x00008, // UP - 0x00002, // RIGHT - 0x00004, // DOWN - 0x00001, // LEFT + 0x00008, // UP + 0x00002, // RIGHT + 0x00004, // DOWN + 0x00001, // LEFT - 0, // Skip - 0x00010, // PLUS - 0x00100, // TWO - 0x00200, // ONE + 0, // Skip + 0x00010, // PLUS + 0x00100, // TWO + 0x00200, // ONE - 0x01000, // MINUS - 0x08000, // HOME - 0x10000, // Z - 0x20000, // C + 0x01000, // MINUS + 0x08000, // HOME + 0x10000, // Z + 0x20000, // C - 0x00400, // B - 0x00800 // A + 0x00400, // B + 0x00800 // A }; const uint32_t PROCONTROLLERBUTTONS[] PROGMEM = { - 0x00100, // UP - 0x00080, // RIGHT - 0x00040, // DOWN - 0x00200, // LEFT + 0x00100, // UP + 0x00080, // RIGHT + 0x00040, // DOWN + 0x00200, // LEFT - 0, // Skip - 0x00004, // PLUS - 0x20000, // L3 - 0x10000, // R3 + 0, // Skip + 0x00004, // PLUS + 0x20000, // L3 + 0x10000, // R3 - 0x00010, // MINUS - 0x00008, // HOME - 0,0, // Skip + 0x00010, // MINUS + 0x00008, // HOME + 0, 0, // Skip - 0x04000, // B - 0x01000, // A - 0x00800, // X - 0x02000, // Y + 0x04000, // B + 0x01000, // A + 0x00800, // X + 0x02000, // Y - 0x00020, // L - 0x00002, // R - 0x08000, // ZL - 0x00400 // ZR + 0x00020, // L + 0x00002, // R + 0x08000, // ZL + 0x00400 // ZR }; -WII::WII(BTD *p, bool pair): +WII::WII(BTD *p, bool pair) : pBtd(p) // pointer to USB class instance - mandatory { - if (pBtd) - pBtd->registerServiceClass(this); // Register it as a Bluetooth service + if (pBtd) + pBtd->registerServiceClass(this); // Register it as a Bluetooth service - pBtd->pairWithWii = pair; + pBtd->pairWithWii = pair; - HIDBuffer[0] = 0xA2;// HID BT DATA_request (0xA0) | Report Type (Output 0x02) + HIDBuffer[0] = 0xA2; // HID BT DATA_request (0xA0) | Report Type (Output 0x02) - /* Set device cid for the control and intterrupt channelse - LSB */ - control_dcid[0] = 0x60;//0x0060 - control_dcid[1] = 0x00; - interrupt_dcid[0] = 0x61;//0x0061 - interrupt_dcid[1] = 0x00; + /* Set device cid for the control and intterrupt channelse - LSB */ + control_dcid[0] = 0x60; //0x0060 + control_dcid[1] = 0x00; + interrupt_dcid[0] = 0x61; //0x0061 + interrupt_dcid[1] = 0x00; - Reset(); + Reset(); } + void WII::Reset() { - wiimoteConnected = false; - nunchuckConnected = false; - motionPlusConnected = false; - activateNunchuck = false; - motionValuesReset = false; - activeConnection = false; - pBtd->motionPlusInside = false; - pBtd->wiiUProController = false; - wiiUProControllerConnected = false; - l2cap_event_flag = 0; // Reset flags - l2cap_state = L2CAP_WAIT; + wiimoteConnected = false; + nunchuckConnected = false; + motionPlusConnected = false; + activateNunchuck = false; + motionValuesReset = false; + activeConnection = false; + pBtd->motionPlusInside = false; + pBtd->wiiUProController = false; + wiiUProControllerConnected = false; + l2cap_event_flag = 0; // Reset flags + l2cap_state = L2CAP_WAIT; } void WII::disconnect() { // Use this void to disconnect any of the controllers - if(motionPlusConnected && !pBtd->motionPlusInside) { // Disable the Motion Plus extension + if (motionPlusConnected && !pBtd->motionPlusInside) { // Disable the Motion Plus extension #ifdef DEBUG - Notify(PSTR("\r\nDeactivating Motion Plus"), 0x80); + Notify(PSTR("\r\nDeactivating Motion Plus"), 0x80); #endif - initExtension1(); // This will disable the Motion Plus extension - } - //First the HID interrupt channel has to be disconencted, then the HID control channel and finally the HCI connection - pBtd->l2cap_disconnection_request(hci_handle,0x0A, interrupt_scid, interrupt_dcid); - Reset(); - l2cap_state = L2CAP_INTERRUPT_DISCONNECT; + initExtension1(); // This will disable the Motion Plus extension + } + //First the HID interrupt channel has to be disconencted, then the HID control channel and finally the HCI connection + pBtd->l2cap_disconnection_request(hci_handle, 0x0A, interrupt_scid, interrupt_dcid); + Reset(); + l2cap_state = L2CAP_INTERRUPT_DISCONNECT; } void WII::ACLData(uint8_t* l2capinbuf) { - if(!pBtd->l2capConnectionClaimed && pBtd->incomingWii && !wiimoteConnected && !activeConnection) { - if (l2capinbuf[8] == L2CAP_CMD_CONNECTION_REQUEST) { - if((l2capinbuf[12] | (l2capinbuf[13] << 8)) == HID_CTRL_PSM) { - pBtd->incomingWii = false; - pBtd->l2capConnectionClaimed = true; // Claim that the incoming connection belongs to this service - activeConnection = true; - hci_handle = pBtd->hci_handle; // Store the HCI Handle for the connection - l2cap_state = L2CAP_WAIT; - } + if (!pBtd->l2capConnectionClaimed && pBtd->incomingWii && !wiimoteConnected && !activeConnection) { + if (l2capinbuf[8] == L2CAP_CMD_CONNECTION_REQUEST) { + if ((l2capinbuf[12] | (l2capinbuf[13] << 8)) == HID_CTRL_PSM) { + pBtd->incomingWii = false; + pBtd->l2capConnectionClaimed = true; // Claim that the incoming connection belongs to this service + activeConnection = true; + hci_handle = pBtd->hci_handle; // Store the HCI Handle for the connection + l2cap_state = L2CAP_WAIT; + } + } } - } - if ((l2capinbuf[0] | (l2capinbuf[1] << 8)) == (hci_handle | 0x2000)) { // acl_handle_ok or it's a new connection - if ((l2capinbuf[6] | (l2capinbuf[7] << 8)) == 0x0001) { //l2cap_control - Channel ID for ACL-U - if (l2capinbuf[8] == L2CAP_CMD_COMMAND_REJECT) { + if ((l2capinbuf[0] | (l2capinbuf[1] << 8)) == (hci_handle | 0x2000)) { // acl_handle_ok or it's a new connection + if ((l2capinbuf[6] | (l2capinbuf[7] << 8)) == 0x0001) { //l2cap_control - Channel ID for ACL-U + if (l2capinbuf[8] == L2CAP_CMD_COMMAND_REJECT) { #ifdef DEBUG - Notify(PSTR("\r\nL2CAP Command Rejected - Reason: "), 0x80); - PrintHex(l2capinbuf[13], 0x80); - Notify(PSTR(" "), 0x80); - PrintHex(l2capinbuf[12], 0x80); - Notify(PSTR(" "), 0x80); - PrintHex(l2capinbuf[17], 0x80); - Notify(PSTR(" "), 0x80); - PrintHex(l2capinbuf[16], 0x80); - Notify(PSTR(" "), 0x80); - PrintHex(l2capinbuf[15], 0x80); - Notify(PSTR(" "), 0x80); - PrintHex(l2capinbuf[14], 0x80); + Notify(PSTR("\r\nL2CAP Command Rejected - Reason: "), 0x80); + PrintHex (l2capinbuf[13], 0x80); + Notify(PSTR(" "), 0x80); + PrintHex (l2capinbuf[12], 0x80); + Notify(PSTR(" "), 0x80); + PrintHex (l2capinbuf[17], 0x80); + Notify(PSTR(" "), 0x80); + PrintHex (l2capinbuf[16], 0x80); + Notify(PSTR(" "), 0x80); + PrintHex (l2capinbuf[15], 0x80); + Notify(PSTR(" "), 0x80); + PrintHex (l2capinbuf[14], 0x80); #endif - } - else if (l2capinbuf[8] == L2CAP_CMD_CONNECTION_RESPONSE) { - if (((l2capinbuf[16] | (l2capinbuf[17] << 8)) == 0x0000) && ((l2capinbuf[18] | (l2capinbuf[19] << 8)) == SUCCESSFUL)) { // Success - if (l2capinbuf[14] == control_dcid[0] && l2capinbuf[15] == control_dcid[1]) { // Success - //Serial.print("\r\nHID Control Connection Complete"); - identifier = l2capinbuf[9]; - control_scid[0] = l2capinbuf[12]; - control_scid[1] = l2capinbuf[13]; - l2cap_event_flag |= L2CAP_FLAG_CONTROL_CONNECTED; - } - else if (l2capinbuf[14] == interrupt_dcid[0] && l2capinbuf[15] == interrupt_dcid[1]) { - //Serial.print("\r\nHID Interrupt Connection Complete"); - identifier = l2capinbuf[9]; - interrupt_scid[0] = l2capinbuf[12]; - interrupt_scid[1] = l2capinbuf[13]; - l2cap_event_flag |= L2CAP_FLAG_INTERRUPT_CONNECTED; - } - } - } - else if (l2capinbuf[8] == L2CAP_CMD_CONNECTION_REQUEST) { -#ifdef EXTRADEBUG - Notify(PSTR("\r\nL2CAP Connection Request - PSM: "), 0x80); - PrintHex(l2capinbuf[13], 0x80); - Notify(PSTR(" "), 0x80); - PrintHex(l2capinbuf[12], 0x80); - Notify(PSTR(" SCID: "), 0x80); - PrintHex(l2capinbuf[15], 0x80); - Notify(PSTR(" "), 0x80); - PrintHex(l2capinbuf[14], 0x80); - Notify(PSTR(" Identifier: "), 0x80); - PrintHex(l2capinbuf[9], 0x80); -#endif - if ((l2capinbuf[12] | (l2capinbuf[13] << 8)) == HID_CTRL_PSM) { - identifier = l2capinbuf[9]; - control_scid[0] = l2capinbuf[14]; - control_scid[1] = l2capinbuf[15]; - l2cap_event_flag |= L2CAP_FLAG_CONNECTION_CONTROL_REQUEST; - } - else if ((l2capinbuf[12] | (l2capinbuf[13] << 8)) == HID_INTR_PSM) { - identifier = l2capinbuf[9]; - interrupt_scid[0] = l2capinbuf[14]; - interrupt_scid[1] = l2capinbuf[15]; - l2cap_event_flag |= L2CAP_FLAG_CONNECTION_INTERRUPT_REQUEST; - } - } - else if (l2capinbuf[8] == L2CAP_CMD_CONFIG_RESPONSE) { - if ((l2capinbuf[16] | (l2capinbuf[17] << 8)) == 0x0000) { // Success - if (l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) { - //Serial.print("\r\nHID Control Configuration Complete"); - identifier = l2capinbuf[9]; - l2cap_event_flag |= L2CAP_FLAG_CONFIG_CONTROL_SUCCESS; - } - else if (l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) { - //Serial.print("\r\nHID Interrupt Configuration Complete"); - identifier = l2capinbuf[9]; - l2cap_event_flag |= L2CAP_FLAG_CONFIG_INTERRUPT_SUCCESS; - } - } - } - else if (l2capinbuf[8] == L2CAP_CMD_CONFIG_REQUEST) { - if (l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) { - //Serial.print("\r\nHID Control Configuration Request"); - pBtd->l2cap_config_response(hci_handle, l2capinbuf[9], control_scid); - } - else if (l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) { - //Serial.print("\r\nHID Interrupt Configuration Request"); - pBtd->l2cap_config_response(hci_handle, l2capinbuf[9], interrupt_scid); - } - } - else if (l2capinbuf[8] == L2CAP_CMD_DISCONNECT_REQUEST) { - if (l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) { -#ifdef DEBUG - Notify(PSTR("\r\nDisconnect Request: Control Channel"), 0x80); -#endif - identifier = l2capinbuf[9]; - pBtd->l2cap_disconnection_response(hci_handle,identifier,control_dcid,control_scid); - Reset(); - } - else if (l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) { -#ifdef DEBUG - Notify(PSTR("\r\nDisconnect Request: Interrupt Channel"), 0x80); -#endif - identifier = l2capinbuf[9]; - pBtd->l2cap_disconnection_response(hci_handle,identifier,interrupt_dcid,interrupt_scid); - Reset(); - } - } - else if (l2capinbuf[8] == L2CAP_CMD_DISCONNECT_RESPONSE) { - if (l2capinbuf[12] == control_scid[0] && l2capinbuf[13] == control_scid[1]) { - //Serial.print("\r\nDisconnect Response: Control Channel"); - identifier = l2capinbuf[9]; - l2cap_event_flag |= L2CAP_FLAG_DISCONNECT_CONTROL_RESPONSE; - } - else if (l2capinbuf[12] == interrupt_scid[0] && l2capinbuf[13] == interrupt_scid[1]) { - //Serial.print("\r\nDisconnect Response: Interrupt Channel"); - identifier = l2capinbuf[9]; - l2cap_event_flag |= L2CAP_FLAG_DISCONNECT_INTERRUPT_RESPONSE; - } - } -#ifdef EXTRADEBUG - else { - identifier = l2capinbuf[9]; - Notify(PSTR("\r\nL2CAP Unknown Signaling Command: "), 0x80); - PrintHex(l2capinbuf[8], 0x80); - } -#endif - } else if (l2capinbuf[6] == interrupt_dcid[0] && l2capinbuf[7] == interrupt_dcid[1]) { // l2cap_interrupt - //Serial.print("\r\nL2CAP Interrupt"); - if(wiimoteConnected) { - if(l2capinbuf[8] == 0xA1) { // HID_THDR_DATA_INPUT - if((l2capinbuf[9] >= 0x20 && l2capinbuf[9] <= 0x22) || (l2capinbuf[9] >= 0x30 && l2capinbuf[9] <= 0x37) || l2capinbuf[9] == 0x3e || l2capinbuf[9] == 0x3f) { // These reports include the buttons - if((l2capinbuf[9] >= 0x20 && l2capinbuf[9] <= 0x22) || l2capinbuf[9] == 0x31 || l2capinbuf[9] == 0x33) // These reports have no extensions bytes - ButtonState = (uint32_t)((l2capinbuf[10] & 0x1F) | ((uint16_t)(l2capinbuf[11] & 0x9F) << 8)); - else if(wiiUProControllerConnected) - ButtonState = (uint32_t)(((~l2capinbuf[23]) & 0xFE) | ((uint16_t)(~l2capinbuf[24]) << 8) | ((uint32_t)((~l2capinbuf[25]) & 0x03) << 16)); - else if(motionPlusConnected) { - if(l2capinbuf[20] & 0x02) // Only update the wiimote buttons, since the extension bytes are from the Motion Plus - ButtonState = (uint32_t)((l2capinbuf[10] & 0x1F) | ((uint16_t)(l2capinbuf[11] & 0x9F) << 8) | ((uint32_t)(ButtonState & 0xFFFF0000))); - else if (nunchuckConnected) // Update if it's a report from the Nunchuck - ButtonState = (uint32_t)((l2capinbuf[10] & 0x1F) | ((uint16_t)(l2capinbuf[11] & 0x9F) << 8) | ((uint32_t)((~l2capinbuf[20]) & 0x0C) << 14)); - //else if(classicControllerConnected) // Update if it's a report from the Classic Controller - } - else if(nunchuckConnected) // The Nunchuck is directly connected - ButtonState = (uint32_t)((l2capinbuf[10] & 0x1F) | ((uint16_t)(l2capinbuf[11] & 0x9F) << 8) | ((uint32_t)((~l2capinbuf[20]) & 0x03) << 16)); - //else if(classicControllerConnected) // The Classic Controller is directly connected - else if(!unknownExtensionConnected) - ButtonState = (uint32_t)((l2capinbuf[10] & 0x1F) | ((uint16_t)(l2capinbuf[11] & 0x9F) << 8)); -#ifdef PRINTREPORT - Notify(PSTR("ButtonState: "), 0x80); - PrintHex(ButtonState, 0x80); - Notify(PSTR("\r\n"), 0x80); -#endif - if(ButtonState != OldButtonState) { - ButtonClickState = ButtonState & ~OldButtonState; // Update click state variable - OldButtonState = ButtonState; - } - } - if(l2capinbuf[9] == 0x31 || l2capinbuf[9] == 0x33 || l2capinbuf[9] == 0x35 || l2capinbuf[9] == 0x37) { // Read the accelerometer - accX = ((l2capinbuf[12] << 2) | (l2capinbuf[10] & 0x60 >> 5))-500; - accY = ((l2capinbuf[13] << 2) | (l2capinbuf[11] & 0x20 >> 4))-500; - accZ = ((l2capinbuf[14] << 2) | (l2capinbuf[11] & 0x40 >> 5))-500; - wiimotePitch = (atan2(accY,accZ)+PI)*RAD_TO_DEG; - wiimoteRoll = (atan2(accX,accZ)+PI)*RAD_TO_DEG; - } - switch (l2capinbuf[9]) { - case 0x20: // Status Information - (a1) 20 BB BB LF 00 00 VV - wiiState = l2capinbuf[12]; // (0x01: Battery is nearly empty), (0x02: An Extension Controller is connected), (0x04: Speaker enabled), (0x08: IR enabled), (0x10: LED1, 0x20: LED2, 0x40: LED3, 0x80: LED4) - batteryLevel = l2capinbuf[15]; // Update battery level - if(l2capinbuf[12] & 0x01) { -#ifdef DEBUG - Notify(PSTR("\r\nWARNING: Battery is nearly empty"), 0x80); -#endif - } - if(l2capinbuf[12] & 0x02) { // Check if a extension is connected -#ifdef DEBUG - if(!unknownExtensionConnected) - Notify(PSTR("\r\nExtension connected"), 0x80); -#endif - unknownExtensionConnected = true; -#ifdef WIICAMERA - if(!isIRCameraEnabled()) // Don't activate the Motion Plus if we are trying to initialize the IR camera -#endif - setReportMode(false,0x35); // Also read the extension - } - else { -#ifdef DEBUG - Notify(PSTR("\r\nExtension disconnected"), 0x80); -#endif - if(motionPlusConnected) { -#ifdef DEBUG - Notify(PSTR(" - from Motion Plus"), 0x80); -#endif - l2cap_event_flag &= ~WII_FLAG_NUNCHUCK_CONNECTED; - if(!activateNunchuck) // If it's already trying to initialize the Nunchuck don't set it to false - nunchuckConnected = false; - //else if(classicControllerConnected) - } - else if(nunchuckConnected) { -#ifdef DEBUG - Notify(PSTR(" - Nunchuck"), 0x80); -#endif - nunchuckConnected = false; // It must be the Nunchuck controller then - l2cap_event_flag &= ~WII_FLAG_NUNCHUCK_CONNECTED; - setLedStatus(); - setReportMode(false,0x31); // If there is no extension connected we will read the button and accelerometer - } else { - setReportMode(false,0x31); // If there is no extension connected we will read the button and accelerometer - } - } - break; - case 0x21: // Read Memory Data - if((l2capinbuf[12] & 0x0F) == 0) { // No error - // See: http://wiibrew.org/wiki/Wiimote/Extension_Controllers - if(l2capinbuf[16] == 0x00 && l2capinbuf[17] == 0xA4 && l2capinbuf[18] == 0x20 && l2capinbuf[19] == 0x00 && l2capinbuf[20] == 0x00) { -#ifdef DEBUG - Notify(PSTR("\r\nNunchuck connected"), 0x80); -#endif - l2cap_event_flag |= WII_FLAG_NUNCHUCK_CONNECTED; - } else if(l2capinbuf[16] == 0x00 && (l2capinbuf[17] == 0xA6 || l2capinbuf[17] == 0xA4) && l2capinbuf[18] == 0x20 && l2capinbuf[19] == 0x00 && l2capinbuf[20] == 0x05) { -#ifdef DEBUG - Notify(PSTR("\r\nMotion Plus connected"), 0x80); -#endif - l2cap_event_flag |= WII_FLAG_MOTION_PLUS_CONNECTED; - } else if(l2capinbuf[16] == 0x00 && l2capinbuf[17] == 0xA4 && l2capinbuf[18] == 0x20 && l2capinbuf[19] == 0x04 && l2capinbuf[20] == 0x05) { -#ifdef DEBUG - Notify(PSTR("\r\nMotion Plus activated in normal mode"), 0x80); -#endif - motionPlusConnected = true; - } else if(l2capinbuf[16] == 0x00 && l2capinbuf[17] == 0xA4 && l2capinbuf[18] == 0x20 && l2capinbuf[19] == 0x05 && l2capinbuf[20] == 0x05) { -#ifdef DEBUG - Notify(PSTR("\r\nMotion Plus activated in Nunchuck pass-through mode"), 0x80); -#endif - activateNunchuck = false; - motionPlusConnected = true; - nunchuckConnected = true; - } else if(l2capinbuf[16] == 0x00 && l2capinbuf[17] == 0xA6 && l2capinbuf[18] == 0x20 && (l2capinbuf[19] == 0x00 || l2capinbuf[19] == 0x04 || l2capinbuf[19] == 0x05 || l2capinbuf[19] == 0x07) && l2capinbuf[20] == 0x05) { -#ifdef DEBUG - Notify(PSTR("\r\nInactive Wii Motion Plus"), 0x80); - Notify(PSTR("\r\nPlease unplug the Motion Plus, disconnect the Wiimote and then replug the Motion Plus Extension"), 0x80); -#endif - stateCounter = 300; // Skip the rest in "L2CAP_CHECK_MOTION_PLUS_STATE" - } else if(l2capinbuf[16] == 0x00 && l2capinbuf[17] == 0xA4 && l2capinbuf[18] == 0x20 && l2capinbuf[19] == 0x01 && l2capinbuf[20] == 0x20) { -#ifdef DEBUG - Notify(PSTR("\r\nWii U Pro Controller connected"), 0x80); -#endif - wiiUProControllerConnected = true; - } -#ifdef DEBUG - else { - Notify(PSTR("\r\nUnknown Device: "), 0x80); - PrintHex(l2capinbuf[13], 0x80); - PrintHex(l2capinbuf[14], 0x80); - Notify(PSTR("\r\nData: "), 0x80); - for(uint8_t i = 0; i < ((l2capinbuf[12] >> 4)+1); i++) { // bit 4-7 is the length-1 - PrintHex(l2capinbuf[15+i], 0x80); - Notify(PSTR(" "), 0x80); - } - } -#endif - } -#ifdef EXTRADEBUG - else { - Notify(PSTR("\r\nReport Error: "), 0x80); - PrintHex(l2capinbuf[13], 0x80); - PrintHex(l2capinbuf[14], 0x80); - } -#endif - break; - case 0x22: // Acknowledge output report, return function result -#ifdef DEBUG - if(l2capinbuf[13] != 0x00) { // Check if there is an error - Notify(PSTR("\r\nCommand failed: "), 0x80); - PrintHex(l2capinbuf[12], 0x80); - } -#endif - break; - case 0x30: // Core buttons - (a1) 30 BB BB - break; - case 0x31: // Core Buttons and Accelerometer - (a1) 31 BB BB AA AA AA - pitch = wiimotePitch; // The pitch is just equal to the angle calculated from the wiimote as there is no Motion Plus connected - roll = wiimoteRoll; - break; - case 0x32: // Core Buttons with 8 Extension bytes - (a1) 32 BB BB EE EE EE EE EE EE EE EE - break; - case 0x33: // Core Buttons with Accelerometer and 12 IR bytes - (a1) 33 BB BB AA AA AA II II II II II II II II II II II II - pitch = wiimotePitch; // The pitch is just equal to the angle calculated from the wiimote as there is no Motion Plus data available - roll = wiimoteRoll; -#ifdef WIICAMERA - // Read the IR data - IR_object_x1 = (l2capinbuf[15] | ((uint16_t)(l2capinbuf[17] & 0x30) << 4)); // x position - IR_object_y1 = (l2capinbuf[16] | ((uint16_t)(l2capinbuf[17] & 0xC0) << 2)); // y position - IR_object_s1 = (l2capinbuf[17] & 0x0F); // size value, 0-15 - - IR_object_x2 = (l2capinbuf[18] | ((uint16_t)(l2capinbuf[20] & 0x30) << 4)); - IR_object_y2 = (l2capinbuf[19] | ((uint16_t)(l2capinbuf[20] & 0xC0) << 2)); - IR_object_s2 = (l2capinbuf[20] & 0x0F); - - IR_object_x3 = (l2capinbuf[21] | ((uint16_t)(l2capinbuf[23] & 0x30) << 4)); - IR_object_y3 = (l2capinbuf[22] | ((uint16_t)(l2capinbuf[23] & 0xC0) << 2)); - IR_object_s3 = (l2capinbuf[23] & 0x0F); - - IR_object_x4 = (l2capinbuf[24] | ((uint16_t)(l2capinbuf[26] & 0x30) << 4)); - IR_object_y4 = (l2capinbuf[25] | ((uint16_t)(l2capinbuf[26] & 0xC0) << 2)); - IR_object_s4 = (l2capinbuf[26] & 0x0F); -#endif - break; - case 0x34: // Core Buttons with 19 Extension bytes - (a1) 34 BB BB EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE - break; - /* 0x3e and 0x3f both give unknown report types when report mode is 0x3e or 0x3f with mode number 0x05 */ - case 0x3E: // Core Buttons with Accelerometer and 32 IR bytes - // (a1) 31 BB BB AA AA AA II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II - // corresponds to output report mode 0x3e - - /**** for reading in full mode: DOES NOT WORK YET ****/ - /* When it works it will also have intensity and bounding box data */ - /* - IR_object_x1 = (l2capinbuf[13] | ((uint16_t)(l2capinbuf[15] & 0x30) << 4)); - IR_object_y1 = (l2capinbuf[14] | ((uint16_t)(l2capinbuf[15] & 0xC0) << 2)); - IR_object_s1 = (l2capinbuf[15] & 0x0F); - */ - break; - case 0x3F: - /* - IR_object_x1 = (l2capinbuf[13] | ((uint16_t)(l2capinbuf[15] & 0x30) << 4)); - IR_object_y1 = (l2capinbuf[14] | ((uint16_t)(l2capinbuf[15] & 0xC0) << 2)); - IR_object_s1 = (l2capinbuf[15] & 0x0F); - */ - break; - case 0x35: // Core Buttons and Accelerometer with 16 Extension Bytes - // (a1) 35 BB BB AA AA AA EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE - if(motionPlusConnected) { - if(l2capinbuf[20] & 0x02) { // Check if it's a report from the Motion controller or the extension - if(motionValuesReset) { // We will only use the values when the gyro value has been set - gyroYawRaw = ((l2capinbuf[15] | ((l2capinbuf[18] & 0xFC) << 6))-gyroYawZero); - gyroRollRaw = ((l2capinbuf[16] | ((l2capinbuf[19] & 0xFC) << 6))-gyroRollZero); - gyroPitchRaw = ((l2capinbuf[17] | ((l2capinbuf[20] & 0xFC) << 6))-gyroPitchZero); - - yawGyroSpeed = (double)gyroYawRaw/((double)gyroYawZero/yawGyroScale); - rollGyroSpeed = -(double)gyroRollRaw/((double)gyroRollZero/rollGyroScale); // We invert these values so they will fit the acc values - pitchGyroSpeed = (double)gyroPitchRaw/((double)gyroPitchZero/pitchGyroScale); - - /* The onboard gyro has two ranges for slow and fast mode */ - if(!(l2capinbuf[18] & 0x02)) // Check if fast more is used - yawGyroSpeed *= 4.545; - if(!(l2capinbuf[18] & 0x01)) // Check if fast more is used - pitchGyroSpeed *= 4.545; - if(!(l2capinbuf[19] & 0x02)) // Check if fast more is used - rollGyroSpeed *= 4.545; - - pitch = (0.93*(pitch+(pitchGyroSpeed*(double)(micros()-timer)/1000000)))+(0.07*wiimotePitch); // Use a complimentary filter to calculate the angle - roll = (0.93*(roll+(rollGyroSpeed*(double)(micros()-timer)/1000000)))+(0.07*wiimoteRoll); - - gyroYaw += (yawGyroSpeed*((double)(micros()-timer)/1000000)); - gyroRoll += (rollGyroSpeed*((double)(micros()-timer)/1000000)); - gyroPitch += (pitchGyroSpeed*((double)(micros()-timer)/1000000)); - timer = micros(); - /* - // Uncomment these lines to tune the gyro scale variabels - Serial.print("\r\ngyroYaw: "); - Serial.print(gyroYaw); - Serial.print("\tgyroRoll: "); - Serial.print(gyroRoll); - Serial.print("\tgyroPitch: "); - Serial.print(gyroPitch); - */ - /* - Serial.print("\twiimoteRoll: "); - Serial.print(wiimoteRoll); - Serial.print("\twiimotePitch: "); - Serial.print(wiimotePitch); - */ - } else { - if((micros() - timer) > 1000000) { // Loop for 1 sec before resetting the values -#ifdef DEBUG - Notify(PSTR("\r\nThe gyro values has been reset"), 0x80); -#endif - gyroYawZero = (l2capinbuf[15] | ((l2capinbuf[18] & 0xFC) << 6)); - gyroRollZero = (l2capinbuf[16] | ((l2capinbuf[19] & 0xFC) << 6)); - gyroPitchZero = (l2capinbuf[17] | ((l2capinbuf[20] & 0xFC) << 6)); - - rollGyroScale = 500; // You might need to adjust these - pitchGyroScale = 400; - yawGyroScale = 415; - - gyroYaw = 0; - gyroRoll = 0; - gyroPitch = 0; - - motionValuesReset = true; - timer = micros(); + } else if (l2capinbuf[8] == L2CAP_CMD_CONNECTION_RESPONSE) { + if (((l2capinbuf[16] | (l2capinbuf[17] << 8)) == 0x0000) && ((l2capinbuf[18] | (l2capinbuf[19] << 8)) == SUCCESSFUL)) { // Success + if (l2capinbuf[14] == control_dcid[0] && l2capinbuf[15] == control_dcid[1]) { // Success + //Serial.print("\r\nHID Control Connection Complete"); + identifier = l2capinbuf[9]; + control_scid[0] = l2capinbuf[12]; + control_scid[1] = l2capinbuf[13]; + l2cap_event_flag |= L2CAP_FLAG_CONTROL_CONNECTED; + } else if (l2capinbuf[14] == interrupt_dcid[0] && l2capinbuf[15] == interrupt_dcid[1]) { + //Serial.print("\r\nHID Interrupt Connection Complete"); + identifier = l2capinbuf[9]; + interrupt_scid[0] = l2capinbuf[12]; + interrupt_scid[1] = l2capinbuf[13]; + l2cap_event_flag |= L2CAP_FLAG_INTERRUPT_CONNECTED; } - } - } else { - if(nunchuckConnected) { - hatValues[HatX] = l2capinbuf[15]; - hatValues[HatY] = l2capinbuf[16]; - accX = ((l2capinbuf[17] << 2) | (l2capinbuf[20] & 0x10 >> 3))-416; - accY = ((l2capinbuf[18] << 2) | (l2capinbuf[20] & 0x20 >> 4))-416; - accZ = (((l2capinbuf[19] & 0xFE) << 2) | (l2capinbuf[20] & 0xC0 >> 5))-416; - nunchuckPitch = (atan2(accY,accZ)+PI)*RAD_TO_DEG; - nunchuckRoll = (atan2(accX,accZ)+PI)*RAD_TO_DEG; - } - //else if(classicControllerConnected) { } } - if(l2capinbuf[19] & 0x01) { - if(!extensionConnected) { - extensionConnected = true; - unknownExtensionConnected = true; -#ifdef DEBUG - Notify(PSTR("\r\nExtension connected to Motion Plus"), 0x80); + } else if (l2capinbuf[8] == L2CAP_CMD_CONNECTION_REQUEST) { +#ifdef EXTRADEBUG + Notify(PSTR("\r\nL2CAP Connection Request - PSM: "), 0x80); + PrintHex (l2capinbuf[13], 0x80); + Notify(PSTR(" "), 0x80); + PrintHex (l2capinbuf[12], 0x80); + Notify(PSTR(" SCID: "), 0x80); + PrintHex (l2capinbuf[15], 0x80); + Notify(PSTR(" "), 0x80); + PrintHex (l2capinbuf[14], 0x80); + Notify(PSTR(" Identifier: "), 0x80); + PrintHex (l2capinbuf[9], 0x80); #endif - } + if ((l2capinbuf[12] | (l2capinbuf[13] << 8)) == HID_CTRL_PSM) { + identifier = l2capinbuf[9]; + control_scid[0] = l2capinbuf[14]; + control_scid[1] = l2capinbuf[15]; + l2cap_event_flag |= L2CAP_FLAG_CONNECTION_CONTROL_REQUEST; + } else if ((l2capinbuf[12] | (l2capinbuf[13] << 8)) == HID_INTR_PSM) { + identifier = l2capinbuf[9]; + interrupt_scid[0] = l2capinbuf[14]; + interrupt_scid[1] = l2capinbuf[15]; + l2cap_event_flag |= L2CAP_FLAG_CONNECTION_INTERRUPT_REQUEST; } - else { - if(extensionConnected && !unknownExtensionConnected) { - extensionConnected = false; - unknownExtensionConnected = true; + } else if (l2capinbuf[8] == L2CAP_CMD_CONFIG_RESPONSE) { + if ((l2capinbuf[16] | (l2capinbuf[17] << 8)) == 0x0000) { // Success + if (l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) { + //Serial.print("\r\nHID Control Configuration Complete"); + identifier = l2capinbuf[9]; + l2cap_event_flag |= L2CAP_FLAG_CONFIG_CONTROL_SUCCESS; + } else if (l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) { + //Serial.print("\r\nHID Interrupt Configuration Complete"); + identifier = l2capinbuf[9]; + l2cap_event_flag |= L2CAP_FLAG_CONFIG_INTERRUPT_SUCCESS; + } + } + } else if (l2capinbuf[8] == L2CAP_CMD_CONFIG_REQUEST) { + if (l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) { + //Serial.print("\r\nHID Control Configuration Request"); + pBtd->l2cap_config_response(hci_handle, l2capinbuf[9], control_scid); + } else if (l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) { + //Serial.print("\r\nHID Interrupt Configuration Request"); + pBtd->l2cap_config_response(hci_handle, l2capinbuf[9], interrupt_scid); + } + } else if (l2capinbuf[8] == L2CAP_CMD_DISCONNECT_REQUEST) { + if (l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) { #ifdef DEBUG - Notify(PSTR("\r\nExtension disconnected from Motion Plus"), 0x80); + Notify(PSTR("\r\nDisconnect Request: Control Channel"), 0x80); #endif - nunchuckConnected = false; // There is no extension connected to the Motion Plus if this report is sent - } + identifier = l2capinbuf[9]; + pBtd->l2cap_disconnection_response(hci_handle, identifier, control_dcid, control_scid); + Reset(); + } else if (l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) { +#ifdef DEBUG + Notify(PSTR("\r\nDisconnect Request: Interrupt Channel"), 0x80); +#endif + identifier = l2capinbuf[9]; + pBtd->l2cap_disconnection_response(hci_handle, identifier, interrupt_dcid, interrupt_scid); + Reset(); } + } else if (l2capinbuf[8] == L2CAP_CMD_DISCONNECT_RESPONSE) { + if (l2capinbuf[12] == control_scid[0] && l2capinbuf[13] == control_scid[1]) { + //Serial.print("\r\nDisconnect Response: Control Channel"); + identifier = l2capinbuf[9]; + l2cap_event_flag |= L2CAP_FLAG_DISCONNECT_CONTROL_RESPONSE; + } else if (l2capinbuf[12] == interrupt_scid[0] && l2capinbuf[13] == interrupt_scid[1]) { + //Serial.print("\r\nDisconnect Response: Interrupt Channel"); + identifier = l2capinbuf[9]; + l2cap_event_flag |= L2CAP_FLAG_DISCONNECT_INTERRUPT_RESPONSE; + } + } +#ifdef EXTRADEBUG + else { + identifier = l2capinbuf[9]; + Notify(PSTR("\r\nL2CAP Unknown Signaling Command: "), 0x80); + PrintHex (l2capinbuf[8], 0x80); + } +#endif + } else if (l2capinbuf[6] == interrupt_dcid[0] && l2capinbuf[7] == interrupt_dcid[1]) { // l2cap_interrupt + //Serial.print("\r\nL2CAP Interrupt"); + if (wiimoteConnected) { + if (l2capinbuf[8] == 0xA1) { // HID_THDR_DATA_INPUT + if ((l2capinbuf[9] >= 0x20 && l2capinbuf[9] <= 0x22) || (l2capinbuf[9] >= 0x30 && l2capinbuf[9] <= 0x37) || l2capinbuf[9] == 0x3e || l2capinbuf[9] == 0x3f) { // These reports include the buttons + if ((l2capinbuf[9] >= 0x20 && l2capinbuf[9] <= 0x22) || l2capinbuf[9] == 0x31 || l2capinbuf[9] == 0x33) // These reports have no extensions bytes + ButtonState = (uint32_t)((l2capinbuf[10] & 0x1F) | ((uint16_t)(l2capinbuf[11] & 0x9F) << 8)); + else if (wiiUProControllerConnected) + ButtonState = (uint32_t)(((~l2capinbuf[23]) & 0xFE) | ((uint16_t)(~l2capinbuf[24]) << 8) | ((uint32_t)((~l2capinbuf[25]) & 0x03) << 16)); + else if (motionPlusConnected) { + if (l2capinbuf[20] & 0x02) // Only update the wiimote buttons, since the extension bytes are from the Motion Plus + ButtonState = (uint32_t)((l2capinbuf[10] & 0x1F) | ((uint16_t)(l2capinbuf[11] & 0x9F) << 8) | ((uint32_t)(ButtonState & 0xFFFF0000))); + else if (nunchuckConnected) // Update if it's a report from the Nunchuck + ButtonState = (uint32_t)((l2capinbuf[10] & 0x1F) | ((uint16_t)(l2capinbuf[11] & 0x9F) << 8) | ((uint32_t)((~l2capinbuf[20]) & 0x0C) << 14)); + //else if(classicControllerConnected) // Update if it's a report from the Classic Controller + } else if (nunchuckConnected) // The Nunchuck is directly connected + ButtonState = (uint32_t)((l2capinbuf[10] & 0x1F) | ((uint16_t)(l2capinbuf[11] & 0x9F) << 8) | ((uint32_t)((~l2capinbuf[20]) & 0x03) << 16)); + //else if(classicControllerConnected) // The Classic Controller is directly connected + else if (!unknownExtensionConnected) + ButtonState = (uint32_t)((l2capinbuf[10] & 0x1F) | ((uint16_t)(l2capinbuf[11] & 0x9F) << 8)); +#ifdef PRINTREPORT + Notify(PSTR("ButtonState: "), 0x80); + PrintHex (ButtonState, 0x80); + Notify(PSTR("\r\n"), 0x80); +#endif + if (ButtonState != OldButtonState) { + ButtonClickState = ButtonState & ~OldButtonState; // Update click state variable + OldButtonState = ButtonState; + } + } + if (l2capinbuf[9] == 0x31 || l2capinbuf[9] == 0x33 || l2capinbuf[9] == 0x35 || l2capinbuf[9] == 0x37) { // Read the accelerometer + accX = ((l2capinbuf[12] << 2) | (l2capinbuf[10] & 0x60 >> 5)) - 500; + accY = ((l2capinbuf[13] << 2) | (l2capinbuf[11] & 0x20 >> 4)) - 500; + accZ = ((l2capinbuf[14] << 2) | (l2capinbuf[11] & 0x40 >> 5)) - 500; + wiimotePitch = (atan2(accY, accZ) + PI) * RAD_TO_DEG; + wiimoteRoll = (atan2(accX, accZ) + PI) * RAD_TO_DEG; + } + switch (l2capinbuf[9]) { + case 0x20: // Status Information - (a1) 20 BB BB LF 00 00 VV + wiiState = l2capinbuf[12]; // (0x01: Battery is nearly empty), (0x02: An Extension Controller is connected), (0x04: Speaker enabled), (0x08: IR enabled), (0x10: LED1, 0x20: LED2, 0x40: LED3, 0x80: LED4) + batteryLevel = l2capinbuf[15]; // Update battery level + if (l2capinbuf[12] & 0x01) { +#ifdef DEBUG + Notify(PSTR("\r\nWARNING: Battery is nearly empty"), 0x80); +#endif + } + if (l2capinbuf[12] & 0x02) { // Check if a extension is connected +#ifdef DEBUG + if (!unknownExtensionConnected) + Notify(PSTR("\r\nExtension connected"), 0x80); +#endif + unknownExtensionConnected = true; +#ifdef WIICAMERA + if (!isIRCameraEnabled()) // Don't activate the Motion Plus if we are trying to initialize the IR camera +#endif + setReportMode(false, 0x35); // Also read the extension + } else { +#ifdef DEBUG + Notify(PSTR("\r\nExtension disconnected"), 0x80); +#endif + if (motionPlusConnected) { +#ifdef DEBUG + Notify(PSTR(" - from Motion Plus"), 0x80); +#endif + l2cap_event_flag &= ~WII_FLAG_NUNCHUCK_CONNECTED; + if (!activateNunchuck) // If it's already trying to initialize the Nunchuck don't set it to false + nunchuckConnected = false; + //else if(classicControllerConnected) + } else if (nunchuckConnected) { +#ifdef DEBUG + Notify(PSTR(" - Nunchuck"), 0x80); +#endif + nunchuckConnected = false; // It must be the Nunchuck controller then + l2cap_event_flag &= ~WII_FLAG_NUNCHUCK_CONNECTED; + setLedStatus(); + setReportMode(false, 0x31); // If there is no extension connected we will read the button and accelerometer + } else { + setReportMode(false, 0x31); // If there is no extension connected we will read the button and accelerometer + } + } + break; + case 0x21: // Read Memory Data + if ((l2capinbuf[12] & 0x0F) == 0) { // No error + // See: http://wiibrew.org/wiki/Wiimote/Extension_Controllers + if (l2capinbuf[16] == 0x00 && l2capinbuf[17] == 0xA4 && l2capinbuf[18] == 0x20 && l2capinbuf[19] == 0x00 && l2capinbuf[20] == 0x00) { +#ifdef DEBUG + Notify(PSTR("\r\nNunchuck connected"), 0x80); +#endif + l2cap_event_flag |= WII_FLAG_NUNCHUCK_CONNECTED; + } else if (l2capinbuf[16] == 0x00 && (l2capinbuf[17] == 0xA6 || l2capinbuf[17] == 0xA4) && l2capinbuf[18] == 0x20 && l2capinbuf[19] == 0x00 && l2capinbuf[20] == 0x05) { +#ifdef DEBUG + Notify(PSTR("\r\nMotion Plus connected"), 0x80); +#endif + l2cap_event_flag |= WII_FLAG_MOTION_PLUS_CONNECTED; + } else if (l2capinbuf[16] == 0x00 && l2capinbuf[17] == 0xA4 && l2capinbuf[18] == 0x20 && l2capinbuf[19] == 0x04 && l2capinbuf[20] == 0x05) { +#ifdef DEBUG + Notify(PSTR("\r\nMotion Plus activated in normal mode"), 0x80); +#endif + motionPlusConnected = true; + } else if (l2capinbuf[16] == 0x00 && l2capinbuf[17] == 0xA4 && l2capinbuf[18] == 0x20 && l2capinbuf[19] == 0x05 && l2capinbuf[20] == 0x05) { +#ifdef DEBUG + Notify(PSTR("\r\nMotion Plus activated in Nunchuck pass-through mode"), 0x80); +#endif + activateNunchuck = false; + motionPlusConnected = true; + nunchuckConnected = true; + } else if (l2capinbuf[16] == 0x00 && l2capinbuf[17] == 0xA6 && l2capinbuf[18] == 0x20 && (l2capinbuf[19] == 0x00 || l2capinbuf[19] == 0x04 || l2capinbuf[19] == 0x05 || l2capinbuf[19] == 0x07) && l2capinbuf[20] == 0x05) { +#ifdef DEBUG + Notify(PSTR("\r\nInactive Wii Motion Plus"), 0x80); + Notify(PSTR("\r\nPlease unplug the Motion Plus, disconnect the Wiimote and then replug the Motion Plus Extension"), 0x80); +#endif + stateCounter = 300; // Skip the rest in "L2CAP_CHECK_MOTION_PLUS_STATE" + } else if (l2capinbuf[16] == 0x00 && l2capinbuf[17] == 0xA4 && l2capinbuf[18] == 0x20 && l2capinbuf[19] == 0x01 && l2capinbuf[20] == 0x20) { +#ifdef DEBUG + Notify(PSTR("\r\nWii U Pro Controller connected"), 0x80); +#endif + wiiUProControllerConnected = true; + } +#ifdef DEBUG + else { + Notify(PSTR("\r\nUnknown Device: "), 0x80); + PrintHex (l2capinbuf[13], 0x80); + PrintHex (l2capinbuf[14], 0x80); + Notify(PSTR("\r\nData: "), 0x80); + for (uint8_t i = 0; i < ((l2capinbuf[12] >> 4) + 1); i++) { // bit 4-7 is the length-1 + PrintHex (l2capinbuf[15 + i], 0x80); + Notify(PSTR(" "), 0x80); + } + } +#endif + } +#ifdef EXTRADEBUG + else { + Notify(PSTR("\r\nReport Error: "), 0x80); + PrintHex (l2capinbuf[13], 0x80); + PrintHex (l2capinbuf[14], 0x80); + } +#endif + break; + case 0x22: // Acknowledge output report, return function result +#ifdef DEBUG + if (l2capinbuf[13] != 0x00) { // Check if there is an error + Notify(PSTR("\r\nCommand failed: "), 0x80); + PrintHex (l2capinbuf[12], 0x80); + } +#endif + break; + case 0x30: // Core buttons - (a1) 30 BB BB + break; + case 0x31: // Core Buttons and Accelerometer - (a1) 31 BB BB AA AA AA + pitch = wiimotePitch; // The pitch is just equal to the angle calculated from the wiimote as there is no Motion Plus connected + roll = wiimoteRoll; + break; + case 0x32: // Core Buttons with 8 Extension bytes - (a1) 32 BB BB EE EE EE EE EE EE EE EE + break; + case 0x33: // Core Buttons with Accelerometer and 12 IR bytes - (a1) 33 BB BB AA AA AA II II II II II II II II II II II II + pitch = wiimotePitch; // The pitch is just equal to the angle calculated from the wiimote as there is no Motion Plus data available + roll = wiimoteRoll; +#ifdef WIICAMERA + // Read the IR data + IR_object_x1 = (l2capinbuf[15] | ((uint16_t)(l2capinbuf[17] & 0x30) << 4)); // x position + IR_object_y1 = (l2capinbuf[16] | ((uint16_t)(l2capinbuf[17] & 0xC0) << 2)); // y position + IR_object_s1 = (l2capinbuf[17] & 0x0F); // size value, 0-15 - } else if(nunchuckConnected) { - hatValues[HatX] = l2capinbuf[15]; - hatValues[HatY] = l2capinbuf[16]; - accX = ((l2capinbuf[17] << 2) | (l2capinbuf[20] & 0x0C >> 2))-416; - accY = ((l2capinbuf[18] << 2) | (l2capinbuf[20] & 0x30 >> 4))-416; - accZ = ((l2capinbuf[19] << 2) | (l2capinbuf[20] & 0xC0 >> 6))-416; - nunchuckPitch = (atan2(accY,accZ)+PI)*RAD_TO_DEG; - nunchuckRoll = (atan2(accX,accZ)+PI)*RAD_TO_DEG; + IR_object_x2 = (l2capinbuf[18] | ((uint16_t)(l2capinbuf[20] & 0x30) << 4)); + IR_object_y2 = (l2capinbuf[19] | ((uint16_t)(l2capinbuf[20] & 0xC0) << 2)); + IR_object_s2 = (l2capinbuf[20] & 0x0F); - pitch = wiimotePitch; // The pitch is just equal to the angle calculated from the wiimote as there is no Motion Plus connected - roll = wiimoteRoll; - } else if(wiiUProControllerConnected) { - hatValues[LeftHatX] = (l2capinbuf[15] | l2capinbuf[16] << 8); - hatValues[RightHatX] = (l2capinbuf[17] | l2capinbuf[18] << 8); - hatValues[LeftHatY] = (l2capinbuf[19] | l2capinbuf[20] << 8); - hatValues[RightHatY] = (l2capinbuf[21] | l2capinbuf[22] << 8); - } - break; -#ifdef DEBUG - default: - Notify(PSTR("\r\nUnknown Report type: "), 0x80); - Serial.print(l2capinbuf[9],HEX); - break; + IR_object_x3 = (l2capinbuf[21] | ((uint16_t)(l2capinbuf[23] & 0x30) << 4)); + IR_object_y3 = (l2capinbuf[22] | ((uint16_t)(l2capinbuf[23] & 0xC0) << 2)); + IR_object_s3 = (l2capinbuf[23] & 0x0F); + + IR_object_x4 = (l2capinbuf[24] | ((uint16_t)(l2capinbuf[26] & 0x30) << 4)); + IR_object_y4 = (l2capinbuf[25] | ((uint16_t)(l2capinbuf[26] & 0xC0) << 2)); + IR_object_s4 = (l2capinbuf[26] & 0x0F); #endif - } + break; + case 0x34: // Core Buttons with 19 Extension bytes - (a1) 34 BB BB EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE + break; + /* 0x3e and 0x3f both give unknown report types when report mode is 0x3e or 0x3f with mode number 0x05 */ + case 0x3E: // Core Buttons with Accelerometer and 32 IR bytes + // (a1) 31 BB BB AA AA AA II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II + // corresponds to output report mode 0x3e + + /**** for reading in full mode: DOES NOT WORK YET ****/ + /* When it works it will also have intensity and bounding box data */ + /* + IR_object_x1 = (l2capinbuf[13] | ((uint16_t)(l2capinbuf[15] & 0x30) << 4)); + IR_object_y1 = (l2capinbuf[14] | ((uint16_t)(l2capinbuf[15] & 0xC0) << 2)); + IR_object_s1 = (l2capinbuf[15] & 0x0F); + */ + break; + case 0x3F: + /* + IR_object_x1 = (l2capinbuf[13] | ((uint16_t)(l2capinbuf[15] & 0x30) << 4)); + IR_object_y1 = (l2capinbuf[14] | ((uint16_t)(l2capinbuf[15] & 0xC0) << 2)); + IR_object_s1 = (l2capinbuf[15] & 0x0F); + */ + break; + case 0x35: // Core Buttons and Accelerometer with 16 Extension Bytes + // (a1) 35 BB BB AA AA AA EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE + if (motionPlusConnected) { + if (l2capinbuf[20] & 0x02) { // Check if it's a report from the Motion controller or the extension + if (motionValuesReset) { // We will only use the values when the gyro value has been set + gyroYawRaw = ((l2capinbuf[15] | ((l2capinbuf[18] & 0xFC) << 6)) - gyroYawZero); + gyroRollRaw = ((l2capinbuf[16] | ((l2capinbuf[19] & 0xFC) << 6)) - gyroRollZero); + gyroPitchRaw = ((l2capinbuf[17] | ((l2capinbuf[20] & 0xFC) << 6)) - gyroPitchZero); + + yawGyroSpeed = (double)gyroYawRaw / ((double)gyroYawZero / yawGyroScale); + rollGyroSpeed = -(double)gyroRollRaw / ((double)gyroRollZero / rollGyroScale); // We invert these values so they will fit the acc values + pitchGyroSpeed = (double)gyroPitchRaw / ((double)gyroPitchZero / pitchGyroScale); + + /* The onboard gyro has two ranges for slow and fast mode */ + if (!(l2capinbuf[18] & 0x02)) // Check if fast more is used + yawGyroSpeed *= 4.545; + if (!(l2capinbuf[18] & 0x01)) // Check if fast more is used + pitchGyroSpeed *= 4.545; + if (!(l2capinbuf[19] & 0x02)) // Check if fast more is used + rollGyroSpeed *= 4.545; + + pitch = (0.93 * (pitch + (pitchGyroSpeed * (double)(micros() - timer) / 1000000)))+(0.07 * wiimotePitch); // Use a complimentary filter to calculate the angle + roll = (0.93 * (roll + (rollGyroSpeed * (double)(micros() - timer) / 1000000)))+(0.07 * wiimoteRoll); + + gyroYaw += (yawGyroSpeed * ((double)(micros() - timer) / 1000000)); + gyroRoll += (rollGyroSpeed * ((double)(micros() - timer) / 1000000)); + gyroPitch += (pitchGyroSpeed * ((double)(micros() - timer) / 1000000)); + timer = micros(); + /* + // Uncomment these lines to tune the gyro scale variabels + Serial.print("\r\ngyroYaw: "); + Serial.print(gyroYaw); + Serial.print("\tgyroRoll: "); + Serial.print(gyroRoll); + Serial.print("\tgyroPitch: "); + Serial.print(gyroPitch); + */ + /* + Serial.print("\twiimoteRoll: "); + Serial.print(wiimoteRoll); + Serial.print("\twiimotePitch: "); + Serial.print(wiimotePitch); + */ + } else { + if ((micros() - timer) > 1000000) { // Loop for 1 sec before resetting the values +#ifdef DEBUG + Notify(PSTR("\r\nThe gyro values has been reset"), 0x80); +#endif + gyroYawZero = (l2capinbuf[15] | ((l2capinbuf[18] & 0xFC) << 6)); + gyroRollZero = (l2capinbuf[16] | ((l2capinbuf[19] & 0xFC) << 6)); + gyroPitchZero = (l2capinbuf[17] | ((l2capinbuf[20] & 0xFC) << 6)); + + rollGyroScale = 500; // You might need to adjust these + pitchGyroScale = 400; + yawGyroScale = 415; + + gyroYaw = 0; + gyroRoll = 0; + gyroPitch = 0; + + motionValuesReset = true; + timer = micros(); + } + } + } else { + if (nunchuckConnected) { + hatValues[HatX] = l2capinbuf[15]; + hatValues[HatY] = l2capinbuf[16]; + accX = ((l2capinbuf[17] << 2) | (l2capinbuf[20] & 0x10 >> 3)) - 416; + accY = ((l2capinbuf[18] << 2) | (l2capinbuf[20] & 0x20 >> 4)) - 416; + accZ = (((l2capinbuf[19] & 0xFE) << 2) | (l2capinbuf[20] & 0xC0 >> 5)) - 416; + nunchuckPitch = (atan2(accY, accZ) + PI) * RAD_TO_DEG; + nunchuckRoll = (atan2(accX, accZ) + PI) * RAD_TO_DEG; + } + //else if(classicControllerConnected) { } + } + if (l2capinbuf[19] & 0x01) { + if (!extensionConnected) { + extensionConnected = true; + unknownExtensionConnected = true; +#ifdef DEBUG + Notify(PSTR("\r\nExtension connected to Motion Plus"), 0x80); +#endif + } + } else { + if (extensionConnected && !unknownExtensionConnected) { + extensionConnected = false; + unknownExtensionConnected = true; +#ifdef DEBUG + Notify(PSTR("\r\nExtension disconnected from Motion Plus"), 0x80); +#endif + nunchuckConnected = false; // There is no extension connected to the Motion Plus if this report is sent + } + } + + } else if (nunchuckConnected) { + hatValues[HatX] = l2capinbuf[15]; + hatValues[HatY] = l2capinbuf[16]; + accX = ((l2capinbuf[17] << 2) | (l2capinbuf[20] & 0x0C >> 2)) - 416; + accY = ((l2capinbuf[18] << 2) | (l2capinbuf[20] & 0x30 >> 4)) - 416; + accZ = ((l2capinbuf[19] << 2) | (l2capinbuf[20] & 0xC0 >> 6)) - 416; + nunchuckPitch = (atan2(accY, accZ) + PI) * RAD_TO_DEG; + nunchuckRoll = (atan2(accX, accZ) + PI) * RAD_TO_DEG; + + pitch = wiimotePitch; // The pitch is just equal to the angle calculated from the wiimote as there is no Motion Plus connected + roll = wiimoteRoll; + } else if (wiiUProControllerConnected) { + hatValues[LeftHatX] = (l2capinbuf[15] | l2capinbuf[16] << 8); + hatValues[RightHatX] = (l2capinbuf[17] | l2capinbuf[18] << 8); + hatValues[LeftHatY] = (l2capinbuf[19] | l2capinbuf[20] << 8); + hatValues[RightHatY] = (l2capinbuf[21] | l2capinbuf[22] << 8); + } + break; +#ifdef DEBUG + default: + Notify(PSTR("\r\nUnknown Report type: "), 0x80); + Serial.print(l2capinbuf[9], HEX); + break; +#endif + } + } + } } - } + L2CAP_task(); } - L2CAP_task(); - } } + void WII::L2CAP_task() { - switch (l2cap_state) { - /* These states are used if the Wiimote is the host */ - case L2CAP_CONTROL_SUCCESS: - if (l2cap_config_success_control_flag) { + switch (l2cap_state) { + /* These states are used if the Wiimote is the host */ + case L2CAP_CONTROL_SUCCESS: + if (l2cap_config_success_control_flag) { #ifdef DEBUG - Notify(PSTR("\r\nHID Control Successfully Configured"), 0x80); + Notify(PSTR("\r\nHID Control Successfully Configured"), 0x80); #endif - l2cap_state = L2CAP_INTERRUPT_SETUP; - } - break; + l2cap_state = L2CAP_INTERRUPT_SETUP; + } + break; - case L2CAP_INTERRUPT_SETUP: - if (l2cap_connection_request_interrupt_flag) { + case L2CAP_INTERRUPT_SETUP: + if (l2cap_connection_request_interrupt_flag) { #ifdef DEBUG - Notify(PSTR("\r\nHID Interrupt Incoming Connection Request"), 0x80); + Notify(PSTR("\r\nHID Interrupt Incoming Connection Request"), 0x80); #endif - pBtd->l2cap_connection_response(hci_handle,identifier, interrupt_dcid, interrupt_scid, PENDING); - delay(1); - pBtd->l2cap_connection_response(hci_handle,identifier, interrupt_dcid, interrupt_scid, SUCCESSFUL); - identifier++; - delay(1); - pBtd->l2cap_config_request(hci_handle,identifier, interrupt_scid); + pBtd->l2cap_connection_response(hci_handle, identifier, interrupt_dcid, interrupt_scid, PENDING); + delay(1); + pBtd->l2cap_connection_response(hci_handle, identifier, interrupt_dcid, interrupt_scid, SUCCESSFUL); + identifier++; + delay(1); + pBtd->l2cap_config_request(hci_handle, identifier, interrupt_scid); - l2cap_state = L2CAP_INTERRUPT_CONFIG_REQUEST; - } - break; + l2cap_state = L2CAP_INTERRUPT_CONFIG_REQUEST; + } + break; - /* These states are used if the Arduino is the host */ - case L2CAP_CONTROL_CONNECT_REQUEST: - if (l2cap_connected_control_flag) { + /* These states are used if the Arduino is the host */ + case L2CAP_CONTROL_CONNECT_REQUEST: + if (l2cap_connected_control_flag) { #ifdef DEBUG - Notify(PSTR("\r\nSend HID Control Config Request"), 0x80); + Notify(PSTR("\r\nSend HID Control Config Request"), 0x80); #endif - identifier++; - pBtd->l2cap_config_request(hci_handle, identifier, control_scid); - l2cap_state = L2CAP_CONTROL_CONFIG_REQUEST; - } - break; + identifier++; + pBtd->l2cap_config_request(hci_handle, identifier, control_scid); + l2cap_state = L2CAP_CONTROL_CONFIG_REQUEST; + } + break; - case L2CAP_CONTROL_CONFIG_REQUEST: - if(l2cap_config_success_control_flag) { + case L2CAP_CONTROL_CONFIG_REQUEST: + if (l2cap_config_success_control_flag) { #ifdef DEBUG - Notify(PSTR("\r\nSend HID Interrupt Connection Request"), 0x80); + Notify(PSTR("\r\nSend HID Interrupt Connection Request"), 0x80); #endif - identifier++; - pBtd->l2cap_connection_request(hci_handle,identifier,interrupt_dcid,HID_INTR_PSM); - l2cap_state = L2CAP_INTERRUPT_CONNECT_REQUEST; - } - break; + identifier++; + pBtd->l2cap_connection_request(hci_handle, identifier, interrupt_dcid, HID_INTR_PSM); + l2cap_state = L2CAP_INTERRUPT_CONNECT_REQUEST; + } + break; - case L2CAP_INTERRUPT_CONNECT_REQUEST: - if(l2cap_connected_interrupt_flag) { + case L2CAP_INTERRUPT_CONNECT_REQUEST: + if (l2cap_connected_interrupt_flag) { #ifdef DEBUG - Notify(PSTR("\r\nSend HID Interrupt Config Request"), 0x80); + Notify(PSTR("\r\nSend HID Interrupt Config Request"), 0x80); #endif - identifier++; - pBtd->l2cap_config_request(hci_handle, identifier, interrupt_scid); - l2cap_state = L2CAP_INTERRUPT_CONFIG_REQUEST; - } - break; + identifier++; + pBtd->l2cap_config_request(hci_handle, identifier, interrupt_scid); + l2cap_state = L2CAP_INTERRUPT_CONFIG_REQUEST; + } + break; - case L2CAP_INTERRUPT_CONFIG_REQUEST: - if(l2cap_config_success_interrupt_flag) { // Now the HID channels is established + case L2CAP_INTERRUPT_CONFIG_REQUEST: + if (l2cap_config_success_interrupt_flag) { // Now the HID channels is established #ifdef DEBUG - Notify(PSTR("\r\nHID Channels Established"), 0x80); + Notify(PSTR("\r\nHID Channels Established"), 0x80); #endif - pBtd->connectToWii = false; - pBtd->pairWithWii = false; - wiimoteConnected = true; - stateCounter = 0; - l2cap_state = L2CAP_CHECK_MOTION_PLUS_STATE; - } - break; + pBtd->connectToWii = false; + pBtd->pairWithWii = false; + wiimoteConnected = true; + stateCounter = 0; + l2cap_state = L2CAP_CHECK_MOTION_PLUS_STATE; + } + break; - /* The next states are in run() */ + /* The next states are in run() */ - case L2CAP_INTERRUPT_DISCONNECT: - if (l2cap_disconnect_response_interrupt_flag) { + case L2CAP_INTERRUPT_DISCONNECT: + if (l2cap_disconnect_response_interrupt_flag) { #ifdef DEBUG - Notify(PSTR("\r\nDisconnected Interrupt Channel"), 0x80); + Notify(PSTR("\r\nDisconnected Interrupt Channel"), 0x80); #endif - identifier++; - pBtd->l2cap_disconnection_request(hci_handle, identifier, control_scid, control_dcid); - l2cap_state = L2CAP_CONTROL_DISCONNECT; - } - break; + identifier++; + pBtd->l2cap_disconnection_request(hci_handle, identifier, control_scid, control_dcid); + l2cap_state = L2CAP_CONTROL_DISCONNECT; + } + break; - case L2CAP_CONTROL_DISCONNECT: - if (l2cap_disconnect_response_control_flag) { + case L2CAP_CONTROL_DISCONNECT: + if (l2cap_disconnect_response_control_flag) { #ifdef DEBUG - Notify(PSTR("\r\nDisconnected Control Channel"), 0x80); + Notify(PSTR("\r\nDisconnected Control Channel"), 0x80); #endif - pBtd->hci_disconnect(hci_handle); - hci_handle = -1; // Reset handle - l2cap_event_flag = 0; // Reset flags - l2cap_state = L2CAP_WAIT; - } - break; - } + pBtd->hci_disconnect(hci_handle); + hci_handle = -1; // Reset handle + l2cap_event_flag = 0; // Reset flags + l2cap_state = L2CAP_WAIT; + } + break; + } } + void WII::Run() { - switch (l2cap_state) { - case L2CAP_WAIT: - if(pBtd->connectToWii && !pBtd->l2capConnectionClaimed && !wiimoteConnected && !activeConnection) { - pBtd->l2capConnectionClaimed = true; - activeConnection = true; + switch (l2cap_state) { + case L2CAP_WAIT: + if (pBtd->connectToWii && !pBtd->l2capConnectionClaimed && !wiimoteConnected && !activeConnection) { + pBtd->l2capConnectionClaimed = true; + activeConnection = true; #ifdef DEBUG - Notify(PSTR("\r\nSend HID Control Connection Request"), 0x80); + Notify(PSTR("\r\nSend HID Control Connection Request"), 0x80); #endif - hci_handle = pBtd->hci_handle; // Store the HCI Handle for the connection - l2cap_event_flag = 0; // Reset flags - identifier = 0; - pBtd->l2cap_connection_request(hci_handle,identifier,control_dcid,HID_CTRL_PSM); - l2cap_state = L2CAP_CONTROL_CONNECT_REQUEST; - } else if (l2cap_connection_request_control_flag) { + hci_handle = pBtd->hci_handle; // Store the HCI Handle for the connection + l2cap_event_flag = 0; // Reset flags + identifier = 0; + pBtd->l2cap_connection_request(hci_handle, identifier, control_dcid, HID_CTRL_PSM); + l2cap_state = L2CAP_CONTROL_CONNECT_REQUEST; + } else if (l2cap_connection_request_control_flag) { #ifdef DEBUG - Notify(PSTR("\r\nHID Control Incoming Connection Request"), 0x80); + Notify(PSTR("\r\nHID Control Incoming Connection Request"), 0x80); #endif - pBtd->l2cap_connection_response(hci_handle,identifier, control_dcid, control_scid, PENDING); - delay(1); - pBtd->l2cap_connection_response(hci_handle,identifier, control_dcid, control_scid, SUCCESSFUL); - identifier++; - delay(1); - pBtd->l2cap_config_request(hci_handle,identifier, control_scid); - l2cap_state = L2CAP_CONTROL_SUCCESS; - } - break; + pBtd->l2cap_connection_response(hci_handle, identifier, control_dcid, control_scid, PENDING); + delay(1); + pBtd->l2cap_connection_response(hci_handle, identifier, control_dcid, control_scid, SUCCESSFUL); + identifier++; + delay(1); + pBtd->l2cap_config_request(hci_handle, identifier, control_scid); + l2cap_state = L2CAP_CONTROL_SUCCESS; + } + break; - case L2CAP_CHECK_MOTION_PLUS_STATE: + case L2CAP_CHECK_MOTION_PLUS_STATE: #ifdef DEBUG - if(stateCounter == 0) // Only print onnce - Notify(PSTR("\r\nChecking if a Motion Plus is connected"), 0x80); + if (stateCounter == 0) // Only print onnce + Notify(PSTR("\r\nChecking if a Motion Plus is connected"), 0x80); #endif - stateCounter++; - if(stateCounter%200 == 0) - checkMotionPresent(); // Check if there is a motion plus connected - if(motion_plus_connected_flag) { - stateCounter = 0; - l2cap_state = L2CAP_INIT_MOTION_PLUS_STATE; - timer = micros(); + stateCounter++; + if (stateCounter % 200 == 0) + checkMotionPresent(); // Check if there is a motion plus connected + if (motion_plus_connected_flag) { + stateCounter = 0; + l2cap_state = L2CAP_INIT_MOTION_PLUS_STATE; + timer = micros(); - if(unknownExtensionConnected) { + if (unknownExtensionConnected) { #ifdef DEBUG - Notify(PSTR("\r\nA extension is also connected"), 0x80); + Notify(PSTR("\r\nA extension is also connected"), 0x80); #endif - activateNunchuck = true; // For we will just set this to true as this the only extension supported so far - } + activateNunchuck = true; // For we will just set this to true as this the only extension supported so far + } - } - else if(stateCounter == 601) { // We will try three times to check for the motion plus + } else if (stateCounter == 601) { // We will try three times to check for the motion plus #ifdef DEBUG - Notify(PSTR("\r\nNo Motion Plus was detected"), 0x80); + Notify(PSTR("\r\nNo Motion Plus was detected"), 0x80); #endif - stateCounter = 0; - l2cap_state = L2CAP_CHECK_EXTENSION_STATE; - } - break; + stateCounter = 0; + l2cap_state = L2CAP_CHECK_EXTENSION_STATE; + } + break; - case L2CAP_CHECK_EXTENSION_STATE: // This is used to check if there is anything plugged in to the extension port + case L2CAP_CHECK_EXTENSION_STATE: // This is used to check if there is anything plugged in to the extension port #ifdef DEBUG - if(stateCounter == 0) // Only print onnce - Notify(PSTR("\r\nChecking if there is any extension connected"), 0x80); + if (stateCounter == 0) // Only print onnce + Notify(PSTR("\r\nChecking if there is any extension connected"), 0x80); #endif - stateCounter++; // We use this counter as there has to be a short delay between the commands - if(stateCounter == 1) - statusRequest(); // See if a new device has connected - if(stateCounter == 100) { - if(unknownExtensionConnected) // Check if there is a extension is connected to the port - initExtension1(); - else - stateCounter = 399; - } else if(stateCounter == 200) - initExtension2(); - else if(stateCounter == 300) { - readExtensionType(); - unknownExtensionConnected = false; - } else if(stateCounter == 400) { - stateCounter = 0; - l2cap_state = L2CAP_LED_STATE; - } - break; + stateCounter++; // We use this counter as there has to be a short delay between the commands + if (stateCounter == 1) + statusRequest(); // See if a new device has connected + if (stateCounter == 100) { + if (unknownExtensionConnected) // Check if there is a extension is connected to the port + initExtension1(); + else + stateCounter = 399; + } else if (stateCounter == 200) + initExtension2(); + else if (stateCounter == 300) { + readExtensionType(); + unknownExtensionConnected = false; + } else if (stateCounter == 400) { + stateCounter = 0; + l2cap_state = L2CAP_LED_STATE; + } + break; - case L2CAP_INIT_MOTION_PLUS_STATE: - stateCounter++; - if(stateCounter == 1) - initMotionPlus(); - else if(stateCounter == 100) - activateMotionPlus(); - else if(stateCounter == 200) - readExtensionType(); // Check if it has been activated - else if(stateCounter == 300) { - stateCounter = 0; - unknownExtensionConnected = false; // The motion plus will send a status report when it's activated, we will set this to false so it doesn't reinitialize the Motion Plus - l2cap_state = L2CAP_LED_STATE; - } - break; + case L2CAP_INIT_MOTION_PLUS_STATE: + stateCounter++; + if (stateCounter == 1) + initMotionPlus(); + else if (stateCounter == 100) + activateMotionPlus(); + else if (stateCounter == 200) + readExtensionType(); // Check if it has been activated + else if (stateCounter == 300) { + stateCounter = 0; + unknownExtensionConnected = false; // The motion plus will send a status report when it's activated, we will set this to false so it doesn't reinitialize the Motion Plus + l2cap_state = L2CAP_LED_STATE; + } + break; - case L2CAP_LED_STATE: - if(nunchuck_connected_flag) - nunchuckConnected = true; - setLedStatus(); - l2cap_state = L2CAP_DONE; - break; + case L2CAP_LED_STATE: + if (nunchuck_connected_flag) + nunchuckConnected = true; + setLedStatus(); + l2cap_state = L2CAP_DONE; + break; - case L2CAP_DONE: - if(unknownExtensionConnected) { + case L2CAP_DONE: + if (unknownExtensionConnected) { #ifdef DEBUG - if(stateCounter == 0) // Only print once - Notify(PSTR("\r\nChecking extension port"), 0x80); + if (stateCounter == 0) // Only print once + Notify(PSTR("\r\nChecking extension port"), 0x80); #endif - stateCounter++; // We will use this counter as there has to be a short delay between the commands - if(stateCounter == 50) - statusRequest(); - else if(stateCounter == 100) - initExtension1(); - else if(stateCounter == 150) - if((extensionConnected && motionPlusConnected) || (unknownExtensionConnected && !motionPlusConnected)) - initExtension2(); - else - stateCounter = 299; // There is no extension connected - else if(stateCounter == 200) - readExtensionType(); - else if(stateCounter == 250) { - if(nunchuck_connected_flag) { + stateCounter++; // We will use this counter as there has to be a short delay between the commands + if (stateCounter == 50) + statusRequest(); + else if (stateCounter == 100) + initExtension1(); + else if (stateCounter == 150) + if ((extensionConnected && motionPlusConnected) || (unknownExtensionConnected && !motionPlusConnected)) + initExtension2(); + else + stateCounter = 299; // There is no extension connected + else if (stateCounter == 200) + readExtensionType(); + else if (stateCounter == 250) { + if (nunchuck_connected_flag) { #ifdef DEBUG - Notify(PSTR("\r\nNunchuck was reconnected"), 0x80); + Notify(PSTR("\r\nNunchuck was reconnected"), 0x80); #endif - activateNunchuck = true; - nunchuckConnected = true; - } - if(!motionPlusConnected) - stateCounter = 449; - } - else if (stateCounter == 300) { - if(motionPlusConnected) { + activateNunchuck = true; + nunchuckConnected = true; + } + if (!motionPlusConnected) + stateCounter = 449; + } else if (stateCounter == 300) { + if (motionPlusConnected) { #ifdef DEBUG - Notify(PSTR("\r\nReactivating the Motion Plus"), 0x80); + Notify(PSTR("\r\nReactivating the Motion Plus"), 0x80); #endif - initMotionPlus(); - } else - stateCounter = 449; - } - else if(stateCounter == 350) - activateMotionPlus(); - else if(stateCounter == 400) - readExtensionType(); // Check if it has been activated - else if(stateCounter == 450) { - setLedStatus(); - stateCounter = 0; - unknownExtensionConnected = false; - } - } else - stateCounter = 0; - break; - } + initMotionPlus(); + } else + stateCounter = 449; + } else if (stateCounter == 350) + activateMotionPlus(); + else if (stateCounter == 400) + readExtensionType(); // Check if it has been activated + else if (stateCounter == 450) { + setLedStatus(); + stateCounter = 0; + unknownExtensionConnected = false; + } + } else + stateCounter = 0; + break; + } } /************************************************************/ /* HID Commands */ + /************************************************************/ void WII::HID_Command(uint8_t* data, uint8_t nbytes) { - if(pBtd->motionPlusInside) - pBtd->L2CAP_Command(hci_handle,data,nbytes,interrupt_scid[0],interrupt_scid[1]); // It's the new wiimote with the Motion Plus Inside - else - pBtd->L2CAP_Command(hci_handle,data,nbytes,control_scid[0],control_scid[1]); + if (pBtd->motionPlusInside) + pBtd->L2CAP_Command(hci_handle, data, nbytes, interrupt_scid[0], interrupt_scid[1]); // It's the new wiimote with the Motion Plus Inside + else + pBtd->L2CAP_Command(hci_handle, data, nbytes, control_scid[0], control_scid[1]); } -void WII::setAllOff() { - HIDBuffer[1] = 0x11; - HIDBuffer[2] = 0x00; - HID_Command(HIDBuffer, 3); -} -void WII::setRumbleOff() { - HIDBuffer[1] = 0x11; - HIDBuffer[2] &= ~0x01; // Bit 0 control the rumble - HID_Command(HIDBuffer, 3); -} -void WII::setRumbleOn() { - HIDBuffer[1] = 0x11; - HIDBuffer[2] |= 0x01; // Bit 0 control the rumble - HID_Command(HIDBuffer, 3); -} -void WII::setRumbleToggle() { - HIDBuffer[1] = 0x11; - HIDBuffer[2] ^= 0x01; // Bit 0 control the rumble - HID_Command(HIDBuffer, 3); -} -void WII::setLedOff(LED a) { - HIDBuffer[1] = 0x11; - HIDBuffer[2] &= ~(pgm_read_byte(&LEDS[(uint8_t)a])); - HID_Command(HIDBuffer, 3); -} -void WII::setLedOn(LED a) { - HIDBuffer[1] = 0x11; - HIDBuffer[2] |= pgm_read_byte(&LEDS[(uint8_t)a]); - HID_Command(HIDBuffer, 3); -} -void WII::setLedToggle(LED a) { - HIDBuffer[1] = 0x11; - HIDBuffer[2] ^= pgm_read_byte(&LEDS[(uint8_t)a]); - HID_Command(HIDBuffer, 3); -} -void WII::setLedStatus() { - HIDBuffer[1] = 0x11; - HIDBuffer[2] = (HIDBuffer[2] & 0x01); // Keep the rumble bit - if(wiimoteConnected) - HIDBuffer[2] |= 0x10; // If it's connected LED1 will light up - if(motionPlusConnected) - HIDBuffer[2] |= 0x20; // If it's connected LED2 will light up - if(nunchuckConnected) - HIDBuffer[2] |= 0x40; // If it's connected LED3 will light up - HID_Command(HIDBuffer, 3); +void WII::setAllOff() { + HIDBuffer[1] = 0x11; + HIDBuffer[2] = 0x00; + HID_Command(HIDBuffer, 3); } + +void WII::setRumbleOff() { + HIDBuffer[1] = 0x11; + HIDBuffer[2] &= ~0x01; // Bit 0 control the rumble + HID_Command(HIDBuffer, 3); +} + +void WII::setRumbleOn() { + HIDBuffer[1] = 0x11; + HIDBuffer[2] |= 0x01; // Bit 0 control the rumble + HID_Command(HIDBuffer, 3); +} + +void WII::setRumbleToggle() { + HIDBuffer[1] = 0x11; + HIDBuffer[2] ^= 0x01; // Bit 0 control the rumble + HID_Command(HIDBuffer, 3); +} + +void WII::setLedOff(LED a) { + HIDBuffer[1] = 0x11; + HIDBuffer[2] &= ~(pgm_read_byte(&LEDS[(uint8_t)a])); + HID_Command(HIDBuffer, 3); +} + +void WII::setLedOn(LED a) { + HIDBuffer[1] = 0x11; + HIDBuffer[2] |= pgm_read_byte(&LEDS[(uint8_t)a]); + HID_Command(HIDBuffer, 3); +} + +void WII::setLedToggle(LED a) { + HIDBuffer[1] = 0x11; + HIDBuffer[2] ^= pgm_read_byte(&LEDS[(uint8_t)a]); + HID_Command(HIDBuffer, 3); +} + +void WII::setLedStatus() { + HIDBuffer[1] = 0x11; + HIDBuffer[2] = (HIDBuffer[2] & 0x01); // Keep the rumble bit + if (wiimoteConnected) + HIDBuffer[2] |= 0x10; // If it's connected LED1 will light up + if (motionPlusConnected) + HIDBuffer[2] |= 0x20; // If it's connected LED2 will light up + if (nunchuckConnected) + HIDBuffer[2] |= 0x40; // If it's connected LED3 will light up + + HID_Command(HIDBuffer, 3); +} + void WII::setReportMode(bool continuous, uint8_t mode) { - uint8_t cmd_buf[4]; - cmd_buf[0] = 0xA2; // HID BT DATA_request (0xA0) | Report Type (Output 0x02) - cmd_buf[1] = 0x12; - if(continuous) - cmd_buf[2] = 0x04 | (HIDBuffer[2] & 0x01); // Keep the rumble bit - else - cmd_buf[2] = 0x00 | (HIDBuffer[2] & 0x01); // Keep the rumble bit - cmd_buf[3] = mode; - HID_Command(cmd_buf, 4); + uint8_t cmd_buf[4]; + cmd_buf[0] = 0xA2; // HID BT DATA_request (0xA0) | Report Type (Output 0x02) + cmd_buf[1] = 0x12; + if (continuous) + cmd_buf[2] = 0x04 | (HIDBuffer[2] & 0x01); // Keep the rumble bit + else + cmd_buf[2] = 0x00 | (HIDBuffer[2] & 0x01); // Keep the rumble bit + cmd_buf[3] = mode; + HID_Command(cmd_buf, 4); } + void WII::statusRequest() { - uint8_t cmd_buf[3]; - cmd_buf[0] = 0xA2; // HID BT DATA_request (0xA0) | Report Type (Output 0x02) - cmd_buf[1] = 0x15; - cmd_buf[2] = (HIDBuffer[2] & 0x01); // Keep the rumble bit - HID_Command(cmd_buf, 3); + uint8_t cmd_buf[3]; + cmd_buf[0] = 0xA2; // HID BT DATA_request (0xA0) | Report Type (Output 0x02) + cmd_buf[1] = 0x15; + cmd_buf[2] = (HIDBuffer[2] & 0x01); // Keep the rumble bit + HID_Command(cmd_buf, 3); } /************************************************************/ /* Memmory Commands */ + /************************************************************/ void WII::writeData(uint32_t offset, uint8_t size, uint8_t* data) { - uint8_t cmd_buf[23]; - cmd_buf[0] = 0xA2; // HID BT DATA_request (0xA0) | Report Type (Output 0x02) - cmd_buf[1] = 0x16; // Write data - cmd_buf[2] = 0x04 | (HIDBuffer[2] & 0x01); // Write to memory, clear bit 2 to write to EEPROM - cmd_buf[3] = (uint8_t)((offset & 0xFF0000) >> 16); - cmd_buf[4] = (uint8_t)((offset & 0xFF00) >> 8); - cmd_buf[5] = (uint8_t)(offset & 0xFF); - cmd_buf[6] = size; - uint8_t i = 0; - for(; i < size; i++) - cmd_buf[7+i] = data[i]; - for(; i < 16; i++) // Set the rest to zero - cmd_buf[7+i] = 0x00; - HID_Command(cmd_buf,23); + uint8_t cmd_buf[23]; + cmd_buf[0] = 0xA2; // HID BT DATA_request (0xA0) | Report Type (Output 0x02) + cmd_buf[1] = 0x16; // Write data + cmd_buf[2] = 0x04 | (HIDBuffer[2] & 0x01); // Write to memory, clear bit 2 to write to EEPROM + cmd_buf[3] = (uint8_t)((offset & 0xFF0000) >> 16); + cmd_buf[4] = (uint8_t)((offset & 0xFF00) >> 8); + cmd_buf[5] = (uint8_t)(offset & 0xFF); + cmd_buf[6] = size; + uint8_t i = 0; + for (; i < size; i++) + cmd_buf[7 + i] = data[i]; + for (; i < 16; i++) // Set the rest to zero + cmd_buf[7 + i] = 0x00; + HID_Command(cmd_buf, 23); } -void WII::initExtension1() { - uint8_t buf[1]; - buf[0] = 0x55; - writeData(0xA400F0,1,buf); -} -void WII::initExtension2() { - uint8_t buf[1]; - buf[0] = 0x00; - writeData(0xA400FB,1,buf); -} -void WII::initMotionPlus() { - uint8_t buf[1]; - buf[0] = 0x55; - writeData(0xA600F0,1,buf); -} -void WII::activateMotionPlus() { - uint8_t buf[1]; - if(pBtd->wiiUProController) { -#ifdef DEBUG - Notify(PSTR("\r\nActivating Wii U Pro Controller"), 0x80); -#endif - buf[0] = 0x00; // It seems like you can send anything but 0x04, 0x05, and 0x07 - } else if(activateNunchuck) { -#ifdef DEBUG - Notify(PSTR("\r\nActivating Motion Plus in pass-through mode"), 0x80); -#endif - buf[0] = 0x05; // Activate nunchuck pass-through mode - } - //else if(classicControllerConnected && extensionConnected) - //buf[0] = 0x07; - else { -#ifdef DEBUG - Notify(PSTR("\r\nActivating Motion Plus in normal mode"), 0x80); -#endif - buf[0] = 0x04; // Don't use any extension - } - writeData(0xA600FE,1,buf); -} -void WII::readData(uint32_t offset, uint16_t size, bool EEPROM) { - uint8_t cmd_buf[8]; - cmd_buf[0] = 0xA2; // HID BT DATA_request (0xA0) | Report Type (Output 0x02) - cmd_buf[1] = 0x17; // Read data - if(EEPROM) - cmd_buf[2] = 0x00 | (HIDBuffer[2] & 0x01); // Read from EEPROM - else - cmd_buf[2] = 0x04 | (HIDBuffer[2] & 0x01); // Read from memory - cmd_buf[3] = (uint8_t)((offset & 0xFF0000) >> 16); - cmd_buf[4] = (uint8_t)((offset & 0xFF00) >> 8); - cmd_buf[5] = (uint8_t)(offset & 0xFF); - cmd_buf[6] = (uint8_t)((size & 0xFF00) >> 8); - cmd_buf[7] = (uint8_t)(size & 0xFF); - HID_Command(cmd_buf,8); +void WII::initExtension1() { + uint8_t buf[1]; + buf[0] = 0x55; + writeData(0xA400F0, 1, buf); } + +void WII::initExtension2() { + uint8_t buf[1]; + buf[0] = 0x00; + writeData(0xA400FB, 1, buf); +} + +void WII::initMotionPlus() { + uint8_t buf[1]; + buf[0] = 0x55; + writeData(0xA600F0, 1, buf); +} + +void WII::activateMotionPlus() { + uint8_t buf[1]; + if (pBtd->wiiUProController) { +#ifdef DEBUG + Notify(PSTR("\r\nActivating Wii U Pro Controller"), 0x80); +#endif + buf[0] = 0x00; // It seems like you can send anything but 0x04, 0x05, and 0x07 + } else if (activateNunchuck) { +#ifdef DEBUG + Notify(PSTR("\r\nActivating Motion Plus in pass-through mode"), 0x80); +#endif + buf[0] = 0x05; // Activate nunchuck pass-through mode + } //else if(classicControllerConnected && extensionConnected) + //buf[0] = 0x07; + else { +#ifdef DEBUG + Notify(PSTR("\r\nActivating Motion Plus in normal mode"), 0x80); +#endif + buf[0] = 0x04; // Don't use any extension + } + writeData(0xA600FE, 1, buf); +} + +void WII::readData(uint32_t offset, uint16_t size, bool EEPROM) { + uint8_t cmd_buf[8]; + cmd_buf[0] = 0xA2; // HID BT DATA_request (0xA0) | Report Type (Output 0x02) + cmd_buf[1] = 0x17; // Read data + if (EEPROM) + cmd_buf[2] = 0x00 | (HIDBuffer[2] & 0x01); // Read from EEPROM + else + cmd_buf[2] = 0x04 | (HIDBuffer[2] & 0x01); // Read from memory + cmd_buf[3] = (uint8_t)((offset & 0xFF0000) >> 16); + cmd_buf[4] = (uint8_t)((offset & 0xFF00) >> 8); + cmd_buf[5] = (uint8_t)(offset & 0xFF); + cmd_buf[6] = (uint8_t)((size & 0xFF00) >> 8); + cmd_buf[7] = (uint8_t)(size & 0xFF); + + HID_Command(cmd_buf, 8); +} + void WII::readExtensionType() { - readData(0xA400FA,6,false); + readData(0xA400FA, 6, false); } + void WII::readCalData() { - readData(0x0016,8,true); + readData(0x0016, 8, true); } + void WII::checkMotionPresent() { - readData(0xA600FA,6,false); + readData(0xA600FA, 6, false); } /************************************************************/ /* WII Commands */ + /************************************************************/ bool WII::getButtonPress(Button b) { // Return true when a button is pressed - if(wiiUProControllerConnected) - return (ButtonState & pgm_read_dword(&PROCONTROLLERBUTTONS[(uint8_t)b])); - else - return (ButtonState & pgm_read_dword(&BUTTONS[(uint8_t)b])); + if (wiiUProControllerConnected) + return (ButtonState & pgm_read_dword(&PROCONTROLLERBUTTONS[(uint8_t)b])); + else + return (ButtonState & pgm_read_dword(&BUTTONS[(uint8_t)b])); } + bool WII::getButtonClick(Button b) { // Only return true when a button is clicked - uint32_t button; - if(wiiUProControllerConnected) - button = pgm_read_dword(&PROCONTROLLERBUTTONS[(uint8_t)b]); - else - button = pgm_read_dword(&BUTTONS[(uint8_t)b]); - bool click = (ButtonClickState & button); - ButtonClickState &= ~button; // clear "click" event - return click; + uint32_t button; + if (wiiUProControllerConnected) + button = pgm_read_dword(&PROCONTROLLERBUTTONS[(uint8_t)b]); + else + button = pgm_read_dword(&BUTTONS[(uint8_t)b]); + bool click = (ButtonClickState & button); + ButtonClickState &= ~button; // clear "click" event + return click; } + uint8_t WII::getAnalogHat(Hat a) { - if(!nunchuckConnected) - return 127; // Return center position - else { - uint8_t output = hatValues[(uint8_t)a]; - if(output == 0xFF || output == 0x00) // The joystick will only read 255 or 0 when the cable is unplugged or initializing, so we will just return the center position - return 127; - else - return output; - } + if (!nunchuckConnected) + return 127; // Return center position + else { + uint8_t output = hatValues[(uint8_t)a]; + if (output == 0xFF || output == 0x00) // The joystick will only read 255 or 0 when the cable is unplugged or initializing, so we will just return the center position + return 127; + else + return output; + } } + uint16_t WII::getAnalogHat(AnalogHat a) { - if(!wiiUProControllerConnected) - return 2000; - else { - uint16_t output = hatValues[(uint8_t)a]; - if(output == 0x00) // The joystick will only read 0 when it is first initializing, so we will just return the center position - return 2000; - else - return output; - } + if (!wiiUProControllerConnected) + return 2000; + else { + uint16_t output = hatValues[(uint8_t)a]; + if (output == 0x00) // The joystick will only read 0 when it is first initializing, so we will just return the center position + return 2000; + else + return output; + } } /************************************************************/ /* The following functions are for the IR camera */ @@ -1056,7 +1063,7 @@ uint16_t WII::getAnalogHat(AnalogHat a) { #ifdef WIICAMERA -void WII::IRinitialize(){ // Turns on and initialises the IR camera +void WII::IRinitialize() { // Turns on and initialises the IR camera enableIRCamera1(); #ifdef DEBUG @@ -1092,7 +1099,7 @@ void WII::IRinitialize(){ // Turns on and initialises the IR camera setWiiModeNumber(mode_num); // Change input for whatever mode you want i.e. 0x01, 0x03, or 0x05 #ifdef DEBUG Notify(PSTR("\r\nSet Wii Mode Number To 0x"), 0x80); - PrintHex(mode_num, 0x80); + PrintHex (mode_num, 0x80); #endif delay(80); @@ -1115,51 +1122,51 @@ void WII::IRinitialize(){ // Turns on and initialises the IR camera #endif } -void WII::enableIRCamera1(){ - uint8_t cmd_buf[3]; - cmd_buf[0] = 0xA2; // HID BT DATA_request (0xA0) | Report Type (Output 0x02) - cmd_buf[1] = 0x13; // Output report 13 - cmd_buf[2] = 0x04 | (HIDBuffer[2] & 0x01); // Keep the rumble bit and sets bit 2 - HID_Command(cmd_buf, 3); +void WII::enableIRCamera1() { + uint8_t cmd_buf[3]; + cmd_buf[0] = 0xA2; // HID BT DATA_request (0xA0) | Report Type (Output 0x02) + cmd_buf[1] = 0x13; // Output report 13 + cmd_buf[2] = 0x04 | (HIDBuffer[2] & 0x01); // Keep the rumble bit and sets bit 2 + HID_Command(cmd_buf, 3); } -void WII::enableIRCamera2(){ - uint8_t cmd_buf[3]; - cmd_buf[0] = 0xA2; // HID BT DATA_request (0xA0) | Report Type (Output 0x02) - cmd_buf[1] = 0x1A; // Output report 1A - cmd_buf[2] = 0x04 | (HIDBuffer[2] & 0x01); // Keep the rumble bit and sets bit 2 - HID_Command(cmd_buf, 3); +void WII::enableIRCamera2() { + uint8_t cmd_buf[3]; + cmd_buf[0] = 0xA2; // HID BT DATA_request (0xA0) | Report Type (Output 0x02) + cmd_buf[1] = 0x1A; // Output report 1A + cmd_buf[2] = 0x04 | (HIDBuffer[2] & 0x01); // Keep the rumble bit and sets bit 2 + HID_Command(cmd_buf, 3); } -void WII::writeSensitivityBlock1(){ - uint8_t buf[9]; - buf[0] = 0x00; - buf[1] = 0x00; - buf[2] = 0x00; - buf[3] = 0x00; - buf[4] = 0x00; - buf[5] = 0x00; - buf[6] = 0x90; - buf[7] = 0x00; - buf[8] = 0x41; +void WII::writeSensitivityBlock1() { + uint8_t buf[9]; + buf[0] = 0x00; + buf[1] = 0x00; + buf[2] = 0x00; + buf[3] = 0x00; + buf[4] = 0x00; + buf[5] = 0x00; + buf[6] = 0x90; + buf[7] = 0x00; + buf[8] = 0x41; - writeData(0xB00000, 9, buf); + writeData(0xB00000, 9, buf); } -void WII::writeSensitivityBlock2(){ - uint8_t buf[2]; - buf[0] = 0x40; - buf[1] = 0x00; +void WII::writeSensitivityBlock2() { + uint8_t buf[2]; + buf[0] = 0x40; + buf[1] = 0x00; - writeData(0xB0001A, 2, buf); + writeData(0xB0001A, 2, buf); } -void WII::write0x08Value(){ - uint8_t cmd = 0x08; - writeData(0xb00030, 1, &cmd); +void WII::write0x08Value() { + uint8_t cmd = 0x08; + writeData(0xb00030, 1, &cmd); } -void WII::setWiiModeNumber(uint8_t mode_number){ // mode_number in hex i.e. 0x03 for extended mode - writeData(0xb00033,1,&mode_number); +void WII::setWiiModeNumber(uint8_t mode_number) { // mode_number in hex i.e. 0x03 for extended mode + writeData(0xb00033, 1, &mode_number); } #endif diff --git a/Wii.h b/Wii.h index d6540704..6ffe6803 100755 --- a/Wii.h +++ b/Wii.h @@ -1,15 +1,15 @@ /* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved. - + This software may be distributed and modified under the terms of the GNU General Public License version 2 (GPL2) as published by the Free Software Foundation and appearing in the file GPL2.TXT included in the packaging of this file. Please note that GPL2 Section 2[b] requires that all works based on this software must also be made publicly available under the terms of the GPL2 ("Copyleft"). - + Contact information ------------------- - + Kristian Lauszus, TKJ Electronics Web : http://www.tkjelectronics.com e-mail : kristianl@tkjelectronics.com @@ -39,7 +39,7 @@ #define L2CAP_CONTROL_CONNECT_REQUEST 3 #define L2CAP_CONTROL_CONFIG_REQUEST 4 #define L2CAP_INTERRUPT_CONNECT_REQUEST 5 - + #define L2CAP_INTERRUPT_CONFIG_REQUEST 6 #define L2CAP_CHECK_MOTION_PLUS_STATE 7 @@ -82,10 +82,10 @@ /** Enum used to read the joystick on the Nunchuck. */ enum Hat { - /** Read the x-axis on the Nunchuck joystick. */ - HatX = 0, - /** Read the y-axis on the Nunchuck joystick. */ - HatY = 1, + /** Read the x-axis on the Nunchuck joystick. */ + HatX = 0, + /** Read the y-axis on the Nunchuck joystick. */ + HatY = 1, }; /** @@ -95,347 +95,394 @@ enum Hat { */ class WII : public BluetoothService { public: - /** - * Constructor for the WII class. - * @param p Pointer to BTD class instance. - * @param pair Set this to true in order to pair with the Wiimote. If the argument is omitted then it won't pair with it. - * One can use ::PAIR to set it to true. - */ - WII(BTD *p, bool pair=false); + /** + * Constructor for the WII class. + * @param p Pointer to BTD class instance. + * @param pair Set this to true in order to pair with the Wiimote. If the argument is omitted then it won't pair with it. + * One can use ::PAIR to set it to true. + */ + WII(BTD *p, bool pair = false); - /** @name BluetoothService implementation */ - /** - * Used to pass acldata to the services. - * @param ACLData Incoming acldata. - */ - virtual void ACLData(uint8_t* ACLData); - /** Used to run part of the state maschine. */ - virtual void Run(); - /** Use this to reset the service. */ - virtual void Reset(); - /** Used this to disconnect any of the controllers. */ - virtual void disconnect(); - /**@}*/ + /** @name BluetoothService implementation */ + /** + * Used to pass acldata to the services. + * @param ACLData Incoming acldata. + */ + virtual void ACLData(uint8_t* ACLData); + /** Used to run part of the state maschine. */ + virtual void Run(); + /** Use this to reset the service. */ + virtual void Reset(); + /** Used this to disconnect any of the controllers. */ + virtual void disconnect(); + /**@}*/ - /** @name Wii Controller functions */ - /** - * getButtonPress(Button b) will return true as long as the button is held down. - * - * While getButtonClick(Button b) will only return it once. - * - * So you instance if you need to increase a variable once you would use getButtonClick(Button b), - * but if you need to drive a robot forward you would use getButtonPress(Button b). - */ - bool getButtonPress(Button b); - bool getButtonClick(Button b); - /**@}*/ + /** @name Wii Controller functions */ + /** + * getButtonPress(Button b) will return true as long as the button is held down. + * + * While getButtonClick(Button b) will only return it once. + * + * So you instance if you need to increase a variable once you would use getButtonClick(Button b), + * but if you need to drive a robot forward you would use getButtonPress(Button b). + */ + bool getButtonPress(Button b); + bool getButtonClick(Button b); + /**@}*/ - /** @name Wii Controller functions */ - /** - * Used to read the joystick of the Nunchuck. - * @param a Either ::HatX or ::HatY. - * @return Return the analog value in the range from approximately 25-230. - */ - uint8_t getAnalogHat(Hat a); - /** - * Used to read the joystick of the Wii U Pro Controller. - * @param a Either ::LeftHatX, ::LeftHatY, ::RightHatX or ::RightHatY. - * @return Return the analog value in the range from approximately 800-3200. - */ - uint16_t getAnalogHat(AnalogHat a); + /** @name Wii Controller functions */ + /** + * Used to read the joystick of the Nunchuck. + * @param a Either ::HatX or ::HatY. + * @return Return the analog value in the range from approximately 25-230. + */ + uint8_t getAnalogHat(Hat a); + /** + * Used to read the joystick of the Wii U Pro Controller. + * @param a Either ::LeftHatX, ::LeftHatY, ::RightHatX or ::RightHatY. + * @return Return the analog value in the range from approximately 800-3200. + */ + uint16_t getAnalogHat(AnalogHat a); - /** - * Pitch calculated from the Wiimote. A complimentary filter is used if the Motion Plus is connected. - * @return Pitch in the range from 0-360. - */ - double getPitch() { return pitch; }; - /** - * Roll calculated from the Wiimote. A complimentary filter is used if the Motion Plus is connected. - * @return Roll in the range from 0-360. - */ - double getRoll() { return roll; }; - /** - * This is the yaw calculated by the gyro. - * - * NOTE: This angle will drift a lot and is only available if the Motion Plus extension is connected. - * @return The angle calculated using the gyro. - */ - double getYaw() { return gyroYaw; }; - - /** Used to set all LEDs and rumble off. */ - void setAllOff(); - /** Turn off rumble. */ - void setRumbleOff(); - /** Turn on rumble. */ - void setRumbleOn(); - /** Toggle rumble. */ - void setRumbleToggle(); - /** - * Turn the specific ::LED off. - * @param a The ::LED to turn off. - */ - void setLedOff(LED a); - /** - * Turn the specific ::LED on. - * @param a The ::LED to turn on. - */ - void setLedOn(LED a); - /** - * Toggle the specific ::LED. - * @param a The ::LED to toggle. - */ - void setLedToggle(LED a); - /** - * This will set the LEDs, so the user can see which connections are active. - * - * The first ::LED indicate that the Wiimote is connected, - * - * the second ::LED indicate indicate that a Motion Plus is also connected - * - * the third ::LED will indicate that a Nunchuck controller is also connected. - */ - void setLedStatus(); + /** + * Pitch calculated from the Wiimote. A complimentary filter is used if the Motion Plus is connected. + * @return Pitch in the range from 0-360. + */ + double getPitch() { + return pitch; + }; - /** - * Return the battery level of the Wiimote. - * @return The battery level in the range 0-255. - */ - uint8_t getBatteryLevel() { return batteryLevel; }; - /** - * Return the Wiimote state. - * @return See: http://wiibrew.org/wiki/Wiimote#0x20:_Status. - */ - uint8_t getWiiState() { return wiiState; }; - /**@}*/ + /** + * Roll calculated from the Wiimote. A complimentary filter is used if the Motion Plus is connected. + * @return Roll in the range from 0-360. + */ + double getRoll() { + return roll; + }; - /**@{*/ - /** Variable used to indicate if a Wiimote is connected. */ - bool wiimoteConnected; - /** Variable used to indicate if a Nunchuck controller is connected. */ - bool nunchuckConnected; - /** Variable used to indicate if a Nunchuck controller is connected. */ - bool motionPlusConnected; - /** Variable used to indicate if a Wii U Pro controller is connected. */ - bool wiiUProControllerConnected; - /**@}*/ - - /* IMU Data, might be usefull if you need to do something more advanced than just calculating the angle */ - - /**@{*/ - /** Pitch and roll calculated from the accelerometer inside the Wiimote. */ - double wiimotePitch; - double wiimoteRoll; - /**@}*/ + /** + * This is the yaw calculated by the gyro. + * + * NOTE: This angle will drift a lot and is only available if the Motion Plus extension is connected. + * @return The angle calculated using the gyro. + */ + double getYaw() { + return gyroYaw; + }; - /**@{*/ - /** Pitch and roll calculated from the accelerometer inside the Nunchuck. */ - double nunchuckPitch; - double nunchuckRoll; - /**@}*/ + /** Used to set all LEDs and rumble off. */ + void setAllOff(); + /** Turn off rumble. */ + void setRumbleOff(); + /** Turn on rumble. */ + void setRumbleOn(); + /** Toggle rumble. */ + void setRumbleToggle(); + /** + * Turn the specific ::LED off. + * @param a The ::LED to turn off. + */ + void setLedOff(LED a); + /** + * Turn the specific ::LED on. + * @param a The ::LED to turn on. + */ + void setLedOn(LED a); + /** + * Toggle the specific ::LED. + * @param a The ::LED to toggle. + */ + void setLedToggle(LED a); + /** + * This will set the LEDs, so the user can see which connections are active. + * + * The first ::LED indicate that the Wiimote is connected, + * + * the second ::LED indicate indicate that a Motion Plus is also connected + * + * the third ::LED will indicate that a Nunchuck controller is also connected. + */ + void setLedStatus(); - /**@{*/ - /** Accelerometer values used to calculate pitch and roll. */ - int16_t accX; - int16_t accY; - int16_t accZ; - /**@}*/ + /** + * Return the battery level of the Wiimote. + * @return The battery level in the range 0-255. + */ + uint8_t getBatteryLevel() { + return batteryLevel; + }; - /* Variables for the gyro inside the Motion Plus */ - /** This is the pitch calculated by the gyro - use this to tune WII#pitchGyroScale. */ - double gyroPitch; - /** This is the roll calculated by the gyro - use this to tune WII#rollGyroScale. */ - double gyroRoll; - /** This is the yaw calculated by the gyro - use this to tune WII#yawGyroScale. */ - double gyroYaw; + /** + * Return the Wiimote state. + * @return See: http://wiibrew.org/wiki/Wiimote#0x20:_Status. + */ + uint8_t getWiiState() { + return wiiState; + }; + /**@}*/ - /**@{*/ - /** The speed in deg/s from the gyro. */ - double pitchGyroSpeed; - double rollGyroSpeed; - double yawGyroSpeed; - /**@}*/ - - /**@{*/ - /** You might need to fine-tune these values. */ - uint16_t pitchGyroScale; - uint16_t rollGyroScale; - uint16_t yawGyroScale; - /**@}*/ - - /**@{*/ - /** Raw value read directly from the Motion Plus. */ - int16_t gyroYawRaw; - int16_t gyroRollRaw; - int16_t gyroPitchRaw; - /**@}*/ - - /**@{*/ - /** These values are set when the controller is first initialized. */ - int16_t gyroYawZero; - int16_t gyroRollZero; - int16_t gyroPitchZero; - /**@}*/ + /**@{*/ + /** Variable used to indicate if a Wiimote is connected. */ + bool wiimoteConnected; + /** Variable used to indicate if a Nunchuck controller is connected. */ + bool nunchuckConnected; + /** Variable used to indicate if a Nunchuck controller is connected. */ + bool motionPlusConnected; + /** Variable used to indicate if a Wii U Pro controller is connected. */ + bool wiiUProControllerConnected; + /**@}*/ + + /* IMU Data, might be usefull if you need to do something more advanced than just calculating the angle */ + + /**@{*/ + /** Pitch and roll calculated from the accelerometer inside the Wiimote. */ + double wiimotePitch; + double wiimoteRoll; + /**@}*/ + + /**@{*/ + /** Pitch and roll calculated from the accelerometer inside the Nunchuck. */ + double nunchuckPitch; + double nunchuckRoll; + /**@}*/ + + /**@{*/ + /** Accelerometer values used to calculate pitch and roll. */ + int16_t accX; + int16_t accY; + int16_t accZ; + /**@}*/ + + /* Variables for the gyro inside the Motion Plus */ + /** This is the pitch calculated by the gyro - use this to tune WII#pitchGyroScale. */ + double gyroPitch; + /** This is the roll calculated by the gyro - use this to tune WII#rollGyroScale. */ + double gyroRoll; + /** This is the yaw calculated by the gyro - use this to tune WII#yawGyroScale. */ + double gyroYaw; + + /**@{*/ + /** The speed in deg/s from the gyro. */ + double pitchGyroSpeed; + double rollGyroSpeed; + double yawGyroSpeed; + /**@}*/ + + /**@{*/ + /** You might need to fine-tune these values. */ + uint16_t pitchGyroScale; + uint16_t rollGyroScale; + uint16_t yawGyroScale; + /**@}*/ + + /**@{*/ + /** Raw value read directly from the Motion Plus. */ + int16_t gyroYawRaw; + int16_t gyroRollRaw; + int16_t gyroPitchRaw; + /**@}*/ + + /**@{*/ + /** These values are set when the controller is first initialized. */ + int16_t gyroYawZero; + int16_t gyroRollZero; + int16_t gyroPitchZero; + /**@}*/ #ifdef WIICAMERA - /** @name Wiimote IR camera functions - * You will have to uncomment #WIICAMERA in Wii.h to use the IR camera. - */ - /** Initialises the camera as per the steps from: http://wiibrew.org/wiki/Wiimote#IR_Camera */ - void IRinitialize(); + /** @name Wiimote IR camera functions + * You will have to uncomment #WIICAMERA in Wii.h to use the IR camera. + */ + /** Initialises the camera as per the steps from: http://wiibrew.org/wiki/Wiimote#IR_Camera */ + void IRinitialize(); - /** - * IR object 1 x-position read from the Wii IR camera. - * @return The x-position of the object in the range 0-1023. - */ - uint16_t getIRx1() { return IR_object_x1; }; - /** - * IR object 1 y-position read from the Wii IR camera. - * @return The y-position of the object in the range 0-767. - */ - uint16_t getIRy1() { return IR_object_y1; }; - /** - * IR object 1 size read from the Wii IR camera. - * @return The size of the object in the range 0-15. - */ - uint8_t getIRs1() { return IR_object_s1; }; + /** + * IR object 1 x-position read from the Wii IR camera. + * @return The x-position of the object in the range 0-1023. + */ + uint16_t getIRx1() { + return IR_object_x1; + }; - /** - * IR object 2 x-position read from the Wii IR camera. - * @return The x-position of the object in the range 0-1023. - */ - uint16_t getIRx2() { return IR_object_x2; }; - /** - * IR object 2 y-position read from the Wii IR camera. - * @return The y-position of the object in the range 0-767. - */ - uint16_t getIRy2() { return IR_object_y2; }; - /** - * IR object 2 size read from the Wii IR camera. - * @return The size of the object in the range 0-15. - */ - uint8_t getIRs2() { return IR_object_s2; }; + /** + * IR object 1 y-position read from the Wii IR camera. + * @return The y-position of the object in the range 0-767. + */ + uint16_t getIRy1() { + return IR_object_y1; + }; - /** - * IR object 3 x-position read from the Wii IR camera. - * @return The x-position of the object in the range 0-1023. - */ - uint16_t getIRx3() { return IR_object_x3; }; - /** - * IR object 3 y-position read from the Wii IR camera. - * @return The y-position of the object in the range 0-767. - */ - uint16_t getIRy3() { return IR_object_y3; }; - /** - * IR object 3 size read from the Wii IR camera. - * @return The size of the object in the range 0-15. - */ - uint8_t getIRs3() { return IR_object_s3; }; + /** + * IR object 1 size read from the Wii IR camera. + * @return The size of the object in the range 0-15. + */ + uint8_t getIRs1() { + return IR_object_s1; + }; - /** - * IR object 4 x-position read from the Wii IR camera. - * @return The x-position of the object in the range 0-1023. - */ - uint16_t getIRx4() { return IR_object_x4; }; - /** - * IR object 4 y-position read from the Wii IR camera. - * @return The y-position of the object in the range 0-767. - */ - uint16_t getIRy4() { return IR_object_y4; }; - /** - * IR object 4 size read from the Wii IR camera. - * @return The size of the object in the range 0-15. - */ - uint8_t getIRs4() { return IR_object_s4; }; + /** + * IR object 2 x-position read from the Wii IR camera. + * @return The x-position of the object in the range 0-1023. + */ + uint16_t getIRx2() { + return IR_object_x2; + }; - /** - * Use this to check if the camera is enabled or not. - * If not call WII#IRinitialize to initialize the IR camera. - * @return True if it's enabled, false if not. - */ - bool isIRCameraEnabled() { return (wiiState & 0x08); }; - /**@}*/ + /** + * IR object 2 y-position read from the Wii IR camera. + * @return The y-position of the object in the range 0-767. + */ + uint16_t getIRy2() { + return IR_object_y2; + }; + + /** + * IR object 2 size read from the Wii IR camera. + * @return The size of the object in the range 0-15. + */ + uint8_t getIRs2() { + return IR_object_s2; + }; + + /** + * IR object 3 x-position read from the Wii IR camera. + * @return The x-position of the object in the range 0-1023. + */ + uint16_t getIRx3() { + return IR_object_x3; + }; + + /** + * IR object 3 y-position read from the Wii IR camera. + * @return The y-position of the object in the range 0-767. + */ + uint16_t getIRy3() { + return IR_object_y3; + }; + + /** + * IR object 3 size read from the Wii IR camera. + * @return The size of the object in the range 0-15. + */ + uint8_t getIRs3() { + return IR_object_s3; + }; + + /** + * IR object 4 x-position read from the Wii IR camera. + * @return The x-position of the object in the range 0-1023. + */ + uint16_t getIRx4() { + return IR_object_x4; + }; + + /** + * IR object 4 y-position read from the Wii IR camera. + * @return The y-position of the object in the range 0-767. + */ + uint16_t getIRy4() { + return IR_object_y4; + }; + + /** + * IR object 4 size read from the Wii IR camera. + * @return The size of the object in the range 0-15. + */ + uint8_t getIRs4() { + return IR_object_s4; + }; + + /** + * Use this to check if the camera is enabled or not. + * If not call WII#IRinitialize to initialize the IR camera. + * @return True if it's enabled, false if not. + */ + bool isIRCameraEnabled() { + return(wiiState & 0x08); + }; + /**@}*/ #endif - + private: - /* Mandatory members */ - BTD *pBtd; - - void L2CAP_task(); // L2CAP state machine - - /* Variables filled from HCI event management */ - uint16_t hci_handle; - bool activeConnection; // Used to indicate if it's already has established a connection - - /* variables used by high level L2CAP task */ - uint8_t l2cap_state; - uint16_t l2cap_event_flag;// l2cap flags of received bluetooth events - - uint32_t ButtonState; - uint32_t OldButtonState; - uint32_t ButtonClickState; - uint16_t hatValues[4]; - - uint8_t HIDBuffer[3];// Used to store HID commands - - uint16_t stateCounter; - bool unknownExtensionConnected; - bool extensionConnected; - - /* L2CAP Channels */ - uint8_t control_scid[2]; // L2CAP source CID for HID_Control - uint8_t control_dcid[2]; // 0x0060 - uint8_t interrupt_scid[2]; // L2CAP source CID for HID_Interrupt - uint8_t interrupt_dcid[2]; // 0x0061 - uint8_t identifier; // Identifier for connection - - /* HID Commands */ - void HID_Command(uint8_t* data, uint8_t nbytes); - void setReportMode(bool continuous, uint8_t mode); - void statusRequest(); - - void writeData(uint32_t offset, uint8_t size, uint8_t* data); - void initExtension1(); - void initExtension2(); - - void readData(uint32_t offset, uint16_t size, bool EEPROM); - void readExtensionType(); - void readCalData(); - - void checkMotionPresent(); // Used to see if a Motion Plus is connected to the Wiimote - void initMotionPlus(); - void activateMotionPlus(); + /* Mandatory members */ + BTD *pBtd; - double pitch; // Fusioned angle using a complimentary filter if the Motion Plus is connected - double roll; // Fusioned angle using a complimentary filter if the Motion Plus is connected - - bool activateNunchuck; - bool motionValuesReset; // This bool is true when the gyro values has been reset - unsigned long timer; + void L2CAP_task(); // L2CAP state machine + + /* Variables filled from HCI event management */ + uint16_t hci_handle; + bool activeConnection; // Used to indicate if it's already has established a connection + + /* variables used by high level L2CAP task */ + uint8_t l2cap_state; + uint16_t l2cap_event_flag; // l2cap flags of received bluetooth events + + uint32_t ButtonState; + uint32_t OldButtonState; + uint32_t ButtonClickState; + uint16_t hatValues[4]; + + uint8_t HIDBuffer[3]; // Used to store HID commands + + uint16_t stateCounter; + bool unknownExtensionConnected; + bool extensionConnected; + + /* L2CAP Channels */ + uint8_t control_scid[2]; // L2CAP source CID for HID_Control + uint8_t control_dcid[2]; // 0x0060 + uint8_t interrupt_scid[2]; // L2CAP source CID for HID_Interrupt + uint8_t interrupt_dcid[2]; // 0x0061 + uint8_t identifier; // Identifier for connection + + /* HID Commands */ + void HID_Command(uint8_t* data, uint8_t nbytes); + void setReportMode(bool continuous, uint8_t mode); + void statusRequest(); + + void writeData(uint32_t offset, uint8_t size, uint8_t* data); + void initExtension1(); + void initExtension2(); + + void readData(uint32_t offset, uint16_t size, bool EEPROM); + void readExtensionType(); + void readCalData(); + + void checkMotionPresent(); // Used to see if a Motion Plus is connected to the Wiimote + void initMotionPlus(); + void activateMotionPlus(); + + double pitch; // Fusioned angle using a complimentary filter if the Motion Plus is connected + double roll; // Fusioned angle using a complimentary filter if the Motion Plus is connected + + bool activateNunchuck; + bool motionValuesReset; // This bool is true when the gyro values has been reset + unsigned long timer; + + uint8_t wiiState; // Stores the value in l2capinbuf[12] - (0x01: Battery is nearly empty), (0x02: An Extension Controller is connected), (0x04: Speaker enabled), (0x08: IR enabled), (0x10: LED1, 0x20: LED2, 0x40: LED3, 0x80: LED4) + uint8_t batteryLevel; - uint8_t wiiState; // Stores the value in l2capinbuf[12] - (0x01: Battery is nearly empty), (0x02: An Extension Controller is connected), (0x04: Speaker enabled), (0x08: IR enabled), (0x10: LED1, 0x20: LED2, 0x40: LED3, 0x80: LED4) - uint8_t batteryLevel; - #ifdef WIICAMERA - /* Private function and variables for the readings from teh IR Camera */ - void enableIRCamera1(); // Sets bit 2 of output report 13 - void enableIRCamera2(); // Sets bit 2 of output report 1A - void writeSensitivityBlock1(); - void writeSensitivityBlock2(); - void write0x08Value(); - void setWiiModeNumber(uint8_t mode_number); - - uint16_t IR_object_x1; // IR x position 10 bits - uint16_t IR_object_y1; // IR y position 10 bits - uint8_t IR_object_s1; // IR size value - uint16_t IR_object_x2; - uint16_t IR_object_y2; - uint8_t IR_object_s2; - uint16_t IR_object_x3; // IR x position 10 bits - uint16_t IR_object_y3; // IR y position 10 bits - uint8_t IR_object_s3; // IR size value - uint16_t IR_object_x4; - uint16_t IR_object_y4; - uint8_t IR_object_s4; + /* Private function and variables for the readings from teh IR Camera */ + void enableIRCamera1(); // Sets bit 2 of output report 13 + void enableIRCamera2(); // Sets bit 2 of output report 1A + void writeSensitivityBlock1(); + void writeSensitivityBlock2(); + void write0x08Value(); + void setWiiModeNumber(uint8_t mode_number); + + uint16_t IR_object_x1; // IR x position 10 bits + uint16_t IR_object_y1; // IR y position 10 bits + uint8_t IR_object_s1; // IR size value + uint16_t IR_object_x2; + uint16_t IR_object_y2; + uint8_t IR_object_s2; + uint16_t IR_object_x3; // IR x position 10 bits + uint16_t IR_object_y3; // IR y position 10 bits + uint8_t IR_object_s3; // IR size value + uint16_t IR_object_x4; + uint16_t IR_object_y4; + uint8_t IR_object_s4; #endif }; #endif \ No newline at end of file diff --git a/XBOXRECV.cpp b/XBOXRECV.cpp index ab0df9ef..72f34b50 100644 --- a/XBOXRECV.cpp +++ b/XBOXRECV.cpp @@ -22,395 +22,411 @@ //#define EXTRADEBUG // Uncomment to get even more debugging data //#define PRINTREPORT // Uncomment to print the report send by the Xbox 360 Controller -XBOXRECV::XBOXRECV(USB *p): +XBOXRECV::XBOXRECV(USB *p) : pUsb(p), // pointer to USB class instance - mandatory bAddress(0), // device address - mandatory bPollEnable(false) { // don't start polling before dongle is connected - for(uint8_t i=0; iRegisterDeviceClass(this); //set devConfig[] entry + if (pUsb) // register in USB subsystem + pUsb->RegisterDeviceClass(this); //set devConfig[] entry } uint8_t XBOXRECV::Init(uint8_t parent, uint8_t port, bool lowspeed) { - uint8_t buf[sizeof(USB_DEVICE_DESCRIPTOR)]; - uint8_t rcode; - UsbDevice *p = NULL; - EpInfo *oldep_ptr = NULL; - uint16_t PID; - uint16_t VID; + uint8_t buf[sizeof (USB_DEVICE_DESCRIPTOR)]; + uint8_t rcode; + UsbDevice *p = NULL; + EpInfo *oldep_ptr = NULL; + uint16_t PID; + uint16_t VID; - // get memory address of USB device address pool - AddressPool &addrPool = pUsb->GetAddressPool(); + // get memory address of USB device address pool + AddressPool &addrPool = pUsb->GetAddressPool(); #ifdef EXTRADEBUG - Notify(PSTR("\r\nXBOXRECV Init"), 0x80); + Notify(PSTR("\r\nXBOXRECV Init"), 0x80); #endif - // check if address has already been assigned to an instance - if (bAddress) { + // check if address has already been assigned to an instance + if (bAddress) { #ifdef DEBUG - Notify(PSTR("\r\nAddress in use"), 0x80); + Notify(PSTR("\r\nAddress in use"), 0x80); #endif - return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE; - } + return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE; + } - // Get pointer to pseudo device with address 0 assigned - p = addrPool.GetUsbDevicePtr(0); + // Get pointer to pseudo device with address 0 assigned + p = addrPool.GetUsbDevicePtr(0); - if (!p) { + if (!p) { #ifdef DEBUG - Notify(PSTR("\r\nAddress not found"), 0x80); + Notify(PSTR("\r\nAddress not found"), 0x80); #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 - Notify(PSTR("\r\nepinfo is null"), 0x80); + Notify(PSTR("\r\nepinfo is null"), 0x80); #endif - return USB_ERROR_EPINFO_IS_NULL; - } + return USB_ERROR_EPINFO_IS_NULL; + } - // Save old pointer to EP_RECORD of address 0 - oldep_ptr = p->epinfo; + // Save old pointer to EP_RECORD of address 0 + oldep_ptr = p->epinfo; - // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence - p->epinfo = epInfo; + // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence + p->epinfo = epInfo; - p->lowspeed = lowspeed; + p->lowspeed = lowspeed; - // Get device descriptor - rcode = pUsb->getDevDescr(0, 0, sizeof(USB_DEVICE_DESCRIPTOR), (uint8_t*)buf);// Get device descriptor - addr, ep, nbytes, data - // Restore p->epinfo - p->epinfo = oldep_ptr; + // Get device descriptor + rcode = pUsb->getDevDescr(0, 0, sizeof (USB_DEVICE_DESCRIPTOR), (uint8_t*)buf); // Get device descriptor - addr, ep, nbytes, data + // Restore p->epinfo + p->epinfo = oldep_ptr; - if(rcode) - goto FailGetDevDescr; + if (rcode) + goto FailGetDevDescr; - VID = ((USB_DEVICE_DESCRIPTOR*)buf)->idVendor; - PID = ((USB_DEVICE_DESCRIPTOR*)buf)->idProduct; + VID = ((USB_DEVICE_DESCRIPTOR*)buf)->idVendor; + PID = ((USB_DEVICE_DESCRIPTOR*)buf)->idProduct; - if(VID != XBOX_VID && VID != MADCATZ_VID) // We just check if it's a xbox receiver using the Vendor ID - goto FailUnknownDevice; - else if(PID != XBOX_WIRELESS_RECEIVER_PID && PID != XBOX_WIRELESS_RECEIVER_THIRD_PARTY_PID) { + if (VID != XBOX_VID && VID != MADCATZ_VID) // We just check if it's a xbox receiver using the Vendor ID + goto FailUnknownDevice; + else if (PID != XBOX_WIRELESS_RECEIVER_PID && PID != XBOX_WIRELESS_RECEIVER_THIRD_PARTY_PID) { #ifdef DEBUG - Notify(PSTR("\r\nYou'll need a wireless receiver for this libary to work"), 0x80); + Notify(PSTR("\r\nYou'll need a wireless receiver for this libary to work"), 0x80); #endif - goto FailUnknownDevice; - } + goto FailUnknownDevice; + } - // Allocate new address according to device class - bAddress = addrPool.AllocAddress(parent, false, port); + // Allocate new address according to device class + bAddress = addrPool.AllocAddress(parent, false, port); - if (!bAddress) - return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; + if (!bAddress) + return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; - // Extract Max Packet Size from device descriptor - epInfo[0].maxPktSize = (uint8_t)((USB_DEVICE_DESCRIPTOR*)buf)->bMaxPacketSize0; + // Extract Max Packet Size from device descriptor + epInfo[0].maxPktSize = (uint8_t)((USB_DEVICE_DESCRIPTOR*)buf)->bMaxPacketSize0; - // Assign new address to the device - rcode = pUsb->setAddr( 0, 0, bAddress ); - if (rcode) { + // Assign new address to the device + rcode = pUsb->setAddr(0, 0, bAddress); + if (rcode) { + p->lowspeed = false; + addrPool.FreeAddress(bAddress); + bAddress = 0; +#ifdef DEBUG + Notify(PSTR("\r\nsetAddr: "), 0x80); +#endif + PrintHex (rcode, 0x80); + return rcode; + } +#ifdef EXTRADEBUG + Notify(PSTR("\r\nAddr: "), 0x80); + PrintHex (bAddress, 0x80); +#endif p->lowspeed = false; - addrPool.FreeAddress(bAddress); - bAddress = 0; -#ifdef DEBUG - Notify(PSTR("\r\nsetAddr: "), 0x80); -#endif - PrintHex(rcode, 0x80); - return rcode; - } -#ifdef EXTRADEBUG - Notify(PSTR("\r\nAddr: "), 0x80); - PrintHex(bAddress, 0x80); -#endif - p->lowspeed = false; - //get pointer to assigned address record - p = addrPool.GetUsbDevicePtr(bAddress); - if (!p) - return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; + //get pointer to assigned address record + p = addrPool.GetUsbDevicePtr(bAddress); + if (!p) + return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; - p->lowspeed = lowspeed; + p->lowspeed = lowspeed; - // Assign epInfo to epinfo pointer - only EP0 is known - rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); - if (rcode) - goto FailSetDevTblEntry; + // Assign epInfo to epinfo pointer - only EP0 is known + rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); + if (rcode) + goto FailSetDevTblEntry; - /* The application will work in reduced host mode, so we can save program and data - memory space. After verifying the VID we will use known values for the - configuration values for device, interface, endpoints and HID for the XBOX360 Wireless receiver */ + /* The application will work in reduced host mode, so we can save program and data + memory space. After verifying the VID we will use known values for the + configuration values for device, interface, endpoints and HID for the XBOX360 Wireless receiver */ - /* Initialize data structures for endpoints of device */ - epInfo[ XBOX_INPUT_PIPE_1 ].epAddr = 0x01; // XBOX 360 report endpoint - poll interval 1ms - epInfo[ XBOX_INPUT_PIPE_1 ].epAttribs = EP_INTERRUPT; - epInfo[ XBOX_INPUT_PIPE_1 ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints - epInfo[ XBOX_INPUT_PIPE_1 ].maxPktSize = EP_MAXPKTSIZE; - epInfo[ XBOX_INPUT_PIPE_1 ].bmSndToggle = bmSNDTOG0; - epInfo[ XBOX_INPUT_PIPE_1 ].bmRcvToggle = bmRCVTOG0; - epInfo[ XBOX_OUTPUT_PIPE_1 ].epAddr = 0x01; // XBOX 360 output endpoint - poll interval 8ms - epInfo[ XBOX_OUTPUT_PIPE_1 ].epAttribs = EP_INTERRUPT; - epInfo[ XBOX_OUTPUT_PIPE_1 ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints - epInfo[ XBOX_OUTPUT_PIPE_1 ].maxPktSize = EP_MAXPKTSIZE; - epInfo[ XBOX_OUTPUT_PIPE_1 ].bmSndToggle = bmSNDTOG0; - epInfo[ XBOX_OUTPUT_PIPE_1 ].bmRcvToggle = bmRCVTOG0; + /* Initialize data structures for endpoints of device */ + epInfo[ XBOX_INPUT_PIPE_1 ].epAddr = 0x01; // XBOX 360 report endpoint - poll interval 1ms + epInfo[ XBOX_INPUT_PIPE_1 ].epAttribs = EP_INTERRUPT; + epInfo[ XBOX_INPUT_PIPE_1 ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints + epInfo[ XBOX_INPUT_PIPE_1 ].maxPktSize = EP_MAXPKTSIZE; + epInfo[ XBOX_INPUT_PIPE_1 ].bmSndToggle = bmSNDTOG0; + epInfo[ XBOX_INPUT_PIPE_1 ].bmRcvToggle = bmRCVTOG0; + epInfo[ XBOX_OUTPUT_PIPE_1 ].epAddr = 0x01; // XBOX 360 output endpoint - poll interval 8ms + epInfo[ XBOX_OUTPUT_PIPE_1 ].epAttribs = EP_INTERRUPT; + epInfo[ XBOX_OUTPUT_PIPE_1 ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints + epInfo[ XBOX_OUTPUT_PIPE_1 ].maxPktSize = EP_MAXPKTSIZE; + epInfo[ XBOX_OUTPUT_PIPE_1 ].bmSndToggle = bmSNDTOG0; + epInfo[ XBOX_OUTPUT_PIPE_1 ].bmRcvToggle = bmRCVTOG0; - epInfo[ XBOX_INPUT_PIPE_2 ].epAddr = 0x03; // XBOX 360 report endpoint - poll interval 1ms - epInfo[ XBOX_INPUT_PIPE_2 ].epAttribs = EP_INTERRUPT; - epInfo[ XBOX_INPUT_PIPE_2 ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints - epInfo[ XBOX_INPUT_PIPE_2 ].maxPktSize = EP_MAXPKTSIZE; - epInfo[ XBOX_INPUT_PIPE_2 ].bmSndToggle = bmSNDTOG0; - epInfo[ XBOX_INPUT_PIPE_2 ].bmRcvToggle = bmRCVTOG0; - epInfo[ XBOX_OUTPUT_PIPE_2 ].epAddr = 0x03; // XBOX 360 output endpoint - poll interval 8ms - epInfo[ XBOX_OUTPUT_PIPE_2 ].epAttribs = EP_INTERRUPT; - epInfo[ XBOX_OUTPUT_PIPE_2 ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints - epInfo[ XBOX_OUTPUT_PIPE_2 ].maxPktSize = EP_MAXPKTSIZE; - epInfo[ XBOX_OUTPUT_PIPE_2 ].bmSndToggle = bmSNDTOG0; - epInfo[ XBOX_OUTPUT_PIPE_2 ].bmRcvToggle = bmRCVTOG0; + epInfo[ XBOX_INPUT_PIPE_2 ].epAddr = 0x03; // XBOX 360 report endpoint - poll interval 1ms + epInfo[ XBOX_INPUT_PIPE_2 ].epAttribs = EP_INTERRUPT; + epInfo[ XBOX_INPUT_PIPE_2 ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints + epInfo[ XBOX_INPUT_PIPE_2 ].maxPktSize = EP_MAXPKTSIZE; + epInfo[ XBOX_INPUT_PIPE_2 ].bmSndToggle = bmSNDTOG0; + epInfo[ XBOX_INPUT_PIPE_2 ].bmRcvToggle = bmRCVTOG0; + epInfo[ XBOX_OUTPUT_PIPE_2 ].epAddr = 0x03; // XBOX 360 output endpoint - poll interval 8ms + epInfo[ XBOX_OUTPUT_PIPE_2 ].epAttribs = EP_INTERRUPT; + epInfo[ XBOX_OUTPUT_PIPE_2 ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints + epInfo[ XBOX_OUTPUT_PIPE_2 ].maxPktSize = EP_MAXPKTSIZE; + epInfo[ XBOX_OUTPUT_PIPE_2 ].bmSndToggle = bmSNDTOG0; + epInfo[ XBOX_OUTPUT_PIPE_2 ].bmRcvToggle = bmRCVTOG0; - epInfo[ XBOX_INPUT_PIPE_3 ].epAddr = 0x05; // XBOX 360 report endpoint - poll interval 1ms - epInfo[ XBOX_INPUT_PIPE_3 ].epAttribs = EP_INTERRUPT; - epInfo[ XBOX_INPUT_PIPE_3 ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints - epInfo[ XBOX_INPUT_PIPE_3 ].maxPktSize = EP_MAXPKTSIZE; - epInfo[ XBOX_INPUT_PIPE_3 ].bmSndToggle = bmSNDTOG0; - epInfo[ XBOX_INPUT_PIPE_3 ].bmRcvToggle = bmRCVTOG0; - epInfo[ XBOX_OUTPUT_PIPE_3 ].epAddr = 0x05; // XBOX 360 output endpoint - poll interval 8ms - epInfo[ XBOX_OUTPUT_PIPE_3 ].epAttribs = EP_INTERRUPT; - epInfo[ XBOX_OUTPUT_PIPE_3 ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints - epInfo[ XBOX_OUTPUT_PIPE_3 ].maxPktSize = EP_MAXPKTSIZE; - epInfo[ XBOX_OUTPUT_PIPE_3 ].bmSndToggle = bmSNDTOG0; - epInfo[ XBOX_OUTPUT_PIPE_3 ].bmRcvToggle = bmRCVTOG0; + epInfo[ XBOX_INPUT_PIPE_3 ].epAddr = 0x05; // XBOX 360 report endpoint - poll interval 1ms + epInfo[ XBOX_INPUT_PIPE_3 ].epAttribs = EP_INTERRUPT; + epInfo[ XBOX_INPUT_PIPE_3 ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints + epInfo[ XBOX_INPUT_PIPE_3 ].maxPktSize = EP_MAXPKTSIZE; + epInfo[ XBOX_INPUT_PIPE_3 ].bmSndToggle = bmSNDTOG0; + epInfo[ XBOX_INPUT_PIPE_3 ].bmRcvToggle = bmRCVTOG0; + epInfo[ XBOX_OUTPUT_PIPE_3 ].epAddr = 0x05; // XBOX 360 output endpoint - poll interval 8ms + epInfo[ XBOX_OUTPUT_PIPE_3 ].epAttribs = EP_INTERRUPT; + epInfo[ XBOX_OUTPUT_PIPE_3 ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints + epInfo[ XBOX_OUTPUT_PIPE_3 ].maxPktSize = EP_MAXPKTSIZE; + epInfo[ XBOX_OUTPUT_PIPE_3 ].bmSndToggle = bmSNDTOG0; + epInfo[ XBOX_OUTPUT_PIPE_3 ].bmRcvToggle = bmRCVTOG0; - epInfo[ XBOX_INPUT_PIPE_4 ].epAddr = 0x07; // XBOX 360 report endpoint - poll interval 1ms - epInfo[ XBOX_INPUT_PIPE_4 ].epAttribs = EP_INTERRUPT; - epInfo[ XBOX_INPUT_PIPE_4 ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints - epInfo[ XBOX_INPUT_PIPE_4 ].maxPktSize = EP_MAXPKTSIZE; - epInfo[ XBOX_INPUT_PIPE_4 ].bmSndToggle = bmSNDTOG0; - epInfo[ XBOX_INPUT_PIPE_4 ].bmRcvToggle = bmRCVTOG0; - epInfo[ XBOX_OUTPUT_PIPE_4 ].epAddr = 0x07; // XBOX 360 output endpoint - poll interval 8ms - epInfo[ XBOX_OUTPUT_PIPE_4 ].epAttribs = EP_INTERRUPT; - epInfo[ XBOX_OUTPUT_PIPE_4 ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints - epInfo[ XBOX_OUTPUT_PIPE_4 ].maxPktSize = EP_MAXPKTSIZE; - epInfo[ XBOX_OUTPUT_PIPE_4 ].bmSndToggle = bmSNDTOG0; - epInfo[ XBOX_OUTPUT_PIPE_4 ].bmRcvToggle = bmRCVTOG0; + epInfo[ XBOX_INPUT_PIPE_4 ].epAddr = 0x07; // XBOX 360 report endpoint - poll interval 1ms + epInfo[ XBOX_INPUT_PIPE_4 ].epAttribs = EP_INTERRUPT; + epInfo[ XBOX_INPUT_PIPE_4 ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints + epInfo[ XBOX_INPUT_PIPE_4 ].maxPktSize = EP_MAXPKTSIZE; + epInfo[ XBOX_INPUT_PIPE_4 ].bmSndToggle = bmSNDTOG0; + epInfo[ XBOX_INPUT_PIPE_4 ].bmRcvToggle = bmRCVTOG0; + epInfo[ XBOX_OUTPUT_PIPE_4 ].epAddr = 0x07; // XBOX 360 output endpoint - poll interval 8ms + epInfo[ XBOX_OUTPUT_PIPE_4 ].epAttribs = EP_INTERRUPT; + epInfo[ XBOX_OUTPUT_PIPE_4 ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints + epInfo[ XBOX_OUTPUT_PIPE_4 ].maxPktSize = EP_MAXPKTSIZE; + epInfo[ XBOX_OUTPUT_PIPE_4 ].bmSndToggle = bmSNDTOG0; + epInfo[ XBOX_OUTPUT_PIPE_4 ].bmRcvToggle = bmRCVTOG0; - rcode = pUsb->setEpInfoEntry(bAddress, 9, epInfo); - if( rcode ) - goto FailSetDevTblEntry; + rcode = pUsb->setEpInfoEntry(bAddress, 9, epInfo); + if (rcode) + goto FailSetDevTblEntry; - delay(200);//Give time for address change + delay(200); //Give time for address change - rcode = pUsb->setConf(bAddress, epInfo[ XBOX_CONTROL_PIPE ].epAddr, 1); - if( rcode ) - goto FailSetConf; + rcode = pUsb->setConf(bAddress, epInfo[ XBOX_CONTROL_PIPE ].epAddr, 1); + if (rcode) + goto FailSetConf; #ifdef DEBUG - Notify(PSTR("\r\nXbox Wireless Receiver Connected\r\n"), 0x80); + Notify(PSTR("\r\nXbox Wireless Receiver Connected\r\n"), 0x80); #endif - XboxReceiverConnected = true; - bPollEnable = true; - return 0; // successful configuration + XboxReceiverConnected = true; + bPollEnable = true; + return 0; // successful configuration - /* diagnostic messages */ + /* diagnostic messages */ FailGetDevDescr: #ifdef DEBUG - Notify(PSTR("\r\ngetDevDescr:"), 0x80); + Notify(PSTR("\r\ngetDevDescr:"), 0x80); #endif - goto Fail; + goto Fail; FailSetDevTblEntry: #ifdef DEBUG - Notify(PSTR("\r\nsetDevTblEn:"), 0x80); + Notify(PSTR("\r\nsetDevTblEn:"), 0x80); #endif - goto Fail; + goto Fail; FailSetConf: #ifdef DEBUG - Notify(PSTR("\r\nsetConf:"), 0x80); + Notify(PSTR("\r\nsetConf:"), 0x80); #endif - goto Fail; + goto Fail; FailUnknownDevice: #ifdef DEBUG - Notify(PSTR("\r\nUnknown Device Connected - VID: "), 0x80); - PrintHex(VID, 0x80); - Notify(PSTR(" PID: "), 0x80); - PrintHex(PID, 0x80); + Notify(PSTR("\r\nUnknown Device Connected - VID: "), 0x80); + PrintHex (VID, 0x80); + Notify(PSTR(" PID: "), 0x80); + PrintHex (PID, 0x80); #endif - rcode = USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; - goto Fail; + rcode = USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; + goto Fail; Fail: #ifdef DEBUG - Notify(PSTR("\r\nXbox 360 Init Failed, error code: "), 0x80); - Serial.print(rcode,HEX); + Notify(PSTR("\r\nXbox 360 Init Failed, error code: "), 0x80); + Serial.print(rcode, HEX); #endif - Release(); - return rcode; + Release(); + return rcode; } /* Performs a cleanup after failed Init() attempt */ uint8_t XBOXRECV::Release() { - XboxReceiverConnected = false; - for(uint8_t i=0;i<4;i++) - Xbox360Connected[i] = 0x00; - pUsb->GetAddressPool().FreeAddress(bAddress); - bAddress = 0; - bPollEnable = false; - return 0; + XboxReceiverConnected = false; + for (uint8_t i = 0; i < 4; i++) + Xbox360Connected[i] = 0x00; + pUsb->GetAddressPool().FreeAddress(bAddress); + bAddress = 0; + bPollEnable = false; + return 0; } + uint8_t XBOXRECV::Poll() { - if (!bPollEnable) - return 0; - if(!timer || ((millis() - timer) > 3000)) { // Run checkStatus every 3 seconds - timer = millis(); - checkStatus(); - } - uint8_t inputPipe; - uint16_t bufferSize; - for(uint8_t i=0;i<4;i++) { - switch (i) { - case 0: inputPipe = XBOX_INPUT_PIPE_1; break; - case 1: inputPipe = XBOX_INPUT_PIPE_2; break; - case 2: inputPipe = XBOX_INPUT_PIPE_3; break; - case 3: inputPipe = XBOX_INPUT_PIPE_4; break; + if (!bPollEnable) + return 0; + if (!timer || ((millis() - timer) > 3000)) { // Run checkStatus every 3 seconds + timer = millis(); + checkStatus(); } - bufferSize = EP_MAXPKTSIZE; // This is the maximum number of bytes we want to receive - pUsb->inTransfer(bAddress, epInfo[ inputPipe ].epAddr, &bufferSize, readBuf); - if(bufferSize > 0) { // The number of received bytes + uint8_t inputPipe; + uint16_t bufferSize; + for (uint8_t i = 0; i < 4; i++) { + switch (i) { + case 0: inputPipe = XBOX_INPUT_PIPE_1; + break; + case 1: inputPipe = XBOX_INPUT_PIPE_2; + break; + case 2: inputPipe = XBOX_INPUT_PIPE_3; + break; + case 3: inputPipe = XBOX_INPUT_PIPE_4; + break; + } + bufferSize = EP_MAXPKTSIZE; // This is the maximum number of bytes we want to receive + pUsb->inTransfer(bAddress, epInfo[ inputPipe ].epAddr, &bufferSize, readBuf); + if (bufferSize > 0) { // The number of received bytes #ifdef EXTRADEBUG - Notify(PSTR("Bytes Received: "), 0x80); - Serial.print(bufferSize); - Notify(PSTR("\r\n"), 0x80); + Notify(PSTR("Bytes Received: "), 0x80); + Serial.print(bufferSize); + Notify(PSTR("\r\n"), 0x80); #endif - readReport(i); + readReport(i); #ifdef PRINTREPORT - printReport(i,bufferSize); // Uncomment "#define PRINTREPORT" to print the report send by the Xbox 360 Controller + printReport(i, bufferSize); // Uncomment "#define PRINTREPORT" to print the report send by the Xbox 360 Controller #endif + } } - } - return 0; + return 0; } void XBOXRECV::readReport(uint8_t controller) { - if (readBuf == NULL) - return; - // This report is send when a controller is connected and disconnected - if(readBuf[0] == 0x08 && readBuf[1] != Xbox360Connected[controller]) { - Xbox360Connected[controller] = readBuf[1]; + if (readBuf == NULL) + return; + // This report is send when a controller is connected and disconnected + if (readBuf[0] == 0x08 && readBuf[1] != Xbox360Connected[controller]) { + Xbox360Connected[controller] = readBuf[1]; #ifdef DEBUG - Notify(PSTR("Controller "), 0x80); - Serial.print(controller); + Notify(PSTR("Controller "), 0x80); + Serial.print(controller); #endif - if(Xbox360Connected[controller]) { + if (Xbox360Connected[controller]) { #ifdef DEBUG - char* str = 0; - switch(readBuf[1]) { - case 0x80: str = PSTR(" as controller\r\n"); break; - case 0x40: str = PSTR(" as headset\r\n"); break; - case 0xC0: str = PSTR(" as controller+headset\r\n"); break; - } - Notify(PSTR(": connected"), 0x80); - Notify(str, 0x80); + char* str = 0; + switch (readBuf[1]) { + case 0x80: str = PSTR(" as controller\r\n"); + break; + case 0x40: str = PSTR(" as headset\r\n"); + break; + case 0xC0: str = PSTR(" as controller+headset\r\n"); + break; + } + Notify(PSTR(": connected"), 0x80); + Notify(str, 0x80); #endif - LED led; - switch (controller) { - case 0: led = LED1; break; - case 1: led = LED2; break; - case 2: led = LED3; break; - case 3: led = LED4; break; - } - setLedOn(controller,led); + LED led; + switch (controller) { + case 0: led = LED1; + break; + case 1: led = LED2; + break; + case 2: led = LED3; + break; + case 3: led = LED4; + break; + } + setLedOn(controller, led); + } +#ifdef DEBUG + else + Notify(PSTR(": disconnected\r\n"), 0x80); +#endif + return; } -#ifdef DEBUG - else - Notify(PSTR(": disconnected\r\n"), 0x80); -#endif - return; - } - // Controller status report - if(readBuf[1] == 0x00 && readBuf[3] & 0x13 && readBuf[4] >= 0x22) { - controllerStatus[controller] = ((uint16_t)readBuf[3] << 8) | readBuf[4]; - return; - } - if(readBuf[1] != 0x01) // Check if it's the correct report - the receiver also sends different status reports - return; + // Controller status report + if (readBuf[1] == 0x00 && readBuf[3] & 0x13 && readBuf[4] >= 0x22) { + controllerStatus[controller] = ((uint16_t)readBuf[3] << 8) | readBuf[4]; + return; + } + if (readBuf[1] != 0x01) // Check if it's the correct report - the receiver also sends different status reports + return; - // A controller must be connected if it's sending data - if(!Xbox360Connected[controller]) - Xbox360Connected[controller] |= 0x80; + // A controller must be connected if it's sending data + if (!Xbox360Connected[controller]) + Xbox360Connected[controller] |= 0x80; - ButtonState[controller] = (uint32_t)(readBuf[9] | ((uint16_t)readBuf[8] << 8) | ((uint32_t)readBuf[7] << 16) | ((uint32_t)readBuf[6] << 24)); + ButtonState[controller] = (uint32_t)(readBuf[9] | ((uint16_t)readBuf[8] << 8) | ((uint32_t)readBuf[7] << 16) | ((uint32_t)readBuf[6] << 24)); - hatValue[controller][LeftHatX] = (int16_t)(((uint16_t)readBuf[11] << 8) | readBuf[10]); - hatValue[controller][LeftHatY] = (int16_t)(((uint16_t)readBuf[13] << 8) | readBuf[12]); - hatValue[controller][RightHatX] = (int16_t)(((uint16_t)readBuf[15] << 8) | readBuf[14]); - hatValue[controller][RightHatY] = (int16_t)(((uint16_t)readBuf[17] << 8) | readBuf[16]); + hatValue[controller][LeftHatX] = (int16_t)(((uint16_t)readBuf[11] << 8) | readBuf[10]); + hatValue[controller][LeftHatY] = (int16_t)(((uint16_t)readBuf[13] << 8) | readBuf[12]); + hatValue[controller][RightHatX] = (int16_t)(((uint16_t)readBuf[15] << 8) | readBuf[14]); + hatValue[controller][RightHatY] = (int16_t)(((uint16_t)readBuf[17] << 8) | readBuf[16]); - //Notify(PSTR("\r\nButtonState: "), 0x80); - //PrintHex(ButtonState[controller], 0x80); + //Notify(PSTR("\r\nButtonState: "), 0x80); + //PrintHex(ButtonState[controller], 0x80); - if(ButtonState[controller] != OldButtonState[controller]) { - buttonStateChanged[controller] = true; - ButtonClickState[controller] = (ButtonState[controller] >> 16) & ((~OldButtonState[controller]) >> 16); // Update click state variable, but don't include the two trigger buttons L2 and R2 - if(((uint8_t)OldButtonState[controller]) == 0 && ((uint8_t)ButtonState[controller]) != 0) // The L2 and R2 buttons are special as they are analog buttons - R2Clicked[controller] = true; - if((uint8_t)(OldButtonState[controller] >> 8) == 0 && (uint8_t)(ButtonState[controller] >> 8) != 0) - L2Clicked[controller] = true; - OldButtonState[controller] = ButtonState[controller]; - } + if (ButtonState[controller] != OldButtonState[controller]) { + buttonStateChanged[controller] = true; + ButtonClickState[controller] = (ButtonState[controller] >> 16) & ((~OldButtonState[controller]) >> 16); // Update click state variable, but don't include the two trigger buttons L2 and R2 + if (((uint8_t)OldButtonState[controller]) == 0 && ((uint8_t)ButtonState[controller]) != 0) // The L2 and R2 buttons are special as they are analog buttons + R2Clicked[controller] = true; + if ((uint8_t)(OldButtonState[controller] >> 8) == 0 && (uint8_t)(ButtonState[controller] >> 8) != 0) + L2Clicked[controller] = true; + OldButtonState[controller] = ButtonState[controller]; + } } void XBOXRECV::printReport(uint8_t controller, uint8_t nBytes) { //Uncomment "#define PRINTREPORT" to print the report send by the Xbox 360 Controller #ifdef PRINTREPORT - if (readBuf == NULL) - return; - Notify(PSTR("Controller "), 0x80); - Serial.print(controller); - Notify(PSTR(": "), 0x80); - for(uint8_t i = 0; i < nBytes;i++) { - PrintHex(readBuf[i], 0x80); - Serial.print(" "); - } - Serial.println(); + if (readBuf == NULL) + return; + Notify(PSTR("Controller "), 0x80); + Serial.print(controller); + Notify(PSTR(": "), 0x80); + for (uint8_t i = 0; i < nBytes; i++) { + PrintHex (readBuf[i], 0x80); + Serial.print(" "); + } + Serial.println(); #endif } + uint8_t XBOXRECV::getButtonPress(uint8_t controller, Button b) { - if(b == L2) // These are analog buttons - return (uint8_t)(ButtonState[controller] >> 8); - else if(b == R2) - return (uint8_t)ButtonState[controller]; - return (ButtonState[controller] & ((uint32_t)pgm_read_word(&XBOXBUTTONS[(uint8_t)b]) << 16)); + if (b == L2) // These are analog buttons + return (uint8_t)(ButtonState[controller] >> 8); + else if (b == R2) + return (uint8_t)ButtonState[controller]; + return (ButtonState[controller] & ((uint32_t)pgm_read_word(&XBOXBUTTONS[(uint8_t)b]) << 16)); } + bool XBOXRECV::getButtonClick(uint8_t controller, Button b) { - if(b == L2) { - if(L2Clicked[controller]) { - L2Clicked[controller] = false; - return true; + if (b == L2) { + if (L2Clicked[controller]) { + L2Clicked[controller] = false; + return true; + } + return false; + } else if (b == R2) { + if (R2Clicked[controller]) { + R2Clicked[controller] = false; + return true; + } + return false; } - return false; - } - else if(b == R2) { - if(R2Clicked[controller]) { - R2Clicked[controller] = false; - return true; - } - return false; - } - uint16_t button = pgm_read_word(&XBOXBUTTONS[(uint8_t)b]); - bool click = (ButtonClickState[controller] & button); - ButtonClickState[controller] &= ~button; // clear "click" event - return click; + uint16_t button = pgm_read_word(&XBOXBUTTONS[(uint8_t)b]); + bool click = (ButtonClickState[controller] & button); + ButtonClickState[controller] &= ~button; // clear "click" event + return click; } + int16_t XBOXRECV::getAnalogHat(uint8_t controller, AnalogHat a) { - return hatValue[controller][a]; + return hatValue[controller][a]; } + bool XBOXRECV::buttonChanged(uint8_t controller) { - bool state = buttonStateChanged[controller]; - buttonStateChanged[controller] = false; - return state; + bool state = buttonStateChanged[controller]; + buttonStateChanged[controller] = false; + return state; } + /* ControllerStatus Breakdown ControllerStatus[controller] & 0x0001 // 0 @@ -429,81 +445,90 @@ ControllerStatus Breakdown ControllerStatus[controller] & 0x2000 // 0 ControllerStatus[controller] & 0x4000 // 0 ControllerStatus[controller] & 0x8000 // 0 -*/ + */ uint8_t XBOXRECV::getBatteryLevel(uint8_t controller) { - uint8_t batteryLevel = ((controllerStatus[controller] & 0x00C0) >> 6) * 33; - if(batteryLevel == 99) - batteryLevel = 100; - return batteryLevel; + uint8_t batteryLevel = ((controllerStatus[controller] & 0x00C0) >> 6) * 33; + if (batteryLevel == 99) + batteryLevel = 100; + return batteryLevel; } void XBOXRECV::XboxCommand(uint8_t controller, uint8_t* data, uint16_t nbytes) { - uint8_t rcode; - uint8_t outputPipe; - switch (controller) { - case 0: outputPipe = XBOX_OUTPUT_PIPE_1; break; - case 1: outputPipe = XBOX_OUTPUT_PIPE_2; break; - case 2: outputPipe = XBOX_OUTPUT_PIPE_3; break; - case 3: outputPipe = XBOX_OUTPUT_PIPE_4; break; - } - rcode = pUsb->outTransfer(bAddress, epInfo[ outputPipe ].epAddr, nbytes, data); + uint8_t rcode; + uint8_t outputPipe; + switch (controller) { + case 0: outputPipe = XBOX_OUTPUT_PIPE_1; + break; + case 1: outputPipe = XBOX_OUTPUT_PIPE_2; + break; + case 2: outputPipe = XBOX_OUTPUT_PIPE_3; + break; + case 3: outputPipe = XBOX_OUTPUT_PIPE_4; + break; + } + rcode = pUsb->outTransfer(bAddress, epInfo[ outputPipe ].epAddr, nbytes, data); #ifdef EXTRADEBUG - if(rcode) - Notify(PSTR("Error sending Xbox message\r\n"), 0x80); + if (rcode) + Notify(PSTR("Error sending Xbox message\r\n"), 0x80); #endif } -void XBOXRECV::setLedRaw(uint8_t controller, uint8_t value) { - writeBuf[0] = 0x00; - writeBuf[1] = 0x00; - writeBuf[2] = 0x08; - writeBuf[3] = value | 0x40; - XboxCommand(controller, writeBuf, 4); +void XBOXRECV::setLedRaw(uint8_t controller, uint8_t value) { + writeBuf[0] = 0x00; + writeBuf[1] = 0x00; + writeBuf[2] = 0x08; + writeBuf[3] = value | 0x40; + + XboxCommand(controller, writeBuf, 4); } + void XBOXRECV::setLedOn(uint8_t controller, LED led) { - if(led != ALL) // All LEDs can't be on a the same time - setLedRaw(controller,(pgm_read_byte(&XBOXLEDS[(uint8_t)led]))+4); + if (led != ALL) // All LEDs can't be on a the same time + setLedRaw(controller, (pgm_read_byte(&XBOXLEDS[(uint8_t)led])) + 4); } + void XBOXRECV::setLedBlink(uint8_t controller, LED led) { - setLedRaw(controller,pgm_read_byte(&XBOXLEDS[(uint8_t)led])); + setLedRaw(controller, pgm_read_byte(&XBOXLEDS[(uint8_t)led])); } + void XBOXRECV::setLedMode(uint8_t controller, LEDMode ledMode) { // This function is used to do some speciel LED stuff the controller supports - setLedRaw(controller,(uint8_t)ledMode); + setLedRaw(controller, (uint8_t)ledMode); } + /* PC runs this at interval of approx 2 seconds Thanks to BusHound from Perisoft.net for the Windows USB Analysis output Found by timstamp.co.uk -*/ + */ void XBOXRECV::checkStatus() { - if(!bPollEnable) - return; - // Get controller info - writeBuf[0] = 0x08; - writeBuf[1] = 0x00; - writeBuf[2] = 0x0f; - writeBuf[3] = 0xc0; - for(uint8_t i=0; i<4; i++) { - XboxCommand(i, writeBuf, 4); - } - // Get battery status - writeBuf[0] = 0x00; - writeBuf[1] = 0x00; - writeBuf[2] = 0x00; - writeBuf[3] = 0x40; - for(uint8_t i=0; i<4; i++) { - if(Xbox360Connected[i]) - XboxCommand(i, writeBuf, 4); - } + if (!bPollEnable) + return; + // Get controller info + writeBuf[0] = 0x08; + writeBuf[1] = 0x00; + writeBuf[2] = 0x0f; + writeBuf[3] = 0xc0; + for (uint8_t i = 0; i < 4; i++) { + XboxCommand(i, writeBuf, 4); + } + // Get battery status + writeBuf[0] = 0x00; + writeBuf[1] = 0x00; + writeBuf[2] = 0x00; + writeBuf[3] = 0x40; + for (uint8_t i = 0; i < 4; i++) { + if (Xbox360Connected[i]) + XboxCommand(i, writeBuf, 4); + } } void XBOXRECV::setRumbleOn(uint8_t controller, uint8_t lValue, uint8_t rValue) { - writeBuf[0] = 0x00; - writeBuf[1] = 0x01; - writeBuf[2] = 0x0f; - writeBuf[3] = 0xc0; - writeBuf[4] = 0x00; - writeBuf[5] = lValue; // big weight - writeBuf[6] = rValue; // small weight + writeBuf[0] = 0x00; + writeBuf[1] = 0x01; + writeBuf[2] = 0x0f; + writeBuf[3] = 0xc0; + writeBuf[4] = 0x00; + writeBuf[5] = lValue; // big weight + writeBuf[6] = rValue; // small weight - XboxCommand(controller, writeBuf, 7); + XboxCommand(controller, writeBuf, 7); } diff --git a/XBOXRECV.h b/XBOXRECV.h index 6c7ed570..1235f201 100644 --- a/XBOXRECV.h +++ b/XBOXRECV.h @@ -1,15 +1,15 @@ /* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved. - + This software may be distributed and modified under the terms of the GNU General Public License version 2 (GPL2) as published by the Free Software Foundation and appearing in the file GPL2.TXT included in the packaging of this file. Please note that GPL2 Section 2[b] requires that all works based on this software must also be made publicly available under the terms of the GPL2 ("Copyleft"). - + Contact information ------------------- - + Kristian Lauszus, TKJ Electronics Web : http://www.tkjelectronics.com e-mail : kristianl@tkjelectronics.com @@ -27,7 +27,7 @@ #endif #include "Usb.h" -#include "xboxEnums.h" +#include "xboxEnums.h" /* Data Xbox 360 taken from descriptors */ #define EP_MAXPKTSIZE 32 // max size for data via USB @@ -62,167 +62,183 @@ */ class XBOXRECV : public USBDeviceConfig { public: - /** - * Constructor for the XBOXRECV class. - * @param pUsb Pointer to USB class instance. - */ - XBOXRECV(USB *pUsb); + /** + * Constructor for the XBOXRECV class. + * @param pUsb Pointer to USB class instance. + */ + XBOXRECV(USB *pUsb); - /** @name USBDeviceConfig implementation */ - /** - * Initialize the Xbox wireless receiver. - * @param parent Hub number. - * @param port Port number on the hub. - * @param lowspeed Speed of the device. - * @return 0 on success. - */ - virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed); - /** - * Release the USB device. - * @return 0 on success. - */ - virtual uint8_t Release(); - /** - * Poll the USB Input endpoins and run the state machines. - * @return 0 on success. - */ - virtual uint8_t Poll(); - /** - * Get the device address. - * @return The device address. - */ - virtual uint8_t GetAddress() { return bAddress; }; - /** - * Used to check if the controller has been initialized. - * @return True if it's ready. - */ - virtual bool isReady() { return bPollEnable; }; - /**@}*/ + /** @name USBDeviceConfig implementation */ + /** + * Initialize the Xbox wireless receiver. + * @param parent Hub number. + * @param port Port number on the hub. + * @param lowspeed Speed of the device. + * @return 0 on success. + */ + virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed); + /** + * Release the USB device. + * @return 0 on success. + */ + virtual uint8_t Release(); + /** + * Poll the USB Input endpoins and run the state machines. + * @return 0 on success. + */ + virtual uint8_t Poll(); - /** @name Xbox Controller functions */ - /** - * getButtonPress(uint8_t controller, Button b) will return true as long as the button is held down. - * - * While getButtonClick(uint8_t controller, Button b) will only return it once. - * - * So you instance if you need to increase a variable once you would use getButtonClick(uint8_t controller, Button b), - * but if you need to drive a robot forward you would use getButtonPress(uint8_t controller, Button b). - * @param controller The controller to read from. - * @param b ::Button to read. - * @return getButtonClick(uint8_t controller, Button b) will return a bool, but getButtonPress(uint8_t controller, Button b) - * will return a byte if reading ::L2 or ::R2. - */ - uint8_t getButtonPress(uint8_t controller, Button b); - bool getButtonClick(uint8_t controller, Button b); - /**@}*/ + /** + * Get the device address. + * @return The device address. + */ + virtual uint8_t GetAddress() { + return bAddress; + }; - /** @name Xbox Controller functions */ - /** - * Return the analog value from the joysticks on the controller. - * @param controller The controller to read from. - * @param a Either ::LeftHatX, ::LeftHatY, ::RightHatX or ::RightHatY. - * @return Returns a signed 16-bit integer. - */ - int16_t getAnalogHat(uint8_t controller, AnalogHat a); - /** - * Turn rumble off and all the LEDs on the specific controller. - * @param controller The controller to write to. - */ - void setAllOff(uint8_t controller) { setRumbleOn(controller,0,0); setLedOff(controller); }; - /** - * Turn rumble off the specific controller. - * @param controller The controller to write to. - */ - void setRumbleOff(uint8_t controller) { setRumbleOn(controller,0,0); }; - /** - * Turn rumble on. - * @param controller The controller to write to. - * @param lValue Left motor (big weight) inside the controller. - * @param rValue Right motor (small weight) inside the controller. - */ - void setRumbleOn(uint8_t controller, uint8_t lValue, uint8_t rValue); - /** - * Set LED value. Without using the ::LED or ::LEDMode enum. - * @param controller The controller to write to. - * @param value See: - * setLedOff(uint8_t controller), setLedOn(uint8_t controller, LED l), - * setLedBlink(uint8_t controller, LED l), and setLedMode(uint8_t controller, LEDMode lm). - */ - void setLedRaw(uint8_t controller, uint8_t value); - /** - * Turn all LEDs off the specific controller. - * @param controller The controller to write to. - */ - void setLedOff(uint8_t controller) { setLedRaw(controller,0); }; - /** - * Turn on a LED by using the ::LED enum. - * @param controller The controller to write to. - * @param l ::LED1, ::LED2, ::LED3 and ::LED4 is supported by the Xbox controller. - */ - void setLedOn(uint8_t controller, LED l); - /** - * Turn on a LED by using the ::LED enum. - * @param controller The controller to write to. - * @param l ::ALL, ::LED1, ::LED2, ::LED3 and ::LED4 is supported by the Xbox controller. - */ - void setLedBlink(uint8_t controller, LED l); - /** - * Used to set special LED modes supported by the Xbox controller. - * @param controller The controller to write to. - * @param lm See ::LEDMode. - */ - void setLedMode(uint8_t controller, LEDMode lm); - /** - * Used to get the battery level from the controller. - * @param controller The controller to read from. - * @return Returns the battery level in percentage in 33% steps. - */ - uint8_t getBatteryLevel(uint8_t controller); - /** - * Used to check if a button has changed. - * @param controller The controller to read from. - * @return True if a button has changed. - */ - bool buttonChanged(uint8_t controller); - /**@}*/ + /** + * Used to check if the controller has been initialized. + * @return True if it's ready. + */ + virtual bool isReady() { + return bPollEnable; + }; + /**@}*/ - /** True if a wireless receiver is connected. */ - bool XboxReceiverConnected; - /** Variable used to indicate if the XBOX 360 controller is successfully connected. */ - uint8_t Xbox360Connected[4]; - -protected: - /** Pointer to USB class instance. */ - USB *pUsb; - /** Device address. */ - uint8_t bAddress; - /** Endpoint info structure. */ - EpInfo epInfo[XBOX_MAX_ENDPOINTS]; - -private: - bool bPollEnable; + /** @name Xbox Controller functions */ + /** + * getButtonPress(uint8_t controller, Button b) will return true as long as the button is held down. + * + * While getButtonClick(uint8_t controller, Button b) will only return it once. + * + * So you instance if you need to increase a variable once you would use getButtonClick(uint8_t controller, Button b), + * but if you need to drive a robot forward you would use getButtonPress(uint8_t controller, Button b). + * @param controller The controller to read from. + * @param b ::Button to read. + * @return getButtonClick(uint8_t controller, Button b) will return a bool, but getButtonPress(uint8_t controller, Button b) + * will return a byte if reading ::L2 or ::R2. + */ + uint8_t getButtonPress(uint8_t controller, Button b); + bool getButtonClick(uint8_t controller, Button b); + /**@}*/ - /* Variables to store the buttons */ - uint32_t ButtonState[4]; - uint32_t OldButtonState[4]; - uint16_t ButtonClickState[4]; - int16_t hatValue[4][4]; - uint16_t controllerStatus[4]; - bool buttonStateChanged[4]; // True if a button has changed - - bool L2Clicked[4]; // These buttons are analog, so we use we use these bools to check if they where clicked or not - bool R2Clicked[4]; + /** @name Xbox Controller functions */ + /** + * Return the analog value from the joysticks on the controller. + * @param controller The controller to read from. + * @param a Either ::LeftHatX, ::LeftHatY, ::RightHatX or ::RightHatY. + * @return Returns a signed 16-bit integer. + */ + int16_t getAnalogHat(uint8_t controller, AnalogHat a); - unsigned long timer; // Timing for checkStatus() signals - - uint8_t readBuf[EP_MAXPKTSIZE]; // General purpose buffer for input data - uint8_t writeBuf[EP_MAXPKTSIZE]; // General purpose buffer for output data - - void readReport(uint8_t controller); // read incoming data - void printReport(uint8_t controller, uint8_t nBytes); // print incoming date - Uncomment for debugging + /** + * Turn rumble off and all the LEDs on the specific controller. + * @param controller The controller to write to. + */ + void setAllOff(uint8_t controller) { + setRumbleOn(controller, 0, 0); + setLedOff(controller); + }; - /* Private commands */ - void XboxCommand(uint8_t controller, uint8_t* data, uint16_t nbytes); - void checkStatus(); + /** + * Turn rumble off the specific controller. + * @param controller The controller to write to. + */ + void setRumbleOff(uint8_t controller) { + setRumbleOn(controller, 0, 0); + }; + /** + * Turn rumble on. + * @param controller The controller to write to. + * @param lValue Left motor (big weight) inside the controller. + * @param rValue Right motor (small weight) inside the controller. + */ + void setRumbleOn(uint8_t controller, uint8_t lValue, uint8_t rValue); + /** + * Set LED value. Without using the ::LED or ::LEDMode enum. + * @param controller The controller to write to. + * @param value See: + * setLedOff(uint8_t controller), setLedOn(uint8_t controller, LED l), + * setLedBlink(uint8_t controller, LED l), and setLedMode(uint8_t controller, LEDMode lm). + */ + void setLedRaw(uint8_t controller, uint8_t value); + + /** + * Turn all LEDs off the specific controller. + * @param controller The controller to write to. + */ + void setLedOff(uint8_t controller) { + setLedRaw(controller, 0); + }; + /** + * Turn on a LED by using the ::LED enum. + * @param controller The controller to write to. + * @param l ::LED1, ::LED2, ::LED3 and ::LED4 is supported by the Xbox controller. + */ + void setLedOn(uint8_t controller, LED l); + /** + * Turn on a LED by using the ::LED enum. + * @param controller The controller to write to. + * @param l ::ALL, ::LED1, ::LED2, ::LED3 and ::LED4 is supported by the Xbox controller. + */ + void setLedBlink(uint8_t controller, LED l); + /** + * Used to set special LED modes supported by the Xbox controller. + * @param controller The controller to write to. + * @param lm See ::LEDMode. + */ + void setLedMode(uint8_t controller, LEDMode lm); + /** + * Used to get the battery level from the controller. + * @param controller The controller to read from. + * @return Returns the battery level in percentage in 33% steps. + */ + uint8_t getBatteryLevel(uint8_t controller); + /** + * Used to check if a button has changed. + * @param controller The controller to read from. + * @return True if a button has changed. + */ + bool buttonChanged(uint8_t controller); + /**@}*/ + + /** True if a wireless receiver is connected. */ + bool XboxReceiverConnected; + /** Variable used to indicate if the XBOX 360 controller is successfully connected. */ + uint8_t Xbox360Connected[4]; + +protected: + /** Pointer to USB class instance. */ + USB *pUsb; + /** Device address. */ + uint8_t bAddress; + /** Endpoint info structure. */ + EpInfo epInfo[XBOX_MAX_ENDPOINTS]; + +private: + bool bPollEnable; + + /* Variables to store the buttons */ + uint32_t ButtonState[4]; + uint32_t OldButtonState[4]; + uint16_t ButtonClickState[4]; + int16_t hatValue[4][4]; + uint16_t controllerStatus[4]; + bool buttonStateChanged[4]; // True if a button has changed + + bool L2Clicked[4]; // These buttons are analog, so we use we use these bools to check if they where clicked or not + bool R2Clicked[4]; + + unsigned long timer; // Timing for checkStatus() signals + + uint8_t readBuf[EP_MAXPKTSIZE]; // General purpose buffer for input data + uint8_t writeBuf[EP_MAXPKTSIZE]; // General purpose buffer for output data + + void readReport(uint8_t controller); // read incoming data + void printReport(uint8_t controller, uint8_t nBytes); // print incoming date - Uncomment for debugging + + /* Private commands */ + void XboxCommand(uint8_t controller, uint8_t* data, uint16_t nbytes); + void checkStatus(); }; #endif \ No newline at end of file diff --git a/XBOXUSB.cpp b/XBOXUSB.cpp index 93047227..89fdffd2 100644 --- a/XBOXUSB.cpp +++ b/XBOXUSB.cpp @@ -20,323 +20,329 @@ //#define EXTRADEBUG // Uncomment to get even more debugging data //#define PRINTREPORT // Uncomment to print the report send by the Xbox 360 Controller -XBOXUSB::XBOXUSB(USB *p): +XBOXUSB::XBOXUSB(USB *p) : pUsb(p), // pointer to USB class instance - mandatory bAddress(0), // device address - mandatory bPollEnable(false) { // don't start polling before dongle is connected - for(uint8_t i=0; iRegisterDeviceClass(this); //set devConfig[] entry + if (pUsb) // register in USB subsystem + pUsb->RegisterDeviceClass(this); //set devConfig[] entry } uint8_t XBOXUSB::Init(uint8_t parent, uint8_t port, bool lowspeed) { - uint8_t buf[sizeof(USB_DEVICE_DESCRIPTOR)]; - uint8_t rcode; - UsbDevice *p = NULL; - EpInfo *oldep_ptr = NULL; - uint16_t PID; - uint16_t VID; + uint8_t buf[sizeof (USB_DEVICE_DESCRIPTOR)]; + uint8_t rcode; + UsbDevice *p = NULL; + EpInfo *oldep_ptr = NULL; + uint16_t PID; + uint16_t VID; - // get memory address of USB device address pool - AddressPool &addrPool = pUsb->GetAddressPool(); + // get memory address of USB device address pool + AddressPool &addrPool = pUsb->GetAddressPool(); #ifdef EXTRADEBUG - Notify(PSTR("\r\nXBOXUSB Init"), 0x80); + Notify(PSTR("\r\nXBOXUSB Init"), 0x80); #endif - // check if address has already been assigned to an instance - if (bAddress) { + // check if address has already been assigned to an instance + if (bAddress) { #ifdef DEBUG - Notify(PSTR("\r\nAddress in use"), 0x80); + Notify(PSTR("\r\nAddress in use"), 0x80); #endif - return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE; - } + return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE; + } - // Get pointer to pseudo device with address 0 assigned - p = addrPool.GetUsbDevicePtr(0); + // Get pointer to pseudo device with address 0 assigned + p = addrPool.GetUsbDevicePtr(0); - if (!p) { + if (!p) { #ifdef DEBUG - Notify(PSTR("\r\nAddress not found"), 0x80); + Notify(PSTR("\r\nAddress not found"), 0x80); #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 - Notify(PSTR("\r\nepinfo is null"), 0x80); + Notify(PSTR("\r\nepinfo is null"), 0x80); #endif - return USB_ERROR_EPINFO_IS_NULL; - } + return USB_ERROR_EPINFO_IS_NULL; + } - // Save old pointer to EP_RECORD of address 0 - oldep_ptr = p->epinfo; + // Save old pointer to EP_RECORD of address 0 + oldep_ptr = p->epinfo; - // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence - p->epinfo = epInfo; + // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence + p->epinfo = epInfo; - p->lowspeed = lowspeed; + p->lowspeed = lowspeed; - // Get device descriptor - rcode = pUsb->getDevDescr(0, 0, sizeof(USB_DEVICE_DESCRIPTOR), (uint8_t*)buf);// Get device descriptor - addr, ep, nbytes, data - // Restore p->epinfo - p->epinfo = oldep_ptr; + // Get device descriptor + rcode = pUsb->getDevDescr(0, 0, sizeof (USB_DEVICE_DESCRIPTOR), (uint8_t*)buf); // Get device descriptor - addr, ep, nbytes, data + // Restore p->epinfo + p->epinfo = oldep_ptr; - if(rcode) - goto FailGetDevDescr; + if (rcode) + goto FailGetDevDescr; - VID = ((USB_DEVICE_DESCRIPTOR*)buf)->idVendor; - PID = ((USB_DEVICE_DESCRIPTOR*)buf)->idProduct; + VID = ((USB_DEVICE_DESCRIPTOR*)buf)->idVendor; + PID = ((USB_DEVICE_DESCRIPTOR*)buf)->idProduct; - if(VID != XBOX_VID && VID != MADCATZ_VID && VID != JOYTECH_VID) // We just check if it's a xbox controller using the Vendor ID - goto FailUnknownDevice; - if(PID == XBOX_WIRELESS_PID) { + if (VID != XBOX_VID && VID != MADCATZ_VID && VID != JOYTECH_VID) // We just check if it's a xbox controller using the Vendor ID + goto FailUnknownDevice; + if (PID == XBOX_WIRELESS_PID) { #ifdef DEBUG - Notify(PSTR("\r\nYou have plugged in a wireless Xbox 360 controller - it doesn't support USB communication"), 0x80); + Notify(PSTR("\r\nYou have plugged in a wireless Xbox 360 controller - it doesn't support USB communication"), 0x80); #endif - goto FailUnknownDevice; - } - else if(PID == XBOX_WIRELESS_RECEIVER_PID || PID == XBOX_WIRELESS_RECEIVER_THIRD_PARTY_PID) { + goto FailUnknownDevice; + } else if (PID == XBOX_WIRELESS_RECEIVER_PID || PID == XBOX_WIRELESS_RECEIVER_THIRD_PARTY_PID) { #ifdef DEBUG - Notify(PSTR("\r\nThis library only supports Xbox 360 controllers via USB"), 0x80); + Notify(PSTR("\r\nThis library only supports Xbox 360 controllers via USB"), 0x80); #endif - goto FailUnknownDevice; - } + goto FailUnknownDevice; + } - // Allocate new address according to device class - bAddress = addrPool.AllocAddress(parent, false, port); + // Allocate new address according to device class + bAddress = addrPool.AllocAddress(parent, false, port); - if (!bAddress) - return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; + if (!bAddress) + return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; - // Extract Max Packet Size from device descriptor - epInfo[0].maxPktSize = (uint8_t)((USB_DEVICE_DESCRIPTOR*)buf)->bMaxPacketSize0; + // Extract Max Packet Size from device descriptor + epInfo[0].maxPktSize = (uint8_t)((USB_DEVICE_DESCRIPTOR*)buf)->bMaxPacketSize0; - // Assign new address to the device - rcode = pUsb->setAddr( 0, 0, bAddress ); - if (rcode) { + // Assign new address to the device + rcode = pUsb->setAddr(0, 0, bAddress); + if (rcode) { + p->lowspeed = false; + addrPool.FreeAddress(bAddress); + bAddress = 0; +#ifdef DEBUG + Notify(PSTR("\r\nsetAddr: "), 0x80); +#endif + PrintHex (rcode, 0x80); + return rcode; + } +#ifdef EXTRADEBUG + Notify(PSTR("\r\nAddr: "), 0x80); + PrintHex (bAddress, 0x80); +#endif p->lowspeed = false; - addrPool.FreeAddress(bAddress); - bAddress = 0; -#ifdef DEBUG - Notify(PSTR("\r\nsetAddr: "), 0x80); -#endif - PrintHex(rcode, 0x80); - return rcode; - } -#ifdef EXTRADEBUG - Notify(PSTR("\r\nAddr: "), 0x80); - PrintHex(bAddress, 0x80); -#endif - p->lowspeed = false; - //get pointer to assigned address record - p = addrPool.GetUsbDevicePtr(bAddress); - if (!p) - return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; + //get pointer to assigned address record + p = addrPool.GetUsbDevicePtr(bAddress); + if (!p) + return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; - p->lowspeed = lowspeed; + p->lowspeed = lowspeed; - // Assign epInfo to epinfo pointer - only EP0 is known - rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); - if (rcode) - goto FailSetDevTblEntry; + // Assign epInfo to epinfo pointer - only EP0 is known + rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); + if (rcode) + goto FailSetDevTblEntry; - /* The application will work in reduced host mode, so we can save program and data - memory space. After verifying the VID we will use known values for the - configuration values for device, interface, endpoints and HID for the XBOX360 Controllers */ + /* The application will work in reduced host mode, so we can save program and data + memory space. After verifying the VID we will use known values for the + configuration values for device, interface, endpoints and HID for the XBOX360 Controllers */ - /* Initialize data structures for endpoints of device */ - epInfo[ XBOX_INPUT_PIPE ].epAddr = 0x01; // XBOX 360 report endpoint - epInfo[ XBOX_INPUT_PIPE ].epAttribs = EP_INTERRUPT; - epInfo[ XBOX_INPUT_PIPE ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints - epInfo[ XBOX_INPUT_PIPE ].maxPktSize = EP_MAXPKTSIZE; - epInfo[ XBOX_INPUT_PIPE ].bmSndToggle = bmSNDTOG0; - epInfo[ XBOX_INPUT_PIPE ].bmRcvToggle = bmRCVTOG0; - epInfo[ XBOX_OUTPUT_PIPE ].epAddr = 0x02; // XBOX 360 output endpoint - epInfo[ XBOX_OUTPUT_PIPE ].epAttribs = EP_INTERRUPT; - epInfo[ XBOX_OUTPUT_PIPE ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints - epInfo[ XBOX_OUTPUT_PIPE ].maxPktSize = EP_MAXPKTSIZE; - epInfo[ XBOX_OUTPUT_PIPE ].bmSndToggle = bmSNDTOG0; - epInfo[ XBOX_OUTPUT_PIPE ].bmRcvToggle = bmRCVTOG0; + /* Initialize data structures for endpoints of device */ + epInfo[ XBOX_INPUT_PIPE ].epAddr = 0x01; // XBOX 360 report endpoint + epInfo[ XBOX_INPUT_PIPE ].epAttribs = EP_INTERRUPT; + epInfo[ XBOX_INPUT_PIPE ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints + epInfo[ XBOX_INPUT_PIPE ].maxPktSize = EP_MAXPKTSIZE; + epInfo[ XBOX_INPUT_PIPE ].bmSndToggle = bmSNDTOG0; + epInfo[ XBOX_INPUT_PIPE ].bmRcvToggle = bmRCVTOG0; + epInfo[ XBOX_OUTPUT_PIPE ].epAddr = 0x02; // XBOX 360 output endpoint + epInfo[ XBOX_OUTPUT_PIPE ].epAttribs = EP_INTERRUPT; + epInfo[ XBOX_OUTPUT_PIPE ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints + epInfo[ XBOX_OUTPUT_PIPE ].maxPktSize = EP_MAXPKTSIZE; + epInfo[ XBOX_OUTPUT_PIPE ].bmSndToggle = bmSNDTOG0; + epInfo[ XBOX_OUTPUT_PIPE ].bmRcvToggle = bmRCVTOG0; - rcode = pUsb->setEpInfoEntry(bAddress, 3, epInfo); - if( rcode ) - goto FailSetDevTblEntry; + rcode = pUsb->setEpInfoEntry(bAddress, 3, epInfo); + if (rcode) + goto FailSetDevTblEntry; - delay(200);//Give time for address change + delay(200); //Give time for address change - rcode = pUsb->setConf(bAddress, epInfo[ XBOX_CONTROL_PIPE ].epAddr, 1); - if( rcode ) - goto FailSetConf; + rcode = pUsb->setConf(bAddress, epInfo[ XBOX_CONTROL_PIPE ].epAddr, 1); + if (rcode) + goto FailSetConf; #ifdef DEBUG - Notify(PSTR("\r\nXbox 360 Controller Connected\r\n"), 0x80); + Notify(PSTR("\r\nXbox 360 Controller Connected\r\n"), 0x80); #endif - setLedOn(LED1); - Xbox360Connected = true; - bPollEnable = true; - return 0; // successful configuration + setLedOn(LED1); + Xbox360Connected = true; + bPollEnable = true; + return 0; // successful configuration - /* diagnostic messages */ + /* diagnostic messages */ FailGetDevDescr: #ifdef DEBUG - Notify(PSTR("\r\ngetDevDescr:"), 0x80); + Notify(PSTR("\r\ngetDevDescr:"), 0x80); #endif - goto Fail; + goto Fail; FailSetDevTblEntry: #ifdef DEBUG - Notify(PSTR("\r\nsetDevTblEn:"), 0x80); + Notify(PSTR("\r\nsetDevTblEn:"), 0x80); #endif - goto Fail; + goto Fail; FailSetConf: #ifdef DEBUG - Notify(PSTR("\r\nsetConf:"), 0x80); + Notify(PSTR("\r\nsetConf:"), 0x80); #endif - goto Fail; + goto Fail; FailUnknownDevice: #ifdef DEBUG - Notify(PSTR("\r\nUnknown Device Connected - VID: "), 0x80); - PrintHex(VID, 0x80); - Notify(PSTR(" PID: "), 0x80); - PrintHex(PID, 0x80); + Notify(PSTR("\r\nUnknown Device Connected - VID: "), 0x80); + PrintHex (VID, 0x80); + Notify(PSTR(" PID: "), 0x80); + PrintHex (PID, 0x80); #endif - rcode = USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; - goto Fail; + rcode = USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; + goto Fail; Fail: #ifdef DEBUG - Notify(PSTR("\r\nXbox 360 Init Failed, error code: "), 0x80); - Serial.print(rcode,HEX); + Notify(PSTR("\r\nXbox 360 Init Failed, error code: "), 0x80); + Serial.print(rcode, HEX); #endif - Release(); - return rcode; + Release(); + return rcode; } /* Performs a cleanup after failed Init() attempt */ uint8_t XBOXUSB::Release() { - Xbox360Connected = false; - pUsb->GetAddressPool().FreeAddress(bAddress); - bAddress = 0; - bPollEnable = false; - return 0; + Xbox360Connected = false; + pUsb->GetAddressPool().FreeAddress(bAddress); + bAddress = 0; + bPollEnable = false; + return 0; } + uint8_t XBOXUSB::Poll() { - if (!bPollEnable) - return 0; - uint16_t BUFFER_SIZE = EP_MAXPKTSIZE; - pUsb->inTransfer(bAddress, epInfo[ XBOX_INPUT_PIPE ].epAddr, &BUFFER_SIZE, readBuf); // input on endpoint 1 - readReport(); + if (!bPollEnable) + return 0; + uint16_t BUFFER_SIZE = EP_MAXPKTSIZE; + pUsb->inTransfer(bAddress, epInfo[ XBOX_INPUT_PIPE ].epAddr, &BUFFER_SIZE, readBuf); // input on endpoint 1 + readReport(); #ifdef PRINTREPORT - printReport(); // Uncomment "#define PRINTREPORT" to print the report send by the Xbox 360 Controller + printReport(); // Uncomment "#define PRINTREPORT" to print the report send by the Xbox 360 Controller #endif - return 0; + return 0; } void XBOXUSB::readReport() { - if (readBuf == NULL) - return; - if(readBuf[0] != 0x00 || readBuf[1] != 0x14) { // Check if it's the correct report - the controller also sends different status reports - return; - } + if (readBuf == NULL) + return; + if (readBuf[0] != 0x00 || readBuf[1] != 0x14) { // Check if it's the correct report - the controller also sends different status reports + return; + } - ButtonState = (uint32_t)(readBuf[5] | ((uint16_t)readBuf[4] << 8) | ((uint32_t)readBuf[3] << 16) | ((uint32_t)readBuf[2] << 24)); + ButtonState = (uint32_t)(readBuf[5] | ((uint16_t)readBuf[4] << 8) | ((uint32_t)readBuf[3] << 16) | ((uint32_t)readBuf[2] << 24)); - hatValue[LeftHatX] = (int16_t)(((uint16_t)readBuf[7] << 8) | readBuf[6]); - hatValue[LeftHatY] = (int16_t)(((uint16_t)readBuf[9] << 8) | readBuf[8]); - hatValue[RightHatX] = (int16_t)(((uint16_t)readBuf[11] << 8) | readBuf[10]); - hatValue[RightHatY] = (int16_t)(((uint16_t)readBuf[13] << 8) | readBuf[12]); + hatValue[LeftHatX] = (int16_t)(((uint16_t)readBuf[7] << 8) | readBuf[6]); + hatValue[LeftHatY] = (int16_t)(((uint16_t)readBuf[9] << 8) | readBuf[8]); + hatValue[RightHatX] = (int16_t)(((uint16_t)readBuf[11] << 8) | readBuf[10]); + hatValue[RightHatY] = (int16_t)(((uint16_t)readBuf[13] << 8) | readBuf[12]); - //Notify(PSTR("\r\nButtonState"), 0x80); - //PrintHex(ButtonState, 0x80); + //Notify(PSTR("\r\nButtonState"), 0x80); + //PrintHex(ButtonState, 0x80); - if(ButtonState != OldButtonState) { - ButtonClickState = (ButtonState >> 16) & ((~OldButtonState) >> 16); // Update click state variable, but don't include the two trigger buttons L2 and R2 - if(((uint8_t)OldButtonState) == 0 && ((uint8_t)ButtonState) != 0) // The L2 and R2 buttons are special as they are analog buttons - R2Clicked = true; - if((uint8_t)(OldButtonState >> 8) == 0 && (uint8_t)(ButtonState >> 8) != 0) - L2Clicked = true; - OldButtonState = ButtonState; - } + if (ButtonState != OldButtonState) { + ButtonClickState = (ButtonState >> 16) & ((~OldButtonState) >> 16); // Update click state variable, but don't include the two trigger buttons L2 and R2 + if (((uint8_t)OldButtonState) == 0 && ((uint8_t)ButtonState) != 0) // The L2 and R2 buttons are special as they are analog buttons + R2Clicked = true; + if ((uint8_t)(OldButtonState >> 8) == 0 && (uint8_t)(ButtonState >> 8) != 0) + L2Clicked = true; + OldButtonState = ButtonState; + } } void XBOXUSB::printReport() { //Uncomment "#define PRINTREPORT" to print the report send by the Xbox 360 Controller #ifdef PRINTREPORT - if (readBuf == NULL) - return; - for(uint8_t i = 0; i < XBOX_REPORT_BUFFER_SIZE;i++) { - PrintHex(readBuf[i], 0x80); - Serial.print(" "); - } - Serial.println(); + if (readBuf == NULL) + return; + for (uint8_t i = 0; i < XBOX_REPORT_BUFFER_SIZE; i++) { + PrintHex (readBuf[i], 0x80); + Serial.print(" "); + } + Serial.println(); #endif } uint8_t XBOXUSB::getButtonPress(Button b) { - if(b == L2) // These are analog buttons - return (uint8_t)(ButtonState >> 8); - else if(b == R2) - return (uint8_t)ButtonState; - return (ButtonState & ((uint32_t)pgm_read_word(&XBOXBUTTONS[(uint8_t)b]) << 16)); + if (b == L2) // These are analog buttons + return (uint8_t)(ButtonState >> 8); + else if (b == R2) + return (uint8_t)ButtonState; + return (ButtonState & ((uint32_t)pgm_read_word(&XBOXBUTTONS[(uint8_t)b]) << 16)); } + bool XBOXUSB::getButtonClick(Button b) { - if(b == L2) { - if(L2Clicked) { - L2Clicked = false; - return true; + if (b == L2) { + if (L2Clicked) { + L2Clicked = false; + return true; + } + return false; + } else if (b == R2) { + if (R2Clicked) { + R2Clicked = false; + return true; + } + return false; } - return false; - } - else if(b == R2) { - if(R2Clicked) { - R2Clicked = false; - return true; - } - return false; - } - uint16_t button = pgm_read_word(&XBOXBUTTONS[(uint8_t)b]); - bool click = (ButtonClickState & button); - ButtonClickState &= ~button; // clear "click" event - return click; + uint16_t button = pgm_read_word(&XBOXBUTTONS[(uint8_t)b]); + bool click = (ButtonClickState & button); + ButtonClickState &= ~button; // clear "click" event + return click; } + int16_t XBOXUSB::getAnalogHat(AnalogHat a) { - return hatValue[a]; + return hatValue[a]; } /* Xbox Controller commands */ void XBOXUSB::XboxCommand(uint8_t* data, uint16_t nbytes) { - //bmRequest = Host to device (0x00) | Class (0x20) | Interface (0x01) = 0x21, bRequest = Set Report (0x09), Report ID (0x00), Report Type (Output 0x02), interface (0x00), datalength, datalength, data) - pUsb->ctrlReq(bAddress,epInfo[XBOX_CONTROL_PIPE].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0x00, 0x02, 0x00, nbytes, nbytes, data, NULL); + //bmRequest = Host to device (0x00) | Class (0x20) | Interface (0x01) = 0x21, bRequest = Set Report (0x09), Report ID (0x00), Report Type (Output 0x02), interface (0x00), datalength, datalength, data) + pUsb->ctrlReq(bAddress, epInfo[XBOX_CONTROL_PIPE].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0x00, 0x02, 0x00, nbytes, nbytes, data, NULL); } + void XBOXUSB::setLedRaw(uint8_t value) { - writeBuf[0] = 0x01; - writeBuf[1] = 0x03; - writeBuf[2] = value; + writeBuf[0] = 0x01; + writeBuf[1] = 0x03; + writeBuf[2] = value; - XboxCommand(writeBuf, 3); + XboxCommand(writeBuf, 3); } + void XBOXUSB::setLedOn(LED led) { - if(led != ALL) // All LEDs can't be on a the same time - setLedRaw((pgm_read_byte(&XBOXLEDS[(uint8_t)led]))+4); + if (led != ALL) // All LEDs can't be on a the same time + setLedRaw((pgm_read_byte(&XBOXLEDS[(uint8_t)led])) + 4); } -void XBOXUSB::setLedBlink(LED led) { - setLedRaw(pgm_read_byte(&XBOXLEDS[(uint8_t)led])); -} -void XBOXUSB::setLedMode(LEDMode ledMode) { // This function is used to do some speciel LED stuff the controller supports - setLedRaw((uint8_t)ledMode); -} -void XBOXUSB::setRumbleOn(uint8_t lValue, uint8_t rValue) { - writeBuf[0] = 0x00; - writeBuf[1] = 0x08; - writeBuf[2] = 0x00; - writeBuf[3] = lValue; // big weight - writeBuf[4] = rValue; // small weight - writeBuf[5] = 0x00; - writeBuf[6] = 0x00; - writeBuf[7] = 0x00; - XboxCommand(writeBuf, 8); +void XBOXUSB::setLedBlink(LED led) { + setLedRaw(pgm_read_byte(&XBOXLEDS[(uint8_t)led])); +} + +void XBOXUSB::setLedMode(LEDMode ledMode) { // This function is used to do some speciel LED stuff the controller supports + setLedRaw((uint8_t)ledMode); +} + +void XBOXUSB::setRumbleOn(uint8_t lValue, uint8_t rValue) { + writeBuf[0] = 0x00; + writeBuf[1] = 0x08; + writeBuf[2] = 0x00; + writeBuf[3] = lValue; // big weight + writeBuf[4] = rValue; // small weight + writeBuf[5] = 0x00; + writeBuf[6] = 0x00; + writeBuf[7] = 0x00; + + XboxCommand(writeBuf, 8); } diff --git a/XBOXUSB.h b/XBOXUSB.h index ada5a48a..5f0621d3 100644 --- a/XBOXUSB.h +++ b/XBOXUSB.h @@ -1,15 +1,15 @@ /* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved. - + This software may be distributed and modified under the terms of the GNU General Public License version 2 (GPL2) as published by the Free Software Foundation and appearing in the file GPL2.TXT included in the packaging of this file. Please note that GPL2 Section 2[b] requires that all works based on this software must also be made publicly available under the terms of the GPL2 ("Copyleft"). - + Contact information ------------------- - + Kristian Lauszus, TKJ Electronics Web : http://www.tkjelectronics.com e-mail : kristianl@tkjelectronics.com @@ -25,7 +25,7 @@ #endif #include "Usb.h" -#include "xboxEnums.h" +#include "xboxEnums.h" /* Data Xbox 360 taken from descriptors */ #define EP_MAXPKTSIZE 32 // max size for data via USB @@ -58,135 +58,150 @@ /** This class implements support for a Xbox wired controller via USB. */ class XBOXUSB : public USBDeviceConfig { public: - /** - * Constructor for the XBOXUSB class. - * @param pUsb Pointer to USB class instance. - */ - XBOXUSB(USB *pUsb); - - /** @name USBDeviceConfig implementation */ - /** - * Initialize the Xbox Controller. - * @param parent Hub number. - * @param port Port number on the hub. - * @param lowspeed Speed of the device. - * @return 0 on success. - */ - virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed); - /** - * Release the USB device. - * @return 0 on success. - */ - virtual uint8_t Release(); - /** - * Poll the USB Input endpoins and run the state machines. - * @return 0 on success. - */ - virtual uint8_t Poll(); - /** - * Get the device address. - * @return The device address. - */ - virtual uint8_t GetAddress() { return bAddress; }; - /** - * Used to check if the controller has been initialized. - * @return True if it's ready. - */ - virtual bool isReady() { return bPollEnable; }; - /**@}*/ - - /** @name Xbox Controller functions */ - /** - * getButtonPress(Button b) will return true as long as the button is held down. - * - * While getButtonClick(Button b) will only return it once. - * - * So you instance if you need to increase a variable once you would use getButtonClick(Button b), - * but if you need to drive a robot forward you would use getButtonPress(Button b). - * @param b ::Button to read. - * @return getButtonClick(Button b) will return a bool, but getButtonPress(Button b) - * will return a byte if reading ::L2 or ::R2. - */ - uint8_t getButtonPress(Button b); - bool getButtonClick(Button b); - /**@}*/ + /** + * Constructor for the XBOXUSB class. + * @param pUsb Pointer to USB class instance. + */ + XBOXUSB(USB *pUsb); - /** @name Xbox Controller functions */ - /** - * Return the analog value from the joysticks on the controller. - * @param a Either ::LeftHatX, ::LeftHatY, ::RightHatX or ::RightHatY. - * @return Returns a signed 16-bit integer. - */ - int16_t getAnalogHat(AnalogHat a); - - /** Turn rumble off and all the LEDs on the controller. */ - void setAllOff() { setRumbleOn(0,0); setLedRaw(0); }; - /** Turn rumble off the controller. */ - void setRumbleOff() { setRumbleOn(0,0); }; - /** - * Turn rumble on. - * @param lValue Left motor (big weight) inside the controller. - * @param rValue Right motor (small weight) inside the controller. - */ - void setRumbleOn(uint8_t lValue, uint8_t rValue); - /** - * Set LED value. Without using the ::LED or ::LEDMode enum. - * @param value See: - * setLedOff(), setLedOn(LED l), - * setLedBlink(LED l), and setLedMode(LEDMode lm). - */ - void setLedRaw(uint8_t value); - /** Turn all LEDs off the controller. */ - void setLedOff() { setLedRaw(0); }; - /** - * Turn on a LED by using the ::LED enum. - * @param l ::LED1, ::LED2, ::LED3 and ::LED4 is supported by the Xbox controller. - */ - void setLedOn(LED l); - /** - * Turn on a LED by using the ::LED enum. - * @param l ::ALL, ::LED1, ::LED2, ::LED3 and ::LED4 is supported by the Xbox controller. - */ - void setLedBlink(LED l); - /** - * Used to set special LED modes supported by the Xbox controller. - * @param controller The controller to write to. - * @param lm See ::LEDMode. - */ - void setLedMode(LEDMode lm); - /**@}*/ - - /** True if a Xbox 360 controller is connected. */ - bool Xbox360Connected; - -protected: - /** Pointer to USB class instance. */ - USB *pUsb; - /** Device address. */ - uint8_t bAddress; - /** Endpoint info structure. */ - EpInfo epInfo[XBOX_MAX_ENDPOINTS]; - -private: - bool bPollEnable; + /** @name USBDeviceConfig implementation */ + /** + * Initialize the Xbox Controller. + * @param parent Hub number. + * @param port Port number on the hub. + * @param lowspeed Speed of the device. + * @return 0 on success. + */ + virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed); + /** + * Release the USB device. + * @return 0 on success. + */ + virtual uint8_t Release(); + /** + * Poll the USB Input endpoins and run the state machines. + * @return 0 on success. + */ + virtual uint8_t Poll(); - /* Variables to store the buttons */ - uint32_t ButtonState; - uint32_t OldButtonState; - uint16_t ButtonClickState; - int16_t hatValue[4]; - uint16_t controllerStatus; - - bool L2Clicked; // These buttons are analog, so we use we use these bools to check if they where clicked or not - bool R2Clicked; - - uint8_t readBuf[EP_MAXPKTSIZE]; // General purpose buffer for input data - uint8_t writeBuf[EP_MAXPKTSIZE]; // General purpose buffer for output data - - void readReport(); // read incoming data - void printReport(); // print incoming date - Uncomment for debugging - - /* Private commands */ - void XboxCommand(uint8_t* data, uint16_t nbytes); + /** + * Get the device address. + * @return The device address. + */ + virtual uint8_t GetAddress() { + return bAddress; + }; + + /** + * Used to check if the controller has been initialized. + * @return True if it's ready. + */ + virtual bool isReady() { + return bPollEnable; + }; + /**@}*/ + + /** @name Xbox Controller functions */ + /** + * getButtonPress(Button b) will return true as long as the button is held down. + * + * While getButtonClick(Button b) will only return it once. + * + * So you instance if you need to increase a variable once you would use getButtonClick(Button b), + * but if you need to drive a robot forward you would use getButtonPress(Button b). + * @param b ::Button to read. + * @return getButtonClick(Button b) will return a bool, but getButtonPress(Button b) + * will return a byte if reading ::L2 or ::R2. + */ + uint8_t getButtonPress(Button b); + bool getButtonClick(Button b); + /**@}*/ + + /** @name Xbox Controller functions */ + /** + * Return the analog value from the joysticks on the controller. + * @param a Either ::LeftHatX, ::LeftHatY, ::RightHatX or ::RightHatY. + * @return Returns a signed 16-bit integer. + */ + int16_t getAnalogHat(AnalogHat a); + + /** Turn rumble off and all the LEDs on the controller. */ + void setAllOff() { + setRumbleOn(0, 0); + setLedRaw(0); + }; + + /** Turn rumble off the controller. */ + void setRumbleOff() { + setRumbleOn(0, 0); + }; + /** + * Turn rumble on. + * @param lValue Left motor (big weight) inside the controller. + * @param rValue Right motor (small weight) inside the controller. + */ + void setRumbleOn(uint8_t lValue, uint8_t rValue); + /** + * Set LED value. Without using the ::LED or ::LEDMode enum. + * @param value See: + * setLedOff(), setLedOn(LED l), + * setLedBlink(LED l), and setLedMode(LEDMode lm). + */ + void setLedRaw(uint8_t value); + + /** Turn all LEDs off the controller. */ + void setLedOff() { + setLedRaw(0); + }; + /** + * Turn on a LED by using the ::LED enum. + * @param l ::LED1, ::LED2, ::LED3 and ::LED4 is supported by the Xbox controller. + */ + void setLedOn(LED l); + /** + * Turn on a LED by using the ::LED enum. + * @param l ::ALL, ::LED1, ::LED2, ::LED3 and ::LED4 is supported by the Xbox controller. + */ + void setLedBlink(LED l); + /** + * Used to set special LED modes supported by the Xbox controller. + * @param controller The controller to write to. + * @param lm See ::LEDMode. + */ + void setLedMode(LEDMode lm); + /**@}*/ + + /** True if a Xbox 360 controller is connected. */ + bool Xbox360Connected; + +protected: + /** Pointer to USB class instance. */ + USB *pUsb; + /** Device address. */ + uint8_t bAddress; + /** Endpoint info structure. */ + EpInfo epInfo[XBOX_MAX_ENDPOINTS]; + +private: + bool bPollEnable; + + /* Variables to store the buttons */ + uint32_t ButtonState; + uint32_t OldButtonState; + uint16_t ButtonClickState; + int16_t hatValue[4]; + uint16_t controllerStatus; + + bool L2Clicked; // These buttons are analog, so we use we use these bools to check if they where clicked or not + bool R2Clicked; + + uint8_t readBuf[EP_MAXPKTSIZE]; // General purpose buffer for input data + uint8_t writeBuf[EP_MAXPKTSIZE]; // General purpose buffer for output data + + void readReport(); // read incoming data + void printReport(); // print incoming date - Uncomment for debugging + + /* Private commands */ + void XboxCommand(uint8_t* data, uint16_t nbytes); }; #endif diff --git a/address.h b/address.h index 2b9de918..b035aac6 100644 --- a/address.h +++ b/address.h @@ -40,9 +40,9 @@ struct EpInfo { uint8_t bmSndToggle : 1; // Send toggle, when zero bmSNDTOG0, bmSNDTOG1 otherwise uint8_t bmRcvToggle : 1; // Send toggle, when zero bmRCVTOG0, bmRCVTOG1 otherwise uint8_t bmNakPower : 6; // Binary order for NAK_LIMIT value - }__attribute__((packed)); + } __attribute__((packed)); }; -}__attribute__((packed)); +} __attribute__((packed)); // 7 6 5 4 3 2 1 0 // --------------------------------- @@ -63,10 +63,10 @@ struct UsbDeviceAddress { uint8_t bmParent : 3; // parent hub address uint8_t bmHub : 1; // hub flag uint8_t bmReserved : 1; // reserved, must be zerro - }__attribute__((packed)); + } __attribute__((packed)); uint8_t devAddress; }; -}__attribute__((packed)); +} __attribute__((packed)); #define bmUSB_DEV_ADDR_ADDRESS 0x07 #define bmUSB_DEV_ADDR_PARENT 0x38 @@ -78,7 +78,7 @@ struct UsbDevice { uint8_t epcount; // number of endpoints bool lowspeed; // indicates if a device is the low speed one // uint8_t devclass; // device class -}__attribute__((packed)); +} __attribute__((packed)); class AddressPool { public: @@ -112,8 +112,8 @@ class AddressPoolImpl : public AddressPool { // Returns thePool index for a given address uint8_t FindAddressIndex(uint8_t address = 0) { - for (uint8_t i = 1; i < MAX_DEVICES_ALLOWED; i++) { - if (thePool[i].address == address) + for(uint8_t i = 1; i < MAX_DEVICES_ALLOWED; i++) { + if(thePool[i].address == address) return i; } return 0; @@ -121,8 +121,8 @@ class AddressPoolImpl : public AddressPool { // Returns thePool child index for a given parent 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++) { - if (((UsbDeviceAddress*) & thePool[i].address)->bmParent == addr.bmAddress) + 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) return i; } return 0; @@ -131,16 +131,16 @@ class AddressPoolImpl : public AddressPool { void FreeAddressByIndex(uint8_t index) { // Zerro field is reserved and should not be affected - if (index == 0) + if(index == 0) return; // If a hub was switched off all port addresses should be freed - if (((UsbDeviceAddress*) & thePool[index].address)->bmHub == 1) { - for (uint8_t i = 1; (i = FindChildIndex(*((UsbDeviceAddress*) & thePool[index].address), i));) + if(((UsbDeviceAddress*) & thePool[index].address)->bmHub == 1) { + for(uint8_t i = 1; (i = FindChildIndex(*((UsbDeviceAddress*) & thePool[index].address), i));) FreeAddressByIndex(i); // If the hub had the last allocated address, hubCounter should be decremented - if (hubCounter == ((UsbDeviceAddress*) & thePool[index].address)->bmAddress) + if(hubCounter == ((UsbDeviceAddress*) & thePool[index].address)->bmAddress) hubCounter--; } InitEntry(index); @@ -148,7 +148,7 @@ class AddressPoolImpl : public AddressPool { // Initializes the whole address pool at once void InitAllAddresses() { - for (uint8_t i = 1; i < MAX_DEVICES_ALLOWED; i++) + for(uint8_t i = 1; i < MAX_DEVICES_ALLOWED; i++) InitEntry(i); hubCounter = 0; @@ -172,22 +172,22 @@ public: // Returns a pointer to a specified address entry virtual UsbDevice* GetUsbDevicePtr(uint8_t addr) { - if (!addr) + if(!addr) return thePool; uint8_t index = FindAddressIndex(addr); - return (!index) ? NULL : thePool + index; + return(!index) ? NULL : thePool + index; }; // Performs an operation specified by pfunc for each addressed device void ForEachUsbDevice(UsbDeviceHandleFunc pfunc) { - if (!pfunc) + if(!pfunc) return; - for (uint8_t i = 1; i < MAX_DEVICES_ALLOWED; i++) - if (thePool[i].address) + for(uint8_t i = 1; i < MAX_DEVICES_ALLOWED; i++) + if(thePool[i].address) pfunc(thePool + i); }; // Allocates new address @@ -196,20 +196,20 @@ public: /* if (parent != 0 && port == 0) Serial.println("PRT:0"); */ - if (parent > 127 || port > 7) + if(parent > 127 || port > 7) return 0; - if (is_hub && hubCounter == 7) + if(is_hub && hubCounter == 7) return 0; // finds first empty address entry starting from one uint8_t index = FindAddressIndex(0); - if (!index) // if empty entry is not found + if(!index) // if empty entry is not found return 0; - if (parent == 0) { - if (is_hub) { + if(parent == 0) { + if(is_hub) { thePool[index].address = 0x41; hubCounter++; } else @@ -222,7 +222,7 @@ public: addr.bmParent = ((UsbDeviceAddress*) & parent)->bmAddress; - if (is_hub) { + if(is_hub) { addr.bmHub = 1; addr.bmAddress = ++hubCounter; } else { @@ -244,7 +244,7 @@ public: virtual void FreeAddress(uint8_t addr) { // if the root hub is disconnected all the addresses should be initialized - if (addr == 0x41) { + if(addr == 0x41) { InitAllAddresses(); return; } diff --git a/adk.cpp b/adk.cpp index 95bf7161..0ea19de0 100644 --- a/adk.cpp +++ b/adk.cpp @@ -41,8 +41,7 @@ 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) - { +ready(false) { // initialize endpoint data structures for (uint8_t i = 0; i < ADK_MAX_ENDPOINTS; i++) { epInfo[i].epAddr = 0; @@ -101,7 +100,7 @@ uint8_t ADK::Init(uint8_t parent, uint8_t port, bool lowspeed) { p->lowspeed = lowspeed; // Get device descriptor - rcode = pUsb->getDevDescr(0, 0, sizeof (USB_DEVICE_DESCRIPTOR), (uint8_t*) buf); + rcode = pUsb->getDevDescr(0, 0, sizeof (USB_DEVICE_DESCRIPTOR), (uint8_t*)buf); // Restore p->epinfo p->epinfo = oldep_ptr; @@ -114,7 +113,7 @@ uint8_t ADK::Init(uint8_t parent, uint8_t port, bool lowspeed) { bAddress = addrPool.AllocAddress(parent, false, port); // Extract Max Packet Size from device descriptor - epInfo[0].maxPktSize = (uint8_t) ((USB_DEVICE_DESCRIPTOR*) buf)->bMaxPacketSize0; + epInfo[0].maxPktSize = (uint8_t)((USB_DEVICE_DESCRIPTOR*)buf)->bMaxPacketSize0; // Assign new address to the device rcode = pUsb->setAddr(0, 0, bAddress); @@ -145,11 +144,11 @@ 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 - if (((USB_DEVICE_DESCRIPTOR*) buf)->idVendor == ADK_VID && - (((USB_DEVICE_DESCRIPTOR*) buf)->idProduct == ADK_PID || ((USB_DEVICE_DESCRIPTOR*) buf)->idProduct == ADB_PID)) { + if (((USB_DEVICE_DESCRIPTOR*)buf)->idVendor == ADK_VID && + (((USB_DEVICE_DESCRIPTOR*)buf)->idProduct == ADK_PID || ((USB_DEVICE_DESCRIPTOR*)buf)->idProduct == ADB_PID)) { USBTRACE("\r\nAcc.mode device detected"); /* 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; //USBTRACE2("\r\nNC:",num_of_conf); @@ -286,7 +285,7 @@ void ADK::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto // Fill in the endpoint info structure epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F); - epInfo[index].maxPktSize = (uint8_t) pep->wMaxPacketSize; + epInfo[index].maxPktSize = (uint8_t)pep->wMaxPacketSize; bNumEP++; diff --git a/adk.h b/adk.h index 7f8bf606..4ea0ed63 100644 --- a/adk.h +++ b/adk.h @@ -133,17 +133,17 @@ public: /* returns 2 bytes in *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 */ 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 */ 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)); } #endif // _ADK_H_ \ No newline at end of file diff --git a/avrpins.h b/avrpins.h index 765a5530..833f9f6b 100644 --- a/avrpins.h +++ b/avrpins.h @@ -178,13 +178,13 @@ public: } static void Set(uint8_t val) { - if (val) + if(val) Set(); else Clear(); } static void SetDir(uint8_t val) { - if (val) + if(val) SetDirWrite(); else SetDirRead(); } @@ -210,12 +210,12 @@ public: } static void WaiteForSet() { - while (IsSet() == 0) { + while(IsSet() == 0) { } } static void WaiteForClear() { - while (IsSet()) { + while(IsSet()) { } } }; //class TPin... @@ -411,7 +411,7 @@ class Tp_Tc { public: static void SetDir(uint8_t val) { - if (val) + if(val) SetDirWrite(); else SetDirRead(); } diff --git a/cdcacm.cpp b/cdcacm.cpp index 9c535a6e..07e1e76a 100644 --- a/cdcacm.cpp +++ b/cdcacm.cpp @@ -79,7 +79,7 @@ uint8_t ACM::Init(uint8_t parent, uint8_t port, bool lowspeed) { p->lowspeed = lowspeed; // Get device descriptor - rcode = pUsb->getDevDescr(0, 0, constBufSize, (uint8_t*) buf); + rcode = pUsb->getDevDescr(0, 0, constBufSize, (uint8_t*)buf); // Restore p->epinfo p->epinfo = oldep_ptr; @@ -94,7 +94,7 @@ uint8_t ACM::Init(uint8_t parent, uint8_t port, bool lowspeed) { return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; // Extract Max Packet Size from the device descriptor - epInfo[0].maxPktSize = (uint8_t) ((USB_DEVICE_DESCRIPTOR*) buf)->bMaxPacketSize0; + epInfo[0].maxPktSize = (uint8_t)((USB_DEVICE_DESCRIPTOR*)buf)->bMaxPacketSize0; // Assign new address to the device rcode = pUsb->setAddr(0, 0, bAddress); @@ -118,7 +118,7 @@ uint8_t ACM::Init(uint8_t parent, uint8_t port, bool lowspeed) { p->lowspeed = lowspeed; - num_of_conf = ((USB_DEVICE_DESCRIPTOR*) buf)->bNumConfigurations; + num_of_conf = ((USB_DEVICE_DESCRIPTOR*)buf)->bNumConfigurations; // Assign epInfo to epinfo pointer rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); @@ -226,7 +226,7 @@ void ACM::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto // Fill in the endpoint info structure epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F); - epInfo[index].maxPktSize = (uint8_t) pep->wMaxPacketSize; + epInfo[index].maxPktSize = (uint8_t)pep->wMaxPacketSize; epInfo[index].epAttribs = 0; bNumEP++; @@ -304,11 +304,11 @@ uint8_t ACM::ClearCommFeature(uint16_t fid) { } 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) { - 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) { diff --git a/cdcftdi.cpp b/cdcftdi.cpp index 2ebca7ab..65f26cb5 100644 --- a/cdcftdi.cpp +++ b/cdcftdi.cpp @@ -78,7 +78,7 @@ uint8_t FTDI::Init(uint8_t parent, uint8_t port, bool lowspeed) { p->lowspeed = lowspeed; // Get device descriptor - rcode = pUsb->getDevDescr(0, 0, sizeof (USB_DEVICE_DESCRIPTOR), (uint8_t*) buf); + rcode = pUsb->getDevDescr(0, 0, sizeof (USB_DEVICE_DESCRIPTOR), (uint8_t*)buf); // Restore p->epinfo p->epinfo = oldep_ptr; @@ -86,11 +86,11 @@ uint8_t FTDI::Init(uint8_t parent, uint8_t port, bool lowspeed) { if (rcode) goto FailGetDevDescr; - if (((USB_DEVICE_DESCRIPTOR*) buf)->idVendor != FTDI_VID || ((USB_DEVICE_DESCRIPTOR*) buf)->idProduct != FTDI_PID) + if (((USB_DEVICE_DESCRIPTOR*)buf)->idVendor != FTDI_VID || ((USB_DEVICE_DESCRIPTOR*)buf)->idProduct != FTDI_PID) return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; // Save type of FTDI chip - wFTDIType = ((USB_DEVICE_DESCRIPTOR*) buf)->bcdDevice; + wFTDIType = ((USB_DEVICE_DESCRIPTOR*)buf)->bcdDevice; // Allocate new address according to device class bAddress = addrPool.AllocAddress(parent, false, port); @@ -99,7 +99,7 @@ uint8_t FTDI::Init(uint8_t parent, uint8_t port, bool lowspeed) { return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; // Extract Max Packet Size from the device descriptor - epInfo[0].maxPktSize = (uint8_t) ((USB_DEVICE_DESCRIPTOR*) buf)->bMaxPacketSize0; + epInfo[0].maxPktSize = (uint8_t)((USB_DEVICE_DESCRIPTOR*)buf)->bMaxPacketSize0; // Assign new address to the device rcode = pUsb->setAddr(0, 0, bAddress); @@ -123,7 +123,7 @@ uint8_t FTDI::Init(uint8_t parent, uint8_t port, bool lowspeed) { p->lowspeed = lowspeed; - num_of_conf = ((USB_DEVICE_DESCRIPTOR*) buf)->bNumConfigurations; + num_of_conf = ((USB_DEVICE_DESCRIPTOR*)buf)->bNumConfigurations; // Assign epInfo to epinfo pointer rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); @@ -224,7 +224,7 @@ void FTDI::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t prot // Fill in the endpoint info structure epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F); - epInfo[index].maxPktSize = (uint8_t) pep->wMaxPacketSize; + epInfo[index].maxPktSize = (uint8_t)pep->wMaxPacketSize; epInfo[index].epAttribs = 0; bNumEP++; diff --git a/cdcprolific.cpp b/cdcprolific.cpp index f0317730..139a627d 100644 --- a/cdcprolific.cpp +++ b/cdcprolific.cpp @@ -57,7 +57,7 @@ uint8_t PL2303::Init(uint8_t parent, uint8_t port, bool lowspeed) { p->lowspeed = lowspeed; // Get device descriptor - rcode = pUsb->getDevDescr(0, 0, sizeof (USB_DEVICE_DESCRIPTOR), (uint8_t*) buf); + rcode = pUsb->getDevDescr(0, 0, sizeof (USB_DEVICE_DESCRIPTOR), (uint8_t*)buf); // Restore p->epinfo p->epinfo = oldep_ptr; @@ -65,11 +65,11 @@ uint8_t PL2303::Init(uint8_t parent, uint8_t port, bool lowspeed) { if (rcode) goto FailGetDevDescr; - if (((USB_DEVICE_DESCRIPTOR*) buf)->idVendor != PL_VID && ((USB_DEVICE_DESCRIPTOR*) buf)->idProduct != PL_PID) + if (((USB_DEVICE_DESCRIPTOR*)buf)->idVendor != PL_VID && ((USB_DEVICE_DESCRIPTOR*)buf)->idProduct != PL_PID) return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; // Save type of PL chip - wPLType = ((USB_DEVICE_DESCRIPTOR*) buf)->bcdDevice; + wPLType = ((USB_DEVICE_DESCRIPTOR*)buf)->bcdDevice; // Allocate new address according to device class bAddress = addrPool.AllocAddress(parent, false, port); @@ -78,7 +78,7 @@ uint8_t PL2303::Init(uint8_t parent, uint8_t port, bool lowspeed) { return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; // Extract Max Packet Size from the device descriptor - epInfo[0].maxPktSize = (uint8_t) ((USB_DEVICE_DESCRIPTOR*) buf)->bMaxPacketSize0; + epInfo[0].maxPktSize = (uint8_t)((USB_DEVICE_DESCRIPTOR*)buf)->bMaxPacketSize0; // Assign new address to the device rcode = pUsb->setAddr(0, 0, bAddress); @@ -102,7 +102,7 @@ uint8_t PL2303::Init(uint8_t parent, uint8_t port, bool lowspeed) { p->lowspeed = lowspeed; - num_of_conf = ((USB_DEVICE_DESCRIPTOR*) buf)->bNumConfigurations; + num_of_conf = ((USB_DEVICE_DESCRIPTOR*)buf)->bNumConfigurations; // Assign epInfo to epinfo pointer rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); diff --git a/confdescparser.h b/confdescparser.h index 9642145f..c446b05e 100644 --- a/confdescparser.h +++ b/confdescparser.h @@ -85,8 +85,8 @@ void ConfigDescParser::Parse(const uin uint16_t cntdn = (uint16_t) len; uint8_t *p = (uint8_t*) pbuf; - while (cntdn) - if (!ParseDescriptor(&p, &cntdn)) + while(cntdn) + if(!ParseDescriptor(&p, &cntdn)) return; } @@ -94,13 +94,13 @@ void ConfigDescParser::Parse(const uin compare masks for them. When the match is found, calls EndpointXtract passing buffer containing endpoint descriptor */ template bool ConfigDescParser::ParseDescriptor(uint8_t **pp, uint16_t *pcntdn) { - switch (stateParseDescr) { + switch(stateParseDescr) { case 0: theBuffer.valueSize = 2; valParser.Initialize(&theBuffer); stateParseDescr = 1; case 1: - if (!valParser.Parse(pp, pcntdn)) + if(!valParser.Parse(pp, pcntdn)) return false; dscrLen = *((uint8_t*) theBuffer.pValue); dscrType = *((uint8_t*) theBuffer.pValue + 1); @@ -114,14 +114,14 @@ bool ConfigDescParser::ParseDescriptor theBuffer.pValue = varBuffer + 2; stateParseDescr = 3; case 3: - switch (dscrType) { + switch(dscrType) { case USB_DESCRIPTOR_INTERFACE: isGoodInterface = false; case USB_DESCRIPTOR_CONFIGURATION: - theBuffer.valueSize = sizeof (USB_CONFIGURATION_DESCRIPTOR) - 2; + theBuffer.valueSize = sizeof(USB_CONFIGURATION_DESCRIPTOR) - 2; break; case USB_DESCRIPTOR_ENDPOINT: - theBuffer.valueSize = sizeof (USB_ENDPOINT_DESCRIPTOR) - 2; + theBuffer.valueSize = sizeof(USB_ENDPOINT_DESCRIPTOR) - 2; break; case HID_DESCRIPTOR_HID: theBuffer.valueSize = dscrLen - 2; @@ -130,20 +130,20 @@ bool ConfigDescParser::ParseDescriptor valParser.Initialize(&theBuffer); stateParseDescr = 4; case 4: - switch (dscrType) { + switch(dscrType) { case USB_DESCRIPTOR_CONFIGURATION: - if (!valParser.Parse(pp, pcntdn)) + if(!valParser.Parse(pp, pcntdn)) return false; confValue = ((USB_CONFIGURATION_DESCRIPTOR*) varBuffer)->bConfigurationValue; break; case USB_DESCRIPTOR_INTERFACE: - if (!valParser.Parse(pp, pcntdn)) + if(!valParser.Parse(pp, pcntdn)) return false; - if ((MASK & CP_MASK_COMPARE_CLASS) && ((USB_INTERFACE_DESCRIPTOR*) varBuffer)->bInterfaceClass != CLASS_ID) + if((MASK & CP_MASK_COMPARE_CLASS) && ((USB_INTERFACE_DESCRIPTOR*) varBuffer)->bInterfaceClass != CLASS_ID) break; - if ((MASK & CP_MASK_COMPARE_SUBCLASS) && ((USB_INTERFACE_DESCRIPTOR*) varBuffer)->bInterfaceSubClass != SUBCLASS_ID) + if((MASK & CP_MASK_COMPARE_SUBCLASS) && ((USB_INTERFACE_DESCRIPTOR*) varBuffer)->bInterfaceSubClass != SUBCLASS_ID) break; - if ((MASK & CP_MASK_COMPARE_PROTOCOL) && ((USB_INTERFACE_DESCRIPTOR*) varBuffer)->bInterfaceProtocol != PROTOCOL_ID) + if((MASK & CP_MASK_COMPARE_PROTOCOL) && ((USB_INTERFACE_DESCRIPTOR*) varBuffer)->bInterfaceProtocol != PROTOCOL_ID) break; isGoodInterface = true; @@ -152,10 +152,10 @@ bool ConfigDescParser::ParseDescriptor protoValue = ((USB_INTERFACE_DESCRIPTOR*) varBuffer)->bInterfaceProtocol; break; case USB_DESCRIPTOR_ENDPOINT: - if (!valParser.Parse(pp, pcntdn)) + if(!valParser.Parse(pp, pcntdn)) return false; - if (isGoodInterface) - if (theXtractor) + if(isGoodInterface) + if(theXtractor) theXtractor->EndpointXtract(confValue, ifaceNumber, ifaceAltSet, protoValue, (USB_ENDPOINT_DESCRIPTOR*) varBuffer); break; //case HID_DESCRIPTOR_HID: @@ -164,7 +164,7 @@ bool ConfigDescParser::ParseDescriptor // PrintHidDescriptor((const USB_HID_DESCRIPTOR*)varBuffer); // break; default: - if (!theSkipper.Skip(pp, pcntdn, dscrLen - 2)) + if(!theSkipper.Skip(pp, pcntdn, dscrLen - 2)) return false; } theBuffer.pValue = varBuffer; @@ -197,7 +197,7 @@ void ConfigDescParser::PrintHidDescrip //Notify(PSTR("\r\nwDescriptorLength:\t")); //PrintHex(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); Notify(PSTR("\r\nbDescrType:\t\t"), 0x80); diff --git a/controllerEnums.h b/controllerEnums.h index 3137e730..5e35a268 100644 --- a/controllerEnums.h +++ b/controllerEnums.h @@ -1,15 +1,15 @@ /* Copyright (C) 2013 Kristian Lauszus, TKJ Electronics. All rights reserved. - + This software may be distributed and modified under the terms of the GNU General Public License version 2 (GPL2) as published by the Free Software Foundation and appearing in the file GPL2.TXT included in the packaging of this file. Please note that GPL2 Section 2[b] requires that all works based on this software must also be made publicly available under the terms of the GPL2 ("Copyleft"). - + Contact information ------------------- - + Kristian Lauszus, TKJ Electronics Web : http://www.tkjelectronics.com e-mail : kristianl@tkjelectronics.com @@ -21,96 +21,98 @@ /* This header file is used to store different enums for the controllers, This is necessary so all the different libraries can be used at once -*/ + */ /** Enum used to turn on the LEDs on the different controllers. */ enum LED { - LED1 = 0, - LED2 = 1, - LED3 = 2, - LED4 = 3, - - LED5 = 4, - LED6 = 5, - LED7 = 6, - LED8 = 7, - LED9 = 8, - LED10 = 9, - /** Used to blink all LEDs on the Xbox controller */ - ALL = 4, + LED1 = 0, + LED2 = 1, + LED3 = 2, + LED4 = 3, + + LED5 = 4, + LED6 = 5, + LED7 = 6, + LED8 = 7, + LED9 = 8, + LED10 = 9, + /** Used to blink all LEDs on the Xbox controller */ + ALL = 4, }; + /** This enum is used to read all the different buttons on the different controllers */ enum Button { - /**@{*/ - /** These buttons are available on all the the controllers */ - UP = 0, - RIGHT = 1, - DOWN = 2, - LEFT = 3, - /**@}*/ + /**@{*/ + /** These buttons are available on all the the controllers */ + UP = 0, + RIGHT = 1, + DOWN = 2, + LEFT = 3, + /**@}*/ - /**@{*/ - /** Wii buttons */ - PLUS = 5, - TWO = 6, - ONE = 7, - MINUS = 8, - HOME = 9, - Z = 10, - C = 11, - B = 12, - A = 13, - /**@}*/ + /**@{*/ + /** Wii buttons */ + PLUS = 5, + TWO = 6, + ONE = 7, + MINUS = 8, + HOME = 9, + Z = 10, + C = 11, + B = 12, + A = 13, + /**@}*/ - /**@{*/ - /** These are only available on the Wii U Pro Controller */ - L = 16, - R = 17, - ZL = 18, - ZR = 19, - /**@}*/ + /**@{*/ + /** These are only available on the Wii U Pro Controller */ + L = 16, + R = 17, + ZL = 18, + ZR = 19, + /**@}*/ - /**@{*/ - /** PS3 controllers buttons */ - SELECT = 4, - START = 5, - L3 = 6, - R3 = 7, - - L2 = 8, - R2 = 9, - L1 = 10, - R1 = 11, - TRIANGLE = 12, - CIRCLE = 13, - CROSS = 14, - SQUARE = 15, - - PS = 16, - - MOVE = 17, // Covers 12 bits - we only need to read the top 8 - T = 18, // Covers 12 bits - we only need to read the top 8 - /**@}*/ + /**@{*/ + /** PS3 controllers buttons */ + SELECT = 4, + START = 5, + L3 = 6, + R3 = 7, - /**@{*/ - /** Xbox buttons */ - BACK = 4, - X = 14, - Y = 15, - XBOX = 16, - SYNC = 17, - /**@}*/ + L2 = 8, + R2 = 9, + L1 = 10, + R1 = 11, + TRIANGLE = 12, + CIRCLE = 13, + CROSS = 14, + SQUARE = 15, + + PS = 16, + + MOVE = 17, // Covers 12 bits - we only need to read the top 8 + T = 18, // Covers 12 bits - we only need to read the top 8 + /**@}*/ + + /**@{*/ + /** Xbox buttons */ + BACK = 4, + X = 14, + Y = 15, + XBOX = 16, + SYNC = 17, + /**@}*/ }; + /** Joysticks on the PS3 and Xbox controllers. */ -enum AnalogHat { - /** Left joystick x-axis */ - LeftHatX = 0, - /** Left joystick y-axis */ - LeftHatY = 1, - /** Right joystick x-axis */ - RightHatX = 2, - /** Right joystick y-axis */ - RightHatY = 3, +enum AnalogHat { + /** Left joystick x-axis */ + LeftHatX = 0, + /** Left joystick y-axis */ + LeftHatY = 1, + /** Right joystick x-axis */ + RightHatX = 2, + /** Right joystick y-axis */ + RightHatY = 3, }; #endif \ No newline at end of file diff --git a/hexdump.h b/hexdump.h index e70317a3..7328d6e5 100644 --- a/hexdump.h +++ b/hexdump.h @@ -41,15 +41,15 @@ public: template void HexDumper::Parse(const LEN_TYPE len, const uint8_t *pbuf, const OFFSET_TYPE &offset) { - for (LEN_TYPE j = 0; j < len; j++, byteCount++, byteTotal++) { - if (!byteCount) { + for(LEN_TYPE j = 0; j < len; j++, byteCount++, byteTotal++) { + if(!byteCount) { SerialPrintHex (byteTotal); Serial.print(": "); } SerialPrintHex (pbuf[j]); Serial.print(" "); - if (byteCount == 15) { + if(byteCount == 15) { Serial.println(""); byteCount = 0xFF; } diff --git a/hid.cpp b/hid.cpp index 7d61c8fb..9d8fcd0f 100644 --- a/hid.cpp +++ b/hid.cpp @@ -7,7 +7,7 @@ uint8_t HID::GetReportDescr(uint8_t ep, USBReadParser *parser) { uint8_t buf[constBufLen]; uint8_t rcode = pUsb->ctrlReq(bAddress, ep, bmREQ_HIDREPORT, USB_REQUEST_GET_DESCRIPTOR, 0x00, - HID_DESCRIPTOR_REPORT, 0x0000, 128, constBufLen, buf, (USBReadParser*) parser); + HID_DESCRIPTOR_REPORT, 0x0000, 128, constBufLen, buf, (USBReadParser*)parser); //return ((rcode != hrSTALL) ? rcode : 0); return rcode; diff --git a/hidboot.cpp b/hidboot.cpp index 2168ecc7..984680eb 100644 --- a/hidboot.cpp +++ b/hidboot.cpp @@ -17,7 +17,7 @@ e-mail : support@circuitsathome.com #include "hidboot.h" 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) OnLeftButtonDown(pmi); @@ -112,20 +112,20 @@ uint8_t KeyboardReportParser::OemToAscii(uint8_t mod, uint8_t key) { // Lower case letters else return (key - 4 + 'a'); - } // Numbers + }// Numbers else if (key > 0x1d && key < 0x27) { if (shift) - return ((uint8_t) pgm_read_byte(&numKeys[key - 0x1e])); + return ((uint8_t)pgm_read_byte(&numKeys[key - 0x1e])); else return (key - 0x1e + '1'); - } // Keypad Numbers + }// Keypad Numbers else if (key > 0x58 && key < 0x62) { if (kbdLockingKeys.kbdLeds.bmNumLock == 1) return (key - 0x59 + '1'); } 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) - return (uint8_t) pgm_read_byte(&padKeys[key - 0x54]); + return (uint8_t)pgm_read_byte(&padKeys[key - 0x54]); else { switch (key) { case KEY_SPACE: return (0x20); diff --git a/hidboot.h b/hidboot.h index 71e813d4..581ee566 100644 --- a/hidboot.h +++ b/hidboot.h @@ -60,7 +60,7 @@ class MouseReportParser : public HIDReportParser { union { MOUSEINFO mouseInfo; - uint8_t bInfo[sizeof (MOUSEINFO)]; + uint8_t bInfo[sizeof(MOUSEINFO)]; } prevState; public: @@ -140,7 +140,7 @@ protected: union { KBDINFO kbdInfo; - uint8_t bInfo[sizeof (KBDINFO)]; + uint8_t bInfo[sizeof(KBDINFO)]; } prevState; union { @@ -221,13 +221,13 @@ bPollEnable(false), pRptParser(NULL) { Initialize(); - if (pUsb) + if(pUsb) pUsb->RegisterDeviceClass(this); } template void HIDBoot::Initialize() { - for (uint8_t i = 0; i < totalEndpoints; i++) { + for(uint8_t i = 0; i < totalEndpoints; i++) { epInfo[i].epAddr = 0; epInfo[i].maxPktSize = (i) ? 0 : 8; epInfo[i].epAttribs = 0; @@ -240,7 +240,7 @@ void HIDBoot::Initialize() { template uint8_t HIDBoot::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 rcode; @@ -256,16 +256,16 @@ uint8_t HIDBoot::Init(uint8_t parent, uint8_t port, bool lowspeed USBTRACE("BM Init\r\n"); - if (bAddress) + if(bAddress) return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE; // Get pointer to pseudo device with address 0 assigned p = addrPool.GetUsbDevicePtr(0); - if (!p) + if(!p) return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; - if (!p->epinfo) { + if(!p->epinfo) { USBTRACE("epinfo\r\n"); return USB_ERROR_EPINFO_IS_NULL; } @@ -281,10 +281,10 @@ uint8_t HIDBoot::Init(uint8_t parent, uint8_t port, bool lowspeed // Get device descriptor rcode = pUsb->getDevDescr(0, 0, 8, (uint8_t*) buf); - if (!rcode) + if(!rcode) len = (buf[0] > constBufSize) ? constBufSize : buf[0]; - if (rcode) { + if(rcode) { // Restore p->epinfo p->epinfo = oldep_ptr; @@ -297,7 +297,7 @@ uint8_t HIDBoot::Init(uint8_t parent, uint8_t port, bool lowspeed // Allocate new address according to device class bAddress = addrPool.AllocAddress(parent, false, port); - if (!bAddress) + if(!bAddress) return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; // Extract Max Packet Size from the device descriptor @@ -306,7 +306,7 @@ uint8_t HIDBoot::Init(uint8_t parent, uint8_t port, bool lowspeed // Assign new address to the device rcode = pUsb->setAddr(0, 0, bAddress); - if (rcode) { + if(rcode) { p->lowspeed = false; addrPool.FreeAddress(bAddress); bAddress = 0; @@ -320,15 +320,15 @@ uint8_t HIDBoot::Init(uint8_t parent, uint8_t port, bool lowspeed p = addrPool.GetUsbDevicePtr(bAddress); - if (!p) + if(!p) return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; p->lowspeed = lowspeed; - if (len) + if(len) rcode = pUsb->getDevDescr(bAddress, 0, len, (uint8_t*) buf); - if (rcode) + if(rcode) goto FailGetDevDescr; num_of_conf = ((USB_DEVICE_DESCRIPTOR*) buf)->bNumConfigurations; @@ -336,12 +336,12 @@ uint8_t HIDBoot::Init(uint8_t parent, uint8_t port, bool lowspeed // Assign epInfo to epinfo pointer rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); - if (rcode) + if(rcode) goto FailSetDevTblEntry; //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_HID, HID_BOOT_INTF_SUBCLASS, @@ -350,11 +350,11 @@ uint8_t HIDBoot::Init(uint8_t parent, uint8_t port, bool lowspeed rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser); - if (bNumEP > 1) + if(bNumEP > 1) break; } // for - if (bNumEP < 2) + if(bNumEP < 2) return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; //USBTRACE2("\r\nbAddr:", bAddress); @@ -368,20 +368,20 @@ uint8_t HIDBoot::Init(uint8_t parent, uint8_t port, bool lowspeed // Set Configuration Value rcode = pUsb->setConf(bAddress, 0, bConfNum); - if (rcode) + if(rcode) goto FailSetConfDescr; //USBTRACE2("\r\nIf:", bIfaceNum); rcode = SetProtocol(bIfaceNum, HID_BOOT_PROTOCOL); - if (rcode) + if(rcode) goto FailSetProtocol; - if (BOOT_PROTOCOL == 1) { + if(BOOT_PROTOCOL == 1) { rcode = SetIdle(bIfaceNum, 0, 0); - if (rcode) + if(rcode) goto FailSetIdle; } USBTRACE("BM configured\r\n"); @@ -424,7 +424,7 @@ Fail: template void HIDBoot::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *pep) { // If the first configuration satisfies, the others are not concidered. - if (bNumEP > 1 && conf != bConfNum) + if(bNumEP > 1 && conf != bConfNum) return; bConfNum = conf; @@ -432,7 +432,7 @@ void HIDBoot::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t uint8_t index; - if ((pep->bmAttributes & 0x03) == 3 && (pep->bEndpointAddress & 0x80) == 0x80) { + if((pep->bmAttributes & 0x03) == 3 && (pep->bEndpointAddress & 0x80) == 0x80) { index = epInterruptInIndex; // Fill in the endpoint info structure @@ -461,10 +461,10 @@ template uint8_t HIDBoot::Poll() { uint8_t rcode = 0; - if (!bPollEnable) + if(!bPollEnable) return 0; - if (qNextPollTime <= millis()) { + if(qNextPollTime <= millis()) { qNextPollTime = millis() + 10; const uint8_t const_buff_len = 16; @@ -474,8 +474,8 @@ uint8_t HIDBoot::Poll() { uint8_t rcode = pUsb->inTransfer(bAddress, epInfo[epInterruptInIndex].epAddr, &read, buf); - if (rcode) { - if (rcode != hrNAK) + if(rcode) { + if(rcode != hrNAK) USBTRACE2("Poll:", rcode); return rcode; } @@ -484,7 +484,7 @@ uint8_t HIDBoot::Poll() { //if (read) // Serial.println(""); - if (pRptParser) + if(pRptParser) pRptParser->Parse((HID*)this, 0, (uint8_t) read, buf); } return rcode; diff --git a/hidescriptorparser.cpp b/hidescriptorparser.cpp index ddb001da..2db1e75c 100644 --- a/hidescriptorparser.cpp +++ b/hidescriptorparser.cpp @@ -1,6 +1,6 @@ #include "hidescriptorparser.h" -const char * const ReportDescParserBase::usagePageTitles0[] PROGMEM ={ +const char * const ReportDescParserBase::usagePageTitles0[] PROGMEM = { pstrUsagePageGenericDesktopControls, pstrUsagePageSimulationControls, pstrUsagePageVRControls, @@ -18,7 +18,7 @@ const char * const ReportDescParserBase::usagePageTitles0[] PROGMEM ={ pstrUsagePageUnicode }; -const char * const ReportDescParserBase::usagePageTitles1[] PROGMEM ={ +const char * const ReportDescParserBase::usagePageTitles1[] PROGMEM = { pstrUsagePageBarCodeScanner, pstrUsagePageScale, pstrUsagePageMSRDevices, @@ -26,7 +26,7 @@ const char * const ReportDescParserBase::usagePageTitles1[] PROGMEM ={ pstrUsagePageCameraControl, pstrUsagePageArcade }; -const char * const ReportDescParserBase::genDesktopTitles0[] PROGMEM ={ +const char * const ReportDescParserBase::genDesktopTitles0[] PROGMEM = { pstrUsagePointer, pstrUsageMouse, pstrUsageJoystick, @@ -37,7 +37,7 @@ const char * const ReportDescParserBase::genDesktopTitles0[] PROGMEM ={ pstrUsageTabletPCSystemControls }; -const char * const ReportDescParserBase::genDesktopTitles1[] PROGMEM ={ +const char * const ReportDescParserBase::genDesktopTitles1[] PROGMEM = { pstrUsageX, pstrUsageY, pstrUsageZ, @@ -64,7 +64,7 @@ const char * const ReportDescParserBase::genDesktopTitles1[] PROGMEM ={ pstrUsageFeatureNotification, pstrUsageResolutionMultiplier }; -const char * const ReportDescParserBase::genDesktopTitles2[] PROGMEM ={ +const char * const ReportDescParserBase::genDesktopTitles2[] PROGMEM = { pstrUsageSystemControl, pstrUsageSystemPowerDown, pstrUsageSystemSleep, @@ -86,7 +86,7 @@ const char * const ReportDescParserBase::genDesktopTitles2[] PROGMEM ={ pstrUsageDPadRight, pstrUsageDPadLeft }; -const char * const ReportDescParserBase::genDesktopTitles3[] PROGMEM ={ +const char * const ReportDescParserBase::genDesktopTitles3[] PROGMEM = { pstrUsageSystemDock, pstrUsageSystemUndock, pstrUsageSystemSetup, @@ -97,7 +97,7 @@ const char * const ReportDescParserBase::genDesktopTitles3[] PROGMEM ={ pstrUsageSystemSpeakerMute, pstrUsageSystemHibernate }; -const char * const ReportDescParserBase::genDesktopTitles4[] PROGMEM ={ +const char * const ReportDescParserBase::genDesktopTitles4[] PROGMEM = { pstrUsageSystemDisplayInvert, pstrUsageSystemDisplayInternal, pstrUsageSystemDisplayExternal, @@ -107,7 +107,7 @@ const char * const ReportDescParserBase::genDesktopTitles4[] PROGMEM ={ pstrUsageSystemDisplaySwapPriSec, pstrUsageSystemDisplayLCDAutoscale }; -const char * const ReportDescParserBase::simuTitles0[] PROGMEM ={ +const char * const ReportDescParserBase::simuTitles0[] PROGMEM = { pstrUsageFlightSimulationDevice, pstrUsageAutomobileSimulationDevice, pstrUsageTankSimulationDevice, @@ -121,7 +121,7 @@ const char * const ReportDescParserBase::simuTitles0[] PROGMEM ={ pstrUsageMagicCarpetSimulationDevice, pstrUsageBicycleSimulationDevice }; -const char * const ReportDescParserBase::simuTitles1[] PROGMEM ={ +const char * const ReportDescParserBase::simuTitles1[] PROGMEM = { pstrUsageFlightControlStick, pstrUsageFlightStick, pstrUsageCyclicControl, @@ -129,7 +129,7 @@ const char * const ReportDescParserBase::simuTitles1[] PROGMEM ={ pstrUsageFlightYoke, pstrUsageTrackControl }; -const char * const ReportDescParserBase::simuTitles2[] PROGMEM ={ +const char * const ReportDescParserBase::simuTitles2[] PROGMEM = { pstrUsageAileron, pstrUsageAileronTrim, pstrUsageAntiTorqueControl, @@ -164,7 +164,7 @@ const char * const ReportDescParserBase::simuTitles2[] PROGMEM ={ pstrUsageFrontBrake, pstrUsageRearBrake }; -const char * const ReportDescParserBase::vrTitles0[] PROGMEM ={ +const char * const ReportDescParserBase::vrTitles0[] PROGMEM = { pstrUsageBelt, pstrUsageBodySuit, pstrUsageFlexor, @@ -176,17 +176,17 @@ const char * const ReportDescParserBase::vrTitles0[] PROGMEM ={ pstrUsageVest, pstrUsageAnimatronicDevice }; -const char * const ReportDescParserBase::vrTitles1[] PROGMEM ={ +const char * const ReportDescParserBase::vrTitles1[] PROGMEM = { pstrUsageStereoEnable, pstrUsageDisplayEnable }; -const char * const ReportDescParserBase::sportsCtrlTitles0[] PROGMEM ={ +const char * const ReportDescParserBase::sportsCtrlTitles0[] PROGMEM = { pstrUsageBaseballBat, pstrUsageGolfClub, pstrUsageRowingMachine, pstrUsageTreadmill }; -const char * const ReportDescParserBase::sportsCtrlTitles1[] PROGMEM ={ +const char * const ReportDescParserBase::sportsCtrlTitles1[] PROGMEM = { pstrUsageOar, pstrUsageSlope, pstrUsageRate, @@ -198,7 +198,7 @@ const char * const ReportDescParserBase::sportsCtrlTitles1[] PROGMEM ={ pstrUsageStickType, pstrUsageStickHeight }; -const char * const ReportDescParserBase::sportsCtrlTitles2[] PROGMEM ={ +const char * const ReportDescParserBase::sportsCtrlTitles2[] PROGMEM = { pstrUsagePutter, pstrUsage1Iron, pstrUsage2Iron, @@ -220,12 +220,12 @@ const char * const ReportDescParserBase::sportsCtrlTitles2[] PROGMEM ={ pstrUsage7Wood, pstrUsage9Wood }; -const char * const ReportDescParserBase::gameTitles0[] PROGMEM ={ +const char * const ReportDescParserBase::gameTitles0[] PROGMEM = { pstrUsage3DGameController, pstrUsagePinballDevice, pstrUsageGunDevice }; -const char * const ReportDescParserBase::gameTitles1[] PROGMEM ={ +const char * const ReportDescParserBase::gameTitles1[] PROGMEM = { pstrUsagePointOfView, pstrUsageTurnRightLeft, pstrUsagePitchForwardBackward, @@ -252,7 +252,7 @@ const char * const ReportDescParserBase::gameTitles1[] PROGMEM ={ pstrUsageGamepadFireJump, pstrUsageGamepadTrigger }; -const char * const ReportDescParserBase::genDevCtrlTitles[] PROGMEM ={ +const char * const ReportDescParserBase::genDevCtrlTitles[] PROGMEM = { pstrUsageBatteryStrength, pstrUsageWirelessChannel, pstrUsageWirelessID, @@ -261,7 +261,7 @@ const char * const ReportDescParserBase::genDevCtrlTitles[] PROGMEM ={ pstrUsageSecurityCodeCharErased, pstrUsageSecurityCodeCleared }; -const char * const ReportDescParserBase::ledTitles[] PROGMEM ={ +const char * const ReportDescParserBase::ledTitles[] PROGMEM = { pstrUsageNumLock, pstrUsageCapsLock, pstrUsageScrollLock, @@ -340,7 +340,7 @@ const char * const ReportDescParserBase::ledTitles[] PROGMEM ={ pstrUsageSystemSuspend, pstrUsageExternalPowerConnected }; -const char * const ReportDescParserBase::telTitles0 [] PROGMEM ={ +const char * const ReportDescParserBase::telTitles0 [] PROGMEM = { pstrUsagePhone, pstrUsageAnsweringMachine, pstrUsageMessageControls, @@ -349,7 +349,7 @@ const char * const ReportDescParserBase::telTitles0 [] PROGMEM ={ pstrUsageTelephonyKeyPad, pstrUsageProgrammableButton }; -const char * const ReportDescParserBase::telTitles1 [] PROGMEM ={ +const char * const ReportDescParserBase::telTitles1 [] PROGMEM = { pstrUsageHookSwitch, pstrUsageFlash, pstrUsageFeature, @@ -369,20 +369,20 @@ const char * const ReportDescParserBase::telTitles1 [] PROGMEM ={ pstrUsageCallerID, pstrUsageSend }; -const char * const ReportDescParserBase::telTitles2 [] PROGMEM ={ +const char * const ReportDescParserBase::telTitles2 [] PROGMEM = { pstrUsageSpeedDial, pstrUsageStoreNumber, pstrUsageRecallNumber, pstrUsagePhoneDirectory }; -const char * const ReportDescParserBase::telTitles3 [] PROGMEM ={ +const char * const ReportDescParserBase::telTitles3 [] PROGMEM = { pstrUsageVoiceMail, pstrUsageScreenCalls, pstrUsageDoNotDisturb, pstrUsageMessage, pstrUsageAnswerOnOff }; -const char * const ReportDescParserBase::telTitles4 [] PROGMEM ={ +const char * const ReportDescParserBase::telTitles4 [] PROGMEM = { pstrUsageInsideDialTone, pstrUsageOutsideDialTone, pstrUsageInsideRingTone, @@ -399,7 +399,7 @@ const char * const ReportDescParserBase::telTitles4 [] PROGMEM ={ pstrUsageOutsideRingback, pstrUsageRinger }; -const char * const ReportDescParserBase::telTitles5 [] PROGMEM ={ +const char * const ReportDescParserBase::telTitles5 [] PROGMEM = { pstrUsagePhoneKey0, pstrUsagePhoneKey1, pstrUsagePhoneKey2, @@ -417,7 +417,7 @@ const char * const ReportDescParserBase::telTitles5 [] PROGMEM ={ pstrUsagePhoneKeyC, pstrUsagePhoneKeyD }; -const char * const ReportDescParserBase::consTitles0[] PROGMEM ={ +const char * const ReportDescParserBase::consTitles0[] PROGMEM = { pstrUsageConsumerControl, pstrUsageNumericKeyPad, pstrUsageProgrammableButton, @@ -425,12 +425,12 @@ const char * const ReportDescParserBase::consTitles0[] PROGMEM ={ pstrUsageHeadphone, pstrUsageGraphicEqualizer }; -const char * const ReportDescParserBase::consTitles1[] PROGMEM ={ +const char * const ReportDescParserBase::consTitles1[] PROGMEM = { pstrUsagePlus10, pstrUsagePlus100, pstrUsageAMPM }; -const char * const ReportDescParserBase::consTitles2[] PROGMEM ={ +const char * const ReportDescParserBase::consTitles2[] PROGMEM = { pstrUsagePower, pstrUsageReset, pstrUsageSleep, @@ -440,7 +440,7 @@ const char * const ReportDescParserBase::consTitles2[] PROGMEM ={ pstrUsageFunctionButtons }; -const char * const ReportDescParserBase::consTitles3[] PROGMEM ={ +const char * const ReportDescParserBase::consTitles3[] PROGMEM = { pstrUsageMenu, pstrUsageMenuPick, pstrUsageMenuUp, @@ -451,7 +451,7 @@ const char * const ReportDescParserBase::consTitles3[] PROGMEM ={ pstrUsageMenuValueIncrease, pstrUsageMenuValueDecrease }; -const char * const ReportDescParserBase::consTitles4[] PROGMEM ={ +const char * const ReportDescParserBase::consTitles4[] PROGMEM = { pstrUsageDataOnScreen, pstrUsageClosedCaption, pstrUsageClosedCaptionSelect, @@ -460,7 +460,7 @@ const char * const ReportDescParserBase::consTitles4[] PROGMEM ={ pstrUsageSnapshot, pstrUsageStill }; -const char * const ReportDescParserBase::consTitles5[] PROGMEM ={ +const char * const ReportDescParserBase::consTitles5[] PROGMEM = { pstrUsageSelection, pstrUsageAssignSelection, pstrUsageModeStep, @@ -499,7 +499,7 @@ const char * const ReportDescParserBase::consTitles5[] PROGMEM ={ pstrUsageWeekly, pstrUsageMonthly }; -const char * const ReportDescParserBase::consTitles6[] PROGMEM ={ +const char * const ReportDescParserBase::consTitles6[] PROGMEM = { pstrUsagePlay, pstrUsagePause, pstrUsageRecord, @@ -532,7 +532,7 @@ const char * const ReportDescParserBase::consTitles6[] PROGMEM ={ pstrUsagePlayPause, pstrUsagePlaySkip }; -const char * const ReportDescParserBase::consTitles7[] PROGMEM ={ +const char * const ReportDescParserBase::consTitles7[] PROGMEM = { pstrUsageVolume, pstrUsageBalance, pstrUsageMute, @@ -545,7 +545,7 @@ const char * const ReportDescParserBase::consTitles7[] PROGMEM ={ pstrUsageVolumeIncrement, pstrUsageVolumeDecrement }; -const char * const ReportDescParserBase::consTitles8[] PROGMEM ={ +const char * const ReportDescParserBase::consTitles8[] PROGMEM = { pstrUsageSpeedSelect, pstrUsagePlaybackSpeed, pstrUsageStandardPlay, @@ -553,7 +553,7 @@ const char * const ReportDescParserBase::consTitles8[] PROGMEM ={ pstrUsageExtendedPlay, pstrUsageSlow }; -const char * const ReportDescParserBase::consTitles9[] PROGMEM ={ +const char * const ReportDescParserBase::consTitles9[] PROGMEM = { pstrUsageFanEnable, pstrUsageFanSpeed, pstrUsageLightEnable, @@ -569,7 +569,7 @@ const char * const ReportDescParserBase::consTitles9[] PROGMEM ={ pstrUsageHoldupAlarm, pstrUsageMedicalAlarm }; -const char * const ReportDescParserBase::consTitlesA[] PROGMEM ={ +const char * const ReportDescParserBase::consTitlesA[] PROGMEM = { pstrUsageBalanceRight, pstrUsageBalanceLeft, pstrUsageBassIncrement, @@ -577,7 +577,7 @@ const char * const ReportDescParserBase::consTitlesA[] PROGMEM ={ pstrUsageTrebleIncrement, pstrUsageTrebleDecrement }; -const char * const ReportDescParserBase::consTitlesB[] PROGMEM ={ +const char * const ReportDescParserBase::consTitlesB[] PROGMEM = { pstrUsageSpeakerSystem, pstrUsageChannelLeft, pstrUsageChannelRight, @@ -590,14 +590,14 @@ const char * const ReportDescParserBase::consTitlesB[] PROGMEM ={ pstrUsageChannelTop, pstrUsageChannelUnknown }; -const char * const ReportDescParserBase::consTitlesC[] PROGMEM ={ +const char * const ReportDescParserBase::consTitlesC[] PROGMEM = { pstrUsageSubChannel, pstrUsageSubChannelIncrement, pstrUsageSubChannelDecrement, pstrUsageAlternateAudioIncrement, pstrUsageAlternateAudioDecrement }; -const char * const ReportDescParserBase::consTitlesD[] PROGMEM ={ +const char * const ReportDescParserBase::consTitlesD[] PROGMEM = { pstrUsageApplicationLaunchButtons, pstrUsageALLaunchButtonConfigTool, pstrUsageALProgrammableButton, @@ -671,7 +671,7 @@ const char * const ReportDescParserBase::consTitlesD[] PROGMEM ={ pstrUsageALResearchSearchBrowser, pstrUsageALAudioPlayer }; -const char * const ReportDescParserBase::consTitlesE[] PROGMEM ={ +const char * const ReportDescParserBase::consTitlesE[] PROGMEM = { pstrUsageGenericGUIAppControls, pstrUsageACNew, pstrUsageACOpen, @@ -814,7 +814,7 @@ const char * const ReportDescParserBase::consTitlesE[] PROGMEM ={ pstrUsageACDistributeHorizontaly, pstrUsageACDistributeVerticaly }; -const char * const ReportDescParserBase::digitTitles0[] PROGMEM ={ +const char * const ReportDescParserBase::digitTitles0[] PROGMEM = { pstrUsageDigitizer, pstrUsagePen, pstrUsageLightPen, @@ -829,13 +829,13 @@ const char * const ReportDescParserBase::digitTitles0[] PROGMEM ={ pstrUsageMultiplePointDigitizer, pstrUsageFreeSpaceWand }; -const char * const ReportDescParserBase::digitTitles1[] PROGMEM ={ +const char * const ReportDescParserBase::digitTitles1[] PROGMEM = { pstrUsageStylus, pstrUsagePuck, pstrUsageFinger }; -const char * const ReportDescParserBase::digitTitles2[] PROGMEM ={ +const char * const ReportDescParserBase::digitTitles2[] PROGMEM = { pstrUsageTipPressure, pstrUsageBarrelPressure, pstrUsageInRange, @@ -860,11 +860,11 @@ const char * const ReportDescParserBase::digitTitles2[] PROGMEM ={ pstrUsageEraser, pstrUsageTabletPick }; -const char * const ReportDescParserBase::aplphanumTitles0[] PROGMEM ={ +const char * const ReportDescParserBase::aplphanumTitles0[] PROGMEM = { pstrUsageAlphanumericDisplay, pstrUsageBitmappedDisplay }; -const char * const ReportDescParserBase::aplphanumTitles1[] PROGMEM ={ +const char * const ReportDescParserBase::aplphanumTitles1[] PROGMEM = { pstrUsageDisplayAttributesReport, pstrUsageASCIICharacterSet, pstrUsageDataReadBack, @@ -912,7 +912,7 @@ const char * const ReportDescParserBase::aplphanumTitles1[] PROGMEM ={ pstrUsageCharAttributeUnderline, pstrUsageCharAttributeBlink }; -const char * const ReportDescParserBase::aplphanumTitles2[] PROGMEM ={ +const char * const ReportDescParserBase::aplphanumTitles2[] PROGMEM = { pstrUsageBitmapSizeX, pstrUsageBitmapSizeY, pstrUsagePageReserved, @@ -935,7 +935,7 @@ const char * const ReportDescParserBase::aplphanumTitles2[] PROGMEM ={ pstrUsageSoftButtonOffset2, pstrUsageSoftButtonReport }; -const char * const ReportDescParserBase::medInstrTitles0[] PROGMEM ={ +const char * const ReportDescParserBase::medInstrTitles0[] PROGMEM = { pstrUsageVCRAcquisition, pstrUsageFreezeThaw, pstrUsageClipStore, @@ -945,18 +945,18 @@ const char * const ReportDescParserBase::medInstrTitles0[] PROGMEM ={ pstrUsagePrint, pstrUsageMicrophoneEnable }; -const char * const ReportDescParserBase::medInstrTitles1[] PROGMEM ={ +const char * const ReportDescParserBase::medInstrTitles1[] PROGMEM = { pstrUsageCine, pstrUsageTransmitPower, pstrUsageVolume, pstrUsageFocus, pstrUsageDepth }; -const char * const ReportDescParserBase::medInstrTitles2[] PROGMEM ={ +const char * const ReportDescParserBase::medInstrTitles2[] PROGMEM = { pstrUsageSoftStepPrimary, pstrUsageSoftStepSecondary }; -const char * const ReportDescParserBase::medInstrTitles3[] PROGMEM ={ +const char * const ReportDescParserBase::medInstrTitles3[] PROGMEM = { pstrUsageZoomSelect, pstrUsageZoomAdjust, pstrUsageSpectralDopplerModeSelect, @@ -968,14 +968,14 @@ const char * const ReportDescParserBase::medInstrTitles3[] PROGMEM ={ pstrUsage2DModeSelect, pstrUsage2DModeAdjust }; -const char * const ReportDescParserBase::medInstrTitles4[] PROGMEM ={ +const char * const ReportDescParserBase::medInstrTitles4[] PROGMEM = { pstrUsageSoftControlSelect, pstrUsageSoftControlAdjust }; void ReportDescParserBase::Parse(const uint16_t len, const uint8_t *pbuf, const uint16_t &offset) { - uint16_t cntdn = (uint16_t) len; - uint8_t *p = (uint8_t*) pbuf; + uint16_t cntdn = (uint16_t)len; + uint8_t *p = (uint8_t*)pbuf; totalSize = 0; @@ -1108,13 +1108,13 @@ uint8_t ReportDescParserBase::ParseItem(uint8_t **pp, uint16_t *pcntdn) { itemParseState = 3; case 3: { - uint8_t data = *((uint8_t*) varBuffer); + uint8_t data = *((uint8_t*)varBuffer); switch (itemPrefix & (TYPE_MASK | TAG_MASK)) { case (TYPE_LOCAL | TAG_LOCAL_USAGE): if (pfUsage) { if (theBuffer.valueSize > 1) - pfUsage(*((uint16_t*) varBuffer)); + pfUsage(*((uint16_t*)varBuffer)); else pfUsage(data); } @@ -1179,7 +1179,7 @@ uint8_t ReportDescParserBase::ParseItem(uint8_t **pp, uint16_t *pcntdn) { case (TYPE_MAIN | TAG_MAIN_INPUT): case (TYPE_MAIN | TAG_MAIN_OUTPUT): case (TYPE_MAIN | TAG_MAIN_FEATURE): - totalSize += (uint16_t) rptSize * (uint16_t) rptCount; + totalSize += (uint16_t)rptSize * (uint16_t)rptCount; rptSize = 0; rptCount = 0; Notify(PSTR("("), 0x80); @@ -1193,7 +1193,7 @@ uint8_t ReportDescParserBase::ParseItem(uint8_t **pp, uint16_t *pcntdn) { return enErrorSuccess; } -ReportDescParserBase::UsagePageFunc ReportDescParserBase::usagePageFunctions[] /*PROGMEM*/ ={ +ReportDescParserBase::UsagePageFunc ReportDescParserBase::usagePageFunctions[] /*PROGMEM*/ = { &ReportDescParserBase::PrintGenericDesktopPageUsage, &ReportDescParserBase::PrintSimulationControlsPageUsage, &ReportDescParserBase::PrintVRControlsPageUsage, @@ -1240,13 +1240,13 @@ void ReportDescParserBase::PrintUsagePage(uint16_t page) { Notify(pstrSpace, 0x80); if (page > 0x00 && page < 0x11) - Notify((char*) pgm_read_word(&usagePageTitles0[page - 1]), 0x80); + Notify((char*)pgm_read_word(&usagePageTitles0[page - 1]), 0x80); else if (page > 0x7f && page < 0x84) Notify(pstrUsagePageMonitor, 0x80); else if (page > 0x83 && page < 0x8c) Notify(pstrUsagePagePower, 0x80); else if (page > 0x8b && page < 0x92) - Notify((char*) pgm_read_word(&usagePageTitles1[page - 0x8c]), 0x80); + Notify((char*)pgm_read_word(&usagePageTitles1[page - 0x8c]), 0x80); else if (page > 0xfeff && page <= 0xffff) Notify(pstrUsagePageVendorDefined, 0x80); else @@ -1283,15 +1283,15 @@ void ReportDescParserBase::PrintGenericDesktopPageUsage(uint16_t usage) { Notify(pstrSpace, 0x80); if (usage > 0x00 && usage < 0x0a) - Notify((char*) pgm_read_word(&genDesktopTitles0[usage - 1]), 0x80); + Notify((char*)pgm_read_word(&genDesktopTitles0[usage - 1]), 0x80); else if (usage > 0x2f && usage < 0x49) - Notify((char*) pgm_read_word(&genDesktopTitles1[usage - 0x30]), 0x80); + Notify((char*)pgm_read_word(&genDesktopTitles1[usage - 0x30]), 0x80); else if (usage > 0x7f && usage < 0x94) - Notify((char*) pgm_read_word(&genDesktopTitles2[usage - 0x80]), 0x80); + Notify((char*)pgm_read_word(&genDesktopTitles2[usage - 0x80]), 0x80); else if (usage > 0x9f && usage < 0xa9) - Notify((char*) pgm_read_word(&genDesktopTitles3[usage - 0xa0]), 0x80); + Notify((char*)pgm_read_word(&genDesktopTitles3[usage - 0xa0]), 0x80); else if (usage > 0xaf && usage < 0xb8) - Notify((char*) pgm_read_word(&genDesktopTitles4[usage - 0xb0]), 0x80); + Notify((char*)pgm_read_word(&genDesktopTitles4[usage - 0xb0]), 0x80); else Notify(pstrUsagePageUndefined, 0x80); } @@ -1300,11 +1300,11 @@ void ReportDescParserBase::PrintSimulationControlsPageUsage(uint16_t usage) { Notify(pstrSpace, 0x80); if (usage > 0x00 && usage < 0x0d) - Notify((char*) pgm_read_word(&simuTitles0[usage - 1]), 0x80); + Notify((char*)pgm_read_word(&simuTitles0[usage - 1]), 0x80); else if (usage > 0x1f && usage < 0x26) - Notify((char*) pgm_read_word(&simuTitles1[usage - 0x20]), 0x80); + Notify((char*)pgm_read_word(&simuTitles1[usage - 0x20]), 0x80); else if (usage > 0xaf && usage < 0xd1) - Notify((char*) pgm_read_word(&simuTitles2[usage - 0xb0]), 0x80); + Notify((char*)pgm_read_word(&simuTitles2[usage - 0xb0]), 0x80); else Notify(pstrUsagePageUndefined, 0x80); } @@ -1313,9 +1313,9 @@ void ReportDescParserBase::PrintVRControlsPageUsage(uint16_t usage) { Notify(pstrSpace, 0x80); if (usage > 0x00 && usage < 0x0b) - Notify((char*) pgm_read_word(&vrTitles0[usage - 1]), 0x80); + Notify((char*)pgm_read_word(&vrTitles0[usage - 1]), 0x80); else if (usage > 0x1f && usage < 0x22) - Notify((char*) pgm_read_word(&vrTitles1[usage - 0x20]), 0x80); + Notify((char*)pgm_read_word(&vrTitles1[usage - 0x20]), 0x80); else Notify(pstrUsagePageUndefined, 0x80); } @@ -1324,11 +1324,11 @@ void ReportDescParserBase::PrintSportsControlsPageUsage(uint16_t usage) { Notify(pstrSpace, 0x80); if (usage > 0x00 && usage < 0x05) - Notify((char*) pgm_read_word(&sportsCtrlTitles0[usage - 1]), 0x80); + Notify((char*)pgm_read_word(&sportsCtrlTitles0[usage - 1]), 0x80); else if (usage > 0x2f && usage < 0x3a) - Notify((char*) pgm_read_word(&sportsCtrlTitles1[usage - 0x30]), 0x80); + Notify((char*)pgm_read_word(&sportsCtrlTitles1[usage - 0x30]), 0x80); else if (usage > 0x4f && usage < 0x64) - Notify((char*) pgm_read_word(&sportsCtrlTitles2[usage - 0x50]), 0x80); + Notify((char*)pgm_read_word(&sportsCtrlTitles2[usage - 0x50]), 0x80); else Notify(pstrUsagePageUndefined, 0x80); } @@ -1337,9 +1337,9 @@ void ReportDescParserBase::PrintGameControlsPageUsage(uint16_t usage) { Notify(pstrSpace, 0x80); if (usage > 0x00 && usage < 0x04) - Notify((char*) pgm_read_word(&gameTitles0[usage - 1]), 0x80); + Notify((char*)pgm_read_word(&gameTitles0[usage - 1]), 0x80); else if (usage > 0x1f && usage < 0x3a) - Notify((char*) pgm_read_word(&gameTitles1[usage - 0x20]), 0x80); + Notify((char*)pgm_read_word(&gameTitles1[usage - 0x20]), 0x80); else Notify(pstrUsagePageUndefined, 0x80); } @@ -1348,7 +1348,7 @@ void ReportDescParserBase::PrintGenericDeviceControlsPageUsage(uint16_t usage) { Notify(pstrSpace, 0x80); if (usage > 0x1f && usage < 0x27) - Notify((char*) pgm_read_word(&genDevCtrlTitles[usage - 0x20]), 0x80); + Notify((char*)pgm_read_word(&genDevCtrlTitles[usage - 0x20]), 0x80); else Notify(pstrUsagePageUndefined, 0x80); } @@ -1357,7 +1357,7 @@ void ReportDescParserBase::PrintLEDPageUsage(uint16_t usage) { Notify(pstrSpace, 0x80); if (usage > 0x00 && usage < 0x4e) - Notify((char*) pgm_read_word(&ledTitles[usage - 1]), 0x80); + Notify((char*)pgm_read_word(&ledTitles[usage - 1]), 0x80); else Notify(pstrUsagePageUndefined, 0x80); } @@ -1366,17 +1366,17 @@ void ReportDescParserBase::PrintTelephonyPageUsage(uint16_t usage) { Notify(pstrSpace, 0x80); if (usage > 0x00 && usage < 0x08) - Notify((char*) pgm_read_word(&telTitles0[usage - 1]), 0x80); + Notify((char*)pgm_read_word(&telTitles0[usage - 1]), 0x80); else if (usage > 0x1f && usage < 0x32) - Notify((char*) pgm_read_word(&telTitles1[usage - 0x1f]), 0x80); + Notify((char*)pgm_read_word(&telTitles1[usage - 0x1f]), 0x80); else if (usage > 0x4f && usage < 0x54) - Notify((char*) pgm_read_word(&telTitles2[usage - 0x4f]), 0x80); + Notify((char*)pgm_read_word(&telTitles2[usage - 0x4f]), 0x80); else if (usage > 0x6f && usage < 0x75) - Notify((char*) pgm_read_word(&telTitles3[usage - 0x6f]), 0x80); + Notify((char*)pgm_read_word(&telTitles3[usage - 0x6f]), 0x80); else if (usage > 0x8f && usage < 0x9f) - Notify((char*) pgm_read_word(&telTitles4[usage - 0x8f]), 0x80); + Notify((char*)pgm_read_word(&telTitles4[usage - 0x8f]), 0x80); else if (usage > 0xaf && usage < 0xc0) - Notify((char*) pgm_read_word(&telTitles5[usage - 0xaf]), 0x80); + Notify((char*)pgm_read_word(&telTitles5[usage - 0xaf]), 0x80); else Notify(pstrUsagePageUndefined, 0x80); } @@ -1385,35 +1385,35 @@ void ReportDescParserBase::PrintConsumerPageUsage(uint16_t usage) { Notify(pstrSpace, 0x80); if (usage > 0x00 && usage < 0x07) - Notify((char*) pgm_read_word(&consTitles0[usage - 1]), 0x80); + Notify((char*)pgm_read_word(&consTitles0[usage - 1]), 0x80); else if (usage > 0x1f && usage < 0x23) - Notify((char*) pgm_read_word(&consTitles1[usage - 0x1f]), 0x80); + Notify((char*)pgm_read_word(&consTitles1[usage - 0x1f]), 0x80); else if (usage > 0x2f && usage < 0x37) - Notify((char*) pgm_read_word(&consTitles2[usage - 0x2f]), 0x80); + Notify((char*)pgm_read_word(&consTitles2[usage - 0x2f]), 0x80); else if (usage > 0x3f && usage < 0x49) - Notify((char*) pgm_read_word(&consTitles3[usage - 0x3f]), 0x80); + Notify((char*)pgm_read_word(&consTitles3[usage - 0x3f]), 0x80); else if (usage > 0x5f && usage < 0x67) - Notify((char*) pgm_read_word(&consTitles4[usage - 0x5f]), 0x80); + Notify((char*)pgm_read_word(&consTitles4[usage - 0x5f]), 0x80); else if (usage > 0x7f && usage < 0xa5) - Notify((char*) pgm_read_word(&consTitles5[usage - 0x7f]), 0x80); + Notify((char*)pgm_read_word(&consTitles5[usage - 0x7f]), 0x80); else if (usage > 0xaf && usage < 0xcf) - Notify((char*) pgm_read_word(&consTitles6[usage - 0xaf]), 0x80); + Notify((char*)pgm_read_word(&consTitles6[usage - 0xaf]), 0x80); else if (usage > 0xdf && usage < 0xeb) - Notify((char*) pgm_read_word(&consTitles7[usage - 0xdf]), 0x80); + Notify((char*)pgm_read_word(&consTitles7[usage - 0xdf]), 0x80); else if (usage > 0xef && usage < 0xf6) - Notify((char*) pgm_read_word(&consTitles8[usage - 0xef]), 0x80); + Notify((char*)pgm_read_word(&consTitles8[usage - 0xef]), 0x80); else if (usage > 0xff && usage < 0x10e) - Notify((char*) pgm_read_word(&consTitles9[usage - 0xff]), 0x80); + Notify((char*)pgm_read_word(&consTitles9[usage - 0xff]), 0x80); else if (usage > 0x14f && usage < 0x156) - Notify((char*) pgm_read_word(&consTitlesA[usage - 0x14f]), 0x80); + Notify((char*)pgm_read_word(&consTitlesA[usage - 0x14f]), 0x80); else if (usage > 0x15f && usage < 0x16b) - Notify((char*) pgm_read_word(&consTitlesB[usage - 0x15f]), 0x80); + Notify((char*)pgm_read_word(&consTitlesB[usage - 0x15f]), 0x80); else if (usage > 0x16f && usage < 0x175) - Notify((char*) pgm_read_word(&consTitlesC[usage - 0x16f]), 0x80); + Notify((char*)pgm_read_word(&consTitlesC[usage - 0x16f]), 0x80); else if (usage > 0x17f && usage < 0x1c8) - Notify((char*) pgm_read_word(&consTitlesD[usage - 0x17f]), 0x80); + Notify((char*)pgm_read_word(&consTitlesD[usage - 0x17f]), 0x80); else if (usage > 0x1ff && usage < 0x29d) - Notify((char*) pgm_read_word(&consTitlesE[usage - 0x1ff]), 0x80); + Notify((char*)pgm_read_word(&consTitlesE[usage - 0x1ff]), 0x80); else Notify(pstrUsagePageUndefined, 0x80); } @@ -1422,11 +1422,11 @@ void ReportDescParserBase::PrintDigitizerPageUsage(uint16_t usage) { Notify(pstrSpace, 0x80); if (usage > 0x00 && usage < 0x0e) - Notify((char*) pgm_read_word(&digitTitles0[usage - 1]), 0x80); + Notify((char*)pgm_read_word(&digitTitles0[usage - 1]), 0x80); else if (usage > 0x1f && usage < 0x23) - Notify((char*) pgm_read_word(&digitTitles1[usage - 0x1f]), 0x80); + Notify((char*)pgm_read_word(&digitTitles1[usage - 0x1f]), 0x80); else if (usage > 0x2f && usage < 0x47) - Notify((char*) pgm_read_word(&digitTitles2[usage - 0x2f]), 0x80); + Notify((char*)pgm_read_word(&digitTitles2[usage - 0x2f]), 0x80); else Notify(pstrUsagePageUndefined, 0x80); } @@ -1435,11 +1435,11 @@ void ReportDescParserBase::PrintAlphanumDisplayPageUsage(uint16_t usage) { Notify(pstrSpace, 0x80); if (usage > 0x00 && usage < 0x03) - Notify((char*) pgm_read_word(&aplphanumTitles0[usage - 1]), 0x80); + Notify((char*)pgm_read_word(&aplphanumTitles0[usage - 1]), 0x80); else if (usage > 0x1f && usage < 0x4e) - Notify((char*) pgm_read_word(&aplphanumTitles1[usage - 0x1f]), 0x80); + Notify((char*)pgm_read_word(&aplphanumTitles1[usage - 0x1f]), 0x80); else if (usage > 0x7f && usage < 0x96) - Notify((char*) pgm_read_word(&digitTitles2[usage - 0x80]), 0x80); + Notify((char*)pgm_read_word(&digitTitles2[usage - 0x80]), 0x80); else Notify(pstrUsagePageUndefined, 0x80); } @@ -1450,17 +1450,17 @@ void ReportDescParserBase::PrintMedicalInstrumentPageUsage(uint16_t usage) { if (usage == 1) Notify(pstrUsageMedicalUltrasound, 0x80); else if (usage > 0x1f && usage < 0x28) - Notify((char*) pgm_read_word(&medInstrTitles0[usage - 0x1f]), 0x80); + Notify((char*)pgm_read_word(&medInstrTitles0[usage - 0x1f]), 0x80); else if (usage > 0x3f && usage < 0x45) - Notify((char*) pgm_read_word(&medInstrTitles1[usage - 0x40]), 0x80); + Notify((char*)pgm_read_word(&medInstrTitles1[usage - 0x40]), 0x80); else if (usage > 0x5f && usage < 0x62) - Notify((char*) pgm_read_word(&medInstrTitles2[usage - 0x60]), 0x80); + Notify((char*)pgm_read_word(&medInstrTitles2[usage - 0x60]), 0x80); else if (usage == 0x70) Notify(pstrUsageDepthGainCompensation, 0x80); else if (usage > 0x7f && usage < 0x8a) - Notify((char*) pgm_read_word(&medInstrTitles3[usage - 0x80]), 0x80); + Notify((char*)pgm_read_word(&medInstrTitles3[usage - 0x80]), 0x80); else if (usage > 0x9f && usage < 0xa2) - Notify((char*) pgm_read_word(&medInstrTitles4[usage - 0xa0]), 0x80); + Notify((char*)pgm_read_word(&medInstrTitles4[usage - 0xa0]), 0x80); else Notify(pstrUsagePageUndefined, 0x80); } @@ -1497,13 +1497,13 @@ uint8_t ReportDescParser2::ParseItem(uint8_t **pp, uint16_t *pcntdn) { itemParseState = 3; case 3: { - uint8_t data = *((uint8_t*) varBuffer); + uint8_t data = *((uint8_t*)varBuffer); switch (itemPrefix & (TYPE_MASK | TAG_MASK)) { case (TYPE_LOCAL | TAG_LOCAL_USAGE): if (pfUsage) { if (theBuffer.valueSize > 1) - pfUsage(*((uint16_t*) varBuffer)); + pfUsage(*((uint16_t*)varBuffer)); else pfUsage(data); } @@ -1536,7 +1536,7 @@ uint8_t ReportDescParser2::ParseItem(uint8_t **pp, uint16_t *pcntdn) { case (TYPE_MAIN | TAG_MAIN_INPUT): OnInputItem(data); - totalSize += (uint16_t) rptSize * (uint16_t) rptCount; + totalSize += (uint16_t)rptSize * (uint16_t)rptCount; rptSize = 0; rptCount = 0; diff --git a/hidescriptorparser.h b/hidescriptorparser.h index 407f6c7e..1c4a1900 100644 --- a/hidescriptorparser.h +++ b/hidescriptorparser.h @@ -119,7 +119,7 @@ protected: MultiValueBuffer theBuffer; MultiByteValueParser valParser; ByteSkipper theSkipper; - uint8_t varBuffer[sizeof (USB_CONFIGURATION_DESCRIPTOR)]; + uint8_t varBuffer[sizeof(USB_CONFIGURATION_DESCRIPTOR)]; uint8_t itemParseState; // Item parser state variable uint8_t itemSize; // Item size diff --git a/hiduniversal.cpp b/hiduniversal.cpp index 9cdb8f66..2ae0ba3c 100644 --- a/hiduniversal.cpp +++ b/hiduniversal.cpp @@ -112,7 +112,7 @@ uint8_t HIDUniversal::Init(uint8_t parent, uint8_t port, bool lowspeed) { p->lowspeed = lowspeed; // Get device descriptor - rcode = pUsb->getDevDescr(0, 0, 8, (uint8_t*) buf); + rcode = pUsb->getDevDescr(0, 0, 8, (uint8_t*)buf); if (!rcode) len = (buf[0] > constBufSize) ? constBufSize : buf[0]; @@ -134,7 +134,7 @@ uint8_t HIDUniversal::Init(uint8_t parent, uint8_t port, bool lowspeed) { return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; // Extract Max Packet Size from the device descriptor - epInfo[0].maxPktSize = (uint8_t) ((USB_DEVICE_DESCRIPTOR*) buf)->bMaxPacketSize0; + epInfo[0].maxPktSize = (uint8_t)((USB_DEVICE_DESCRIPTOR*)buf)->bMaxPacketSize0; // Assign new address to the device rcode = pUsb->setAddr(0, 0, bAddress); @@ -159,12 +159,12 @@ uint8_t HIDUniversal::Init(uint8_t parent, uint8_t port, bool lowspeed) { p->lowspeed = lowspeed; if (len) - rcode = pUsb->getDevDescr(bAddress, 0, len, (uint8_t*) buf); + rcode = pUsb->getDevDescr(bAddress, 0, len, (uint8_t*)buf); if (rcode) goto FailGetDevDescr; - num_of_conf = ((USB_DEVICE_DESCRIPTOR*) buf)->bNumConfigurations; + num_of_conf = ((USB_DEVICE_DESCRIPTOR*)buf)->bNumConfigurations; // Assign epInfo to epinfo pointer rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); @@ -287,7 +287,7 @@ void HIDUniversal::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint if (index) { // Fill in the endpoint info structure epInfo[bNumEP].epAddr = (pep->bEndpointAddress & 0x0F); - epInfo[bNumEP].maxPktSize = (uint8_t) pep->wMaxPacketSize; + epInfo[bNumEP].maxPktSize = (uint8_t)pep->wMaxPacketSize; epInfo[bNumEP].epAttribs = 0; epInfo[bNumEP].bmNakPower = USB_NAK_NOWAIT; @@ -339,7 +339,7 @@ uint8_t HIDUniversal::Poll() { for (uint8_t i = 0; i < bNumIface; i++) { uint8_t index = hidInterfaces[i].epIndex[epInterruptInIndex]; - uint16_t read = (uint16_t) epInfo[index].maxPktSize; + uint16_t read = (uint16_t)epInfo[index].maxPktSize; ZeroMemory(constBuffLen, buf); @@ -371,7 +371,7 @@ uint8_t HIDUniversal::Poll() { HIDReportParser *prs = GetReportParser(((bHasReportId) ? *buf : 0)); if (prs) - prs->Parse(this, bHasReportId, (uint8_t) read, buf); + prs->Parse(this, bHasReportId, (uint8_t)read, buf); } } return rcode; diff --git a/masstorage.cpp b/masstorage.cpp index 1fca5f55..dde10114 100644 --- a/masstorage.cpp +++ b/masstorage.cpp @@ -82,7 +82,7 @@ uint8_t BulkOnly::Init(uint8_t parent, uint8_t port, bool lowspeed) { p->lowspeed = lowspeed; // Get device descriptor - rcode = pUsb->getDevDescr(0, 0, constBufSize, (uint8_t*) buf); + rcode = pUsb->getDevDescr(0, 0, constBufSize, (uint8_t*)buf); // Restore p->epinfo p->epinfo = oldep_ptr; @@ -97,7 +97,7 @@ uint8_t BulkOnly::Init(uint8_t parent, uint8_t port, bool lowspeed) { return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; // Extract Max Packet Size from the device descriptor - epInfo[0].maxPktSize = (uint8_t) ((USB_DEVICE_DESCRIPTOR*) buf)->bMaxPacketSize0; + epInfo[0].maxPktSize = (uint8_t)((USB_DEVICE_DESCRIPTOR*)buf)->bMaxPacketSize0; // Assign new address to the device rcode = pUsb->setAddr(0, 0, bAddress); @@ -121,7 +121,7 @@ uint8_t BulkOnly::Init(uint8_t parent, uint8_t port, bool lowspeed) { p->lowspeed = lowspeed; - num_of_conf = ((USB_DEVICE_DESCRIPTOR*) buf)->bNumConfigurations; + num_of_conf = ((USB_DEVICE_DESCRIPTOR*)buf)->bNumConfigurations; // Assign epInfo to epinfo pointer rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); @@ -220,7 +220,7 @@ uint8_t BulkOnly::Init(uint8_t parent, uint8_t port, bool lowspeed) { PrintHex (capacity.data[i], 0x80); Notify(PSTR("\r\n\r\n"), 0x80); // Only 512/1024/2048/4096 are valid values! - uint32_t c = ((uint32_t) capacity.data[4] << 24) + ((uint32_t) capacity.data[5] << 16) + ((uint32_t) capacity.data[6] << 8) + (uint32_t) capacity.data[7]; + uint32_t c = ((uint32_t)capacity.data[4] << 24) + ((uint32_t)capacity.data[5] << 16) + ((uint32_t)capacity.data[6] << 8) + (uint32_t)capacity.data[7]; if (c != 0x0200LU && c != 0x0400LU && c != 0x0800LU && c != 0x1000LU) { rcode = 255; goto FailInvalidSectorSize; @@ -354,7 +354,7 @@ void BulkOnly::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t // Fill in the endpoint info structure epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F); - epInfo[index].maxPktSize = (uint8_t) pep->wMaxPacketSize; + epInfo[index].maxPktSize = (uint8_t)pep->wMaxPacketSize; epInfo[index].epAttribs = 0; bNumEP++; @@ -611,7 +611,7 @@ uint8_t BulkOnly::Read(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t block cbw.dCBWSignature = MASS_CBW_SIGNATURE; cbw.dCBWTag = ++dCBWTag; - cbw.dCBWDataTransferLength = ((uint32_t) bsize * blocks); + cbw.dCBWDataTransferLength = ((uint32_t)bsize * blocks); cbw.bmCBWFlags = MASS_CMD_DIR_IN, cbw.bmCBWLUN = lun; cbw.bmCBWCBLength = 10; @@ -638,7 +638,7 @@ uint8_t BulkOnly::Read(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t block cbw.dCBWSignature = MASS_CBW_SIGNATURE; cbw.dCBWTag = ++dCBWTag; - cbw.dCBWDataTransferLength = ((uint32_t) bsize * blocks); + cbw.dCBWDataTransferLength = ((uint32_t)bsize * blocks); cbw.bmCBWFlags = MASS_CMD_DIR_IN, cbw.bmCBWLUN = lun; cbw.bmCBWCBLength = 10; @@ -666,7 +666,7 @@ uint8_t BulkOnly::Write(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t bloc cbw.dCBWSignature = MASS_CBW_SIGNATURE; cbw.dCBWTag = ++dCBWTag; - cbw.dCBWDataTransferLength = ((uint32_t) bsize * blocks); + cbw.dCBWDataTransferLength = ((uint32_t)bsize * blocks); cbw.bmCBWFlags = MASS_CMD_DIR_OUT, cbw.bmCBWLUN = lun; cbw.bmCBWCBLength = 10; @@ -681,7 +681,7 @@ uint8_t BulkOnly::Write(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t bloc cbw.CBWCB[3] = ((addr >> 16) & 0xff); cbw.CBWCB[2] = ((addr >> 24) & 0xff); - return HandleSCSIError(Transaction(&cbw, bsize, (void*) buf, 0)); + return HandleSCSIError(Transaction(&cbw, bsize, (void*)buf, 0)); } uint8_t BulkOnly::ModeSense(uint8_t lun, uint8_t pc, uint8_t page, uint8_t subpage, uint8_t len, uint8_t *pbuf) { @@ -714,7 +714,7 @@ uint8_t BulkOnly::Transaction(CommandBlockWrapper *pcbw, uint16_t buf_size, void ErrorMessage (PSTR("CBW.dCBWTag"), pcbw->dCBWTag); - ret = HandleUsbError(pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, sizeof (CommandBlockWrapper), (uint8_t*) pcbw), epDataOutIndex); + ret = HandleUsbError(pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, sizeof (CommandBlockWrapper), (uint8_t*)pcbw), epDataOutIndex); if (ret) { ErrorMessage (PSTR("CBW"), ret); @@ -732,16 +732,16 @@ uint8_t BulkOnly::Transaction(CommandBlockWrapper *pcbw, uint16_t buf_size, void uint8_t rbuf[read]; uint8_t err = 0; ret = pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, &read, rbuf); - if (ret == hrSUCCESS) ((USBReadParser*) buf)->Parse(read, rbuf, 0); + if (ret == hrSUCCESS) ((USBReadParser*)buf)->Parse(read, rbuf, 0); if (ret == hrSTALL) err = ClearEpHalt(epDataInIndex); if (ret) { ErrorMessage (PSTR("RDR"), err); return MASS_ERR_GENERAL_USB_ERROR; } } else - ret = pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, &read, (uint8_t*) buf); + ret = pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, &read, (uint8_t*)buf); } else - ret = pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, read, (uint8_t*) buf); + ret = pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, read, (uint8_t*)buf); ret = HandleUsbError(ret, (pcbw->bmCBWFlags & MASS_CMD_DIR_IN) ? epDataInIndex : epDataOutIndex); @@ -798,7 +798,7 @@ uint8_t BulkOnly::HandleSCSIError(uint8_t status) { switch (status) { case 0: return MASS_ERR_SUCCESS; - //case 4: return MASS_ERR_UNIT_BUSY; + //case 4: return MASS_ERR_UNIT_BUSY; case 2: ErrorMessage (PSTR("Phase"), status); ResetRecovery(); diff --git a/masstorage.h b/masstorage.h index de16d12b..c30f4ae6 100644 --- a/masstorage.h +++ b/masstorage.h @@ -104,7 +104,7 @@ struct Capacity { uint8_t data[8]; //uint32_t dwBlockAddress; //uint32_t dwBlockLength; -}__attribute__((packed)); +} __attribute__((packed)); struct InquiryResponse { uint8_t DeviceType : 5; @@ -136,14 +136,14 @@ struct InquiryResponse { uint8_t VendorID[8]; uint8_t ProductID[16]; uint8_t RevisionID[4]; -}__attribute__((packed)); +} __attribute__((packed)); struct CommandBlockWrapperBase { uint32_t dCBWSignature; uint32_t dCBWTag; uint32_t dCBWDataTransferLength; uint8_t bmCBWFlags; -}__attribute__((packed)); +} __attribute__((packed)); struct CommandBlockWrapper : public CommandBlockWrapperBase { @@ -158,14 +158,14 @@ struct CommandBlockWrapper : public CommandBlockWrapperBase { }; uint8_t CBWCB[16]; -}__attribute__((packed)); +} __attribute__((packed)); struct CommandStatusWrapper { uint32_t dCSWSignature; uint32_t dCSWTag; uint32_t dCSWDataResidue; uint8_t bCSWStatus; -}__attribute__((packed)); +} __attribute__((packed)); struct RequestSenseResponce { uint8_t bResponseCode; @@ -184,7 +184,7 @@ struct RequestSenseResponce { uint8_t bAdditionalSenseQualifier; uint8_t bFieldReplaceableUnitCode; uint8_t SenseKeySpecific[3]; -}__attribute__((packed)); +} __attribute__((packed)); #define MASS_MAX_ENDPOINTS 3 diff --git a/parsetools.cpp b/parsetools.cpp index 469c3c8e..c302dd2a 100644 --- a/parsetools.cpp +++ b/parsetools.cpp @@ -43,7 +43,7 @@ bool PTPListParser::Parse(uint8_t **pp, uint16_t *pcntdn, PTP_ARRAY_EL_FUNC pf, return false; arLen = 0; - arLen = (pBuf->valueSize >= 4) ? *((uint32_t*) pBuf->pValue) : (uint32_t) (*((uint16_t*) pBuf->pValue)); + arLen = (pBuf->valueSize >= 4) ? *((uint32_t*)pBuf->pValue) : (uint32_t)(*((uint16_t*)pBuf->pValue)); arLenCntdn = arLen; nStage = 2; diff --git a/parsetools.h b/parsetools.h index 9fc9568c..59402df2 100644 --- a/parsetools.h +++ b/parsetools.h @@ -32,7 +32,7 @@ e-mail : support@circuitsathome.com struct MultiValueBuffer { uint8_t valueSize; void *pValue; -}__attribute__((packed)); +} __attribute__((packed)); class MultiByteValueParser { uint8_t * pBuf; @@ -72,17 +72,17 @@ public: }; bool Skip(uint8_t **pp, uint16_t *pcntdn, uint16_t bytes_to_skip) { - switch (nStage) { + switch(nStage) { case 0: countDown = bytes_to_skip; nStage++; case 1: - for (; countDown && (*pcntdn); countDown--, (*pp)++, (*pcntdn)--); + for(; countDown && (*pcntdn); countDown--, (*pp)++, (*pcntdn)--); - if (!countDown) + if(!countDown) nStage = 0; }; - return (!countDown); + return(!countDown); }; }; @@ -132,7 +132,7 @@ public: valSize = val_size; prsMode = mode; - if (prsMode == modeRange) { + if(prsMode == modeRange) { arLenCntdn = arLen = 3; nStage = 2; } else { diff --git a/printhex.h b/printhex.h index 262286c0..4a303884 100644 --- a/printhex.h +++ b/printhex.h @@ -26,19 +26,19 @@ void Notifyc(char c, int lvl); template void PrintHex(T val, int lvl) { - int num_nibbles = sizeof (T) * 2; + int num_nibbles = sizeof(T) * 2; do { char v = 48 + (((val >> (num_nibbles - 1) * 4)) & 0x0f); - if (v > 57) v += 7; + if(v > 57) v += 7; Notifyc(v, lvl); - } while (--num_nibbles); + } while(--num_nibbles); } template void PrintBin(T val, int lvl) { - for (T mask = (((T) 1) << ((sizeof (T) << 3) - 1)); mask; mask >>= 1) - if (val & mask) + for(T mask = (((T) 1) << ((sizeof(T) << 3) - 1)); mask; mask >>= 1) + if(val & mask) Notifyc('1', lvl); else Notifyc('0', lvl); @@ -46,21 +46,21 @@ void PrintBin(T val, int lvl) { template void SerialPrintHex(T val) { - int num_nibbles = sizeof (T) * 2; + int num_nibbles = sizeof(T) * 2; do { char v = 48 + (((val >> (num_nibbles - 1) * 4)) & 0x0f); - if (v > 57) v += 7; + if(v > 57) v += 7; Serial.print(v); - } while (--num_nibbles); + } while(--num_nibbles); } template 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) { - if (val < mask) + while(mask > 1) { + if(val < mask) prn->print("0"); mask >>= 4; diff --git a/usb_ch9.h b/usb_ch9.h index 9a8d3c99..dd854f5c 100644 --- a/usb_ch9.h +++ b/usb_ch9.h @@ -108,7 +108,7 @@ typedef struct { 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 bNumConfigurations; // Number of possible configurations. -}__attribute__((packed)) USB_DEVICE_DESCRIPTOR; +} __attribute__((packed)) USB_DEVICE_DESCRIPTOR; /* Configuration descriptor structure */ typedef struct { @@ -120,7 +120,7 @@ typedef struct { uint8_t iConfiguration; // Index of String Descriptor describing the configuration. uint8_t bmAttributes; // Configuration characteristics. uint8_t bMaxPower; // Maximum power consumed by this configuration. -}__attribute__((packed)) USB_CONFIGURATION_DESCRIPTOR; +} __attribute__((packed)) USB_CONFIGURATION_DESCRIPTOR; /* Interface descriptor structure */ typedef struct { @@ -133,7 +133,7 @@ typedef struct { 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 iInterface; // Index of String Descriptor describing the interface. -}__attribute__((packed)) USB_INTERFACE_DESCRIPTOR; +} __attribute__((packed)) USB_INTERFACE_DESCRIPTOR; /* Endpoint descriptor structure */ typedef struct { @@ -143,7 +143,7 @@ typedef struct { uint8_t bmAttributes; // Endpoint transfer type. uint16_t wMaxPacketSize; // Maximum packet size. uint8_t bInterval; // Polling interval in frames. -}__attribute__((packed)) USB_ENDPOINT_DESCRIPTOR; +} __attribute__((packed)) USB_ENDPOINT_DESCRIPTOR; /* HID descriptor */ typedef struct { @@ -154,11 +154,11 @@ typedef struct { uint8_t bNumDescriptors; // Number of additional class specific descriptors uint8_t bDescrType; // Type of class descriptor uint16_t wDescriptorLength; // Total size of the Report descriptor -}__attribute__((packed)) USB_HID_DESCRIPTOR; +} __attribute__((packed)) USB_HID_DESCRIPTOR; typedef struct { uint8_t bDescrType; // Type of class descriptor uint16_t wDescriptorLength; // Total size of the Report descriptor -}__attribute__((packed)) HID_CLASS_DESCRIPTOR_LEN_AND_TYPE; +} __attribute__((packed)) HID_CLASS_DESCRIPTOR_LEN_AND_TYPE; #endif // _ch9_h_ diff --git a/usbhost.h b/usbhost.h index 95b87a48..2dd60a06 100644 --- a/usbhost.h +++ b/usbhost.h @@ -96,9 +96,9 @@ template< typename SS, typename INTR > void MAX3421e< SS, INTR >::regWr(uint8_t reg, uint8_t data) { SS::Clear(); SPDR = (reg | 0x02); - while (!(SPSR & (1 << SPIF))); + while(!(SPSR & (1 << SPIF))); SPDR = data; - while (!(SPSR & (1 << SPIF))); + while(!(SPSR & (1 << SPIF))); SS::Set(); return; }; @@ -109,14 +109,14 @@ template< typename SS, typename INTR > uint8_t* MAX3421e< SS, INTR >::bytesWr(uint8_t reg, uint8_t nbytes, uint8_t* data_p) { SS::Clear(); SPDR = (reg | 0x02); //set WR bit and send register number - while (nbytes--) { - while (!(SPSR & (1 << SPIF))); //check if previous byte was sent + while(nbytes--) { + while(!(SPSR & (1 << SPIF))); //check if previous byte was sent SPDR = (*data_p); // send next data byte data_p++; // advance data pointer } - while (!(SPSR & (1 << SPIF))); + while(!(SPSR & (1 << SPIF))); SS::Set(); - return ( data_p); + return( data_p); } /* GPIO write */ /*GPIO byte is split between 2 registers, so two writes are needed to write one byte */ @@ -135,11 +135,11 @@ template< typename SS, typename INTR > uint8_t MAX3421e< SS, INTR >::regRd(uint8_t reg) { SS::Clear(); SPDR = reg; - while (!(SPSR & (1 << SPIF))); + while(!(SPSR & (1 << SPIF))); SPDR = 0; //send empty byte - while (!(SPSR & (1 << SPIF))); + while(!(SPSR & (1 << SPIF))); SS::Set(); - return ( SPDR); + return( SPDR); } /* multiple-byte register read */ @@ -148,16 +148,16 @@ template< typename SS, typename INTR > uint8_t* MAX3421e< SS, INTR >::bytesRd(uint8_t reg, uint8_t nbytes, uint8_t* data_p) { SS::Clear(); SPDR = reg; - while (!(SPSR & (1 << SPIF))); //wait - while (nbytes) { + while(!(SPSR & (1 << SPIF))); //wait + while(nbytes) { SPDR = 0; //send empty byte nbytes--; - while (!(SPSR & (1 << SPIF))); + while(!(SPSR & (1 << SPIF))); *data_p = SPDR; data_p++; } SS::Set(); - return ( data_p); + return( data_p); } /* GPIO read. See gpioWr for explanation */ @@ -168,7 +168,7 @@ uint8_t MAX3421e< SS, INTR >::gpioRd() { gpin = regRd(rIOPINS2); //pins 4-7 gpin &= 0xf0; //clean lower nibble 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 @@ -178,12 +178,12 @@ uint16_t MAX3421e< SS, INTR >::reset() { uint16_t i = 0; regWr(rUSBCTL, bmCHIPRES); regWr(rUSBCTL, 0x00); - while (++i) { - if ((regRd(rUSBIRQ) & bmOSCOKIRQ)) { + while(++i) { + if((regRd(rUSBIRQ) & bmOSCOKIRQ)) { break; } } - return ( i); + return( i); } ///* initialize MAX3421E. Set Host mode, pullups, and stuff. Returns 0 if success, -1 if not */ //template< typename SS, typename INTR > @@ -200,8 +200,8 @@ uint16_t MAX3421e< SS, INTR >::reset() { /* initialize MAX3421E. Set Host mode, pullups, and stuff. Returns 0 if success, -1 if not */ template< typename SS, typename INTR > int8_t MAX3421e< SS, INTR >::Init() { - if (reset() == 0) { //OSCOKIRQ hasn't asserted in time - return ( -1); + if(reset() == 0) { //OSCOKIRQ hasn't asserted in time + return( -1); } regWr(rMODE, bmDPPULLDN | bmDMPULLDN | bmHOST); // set pull-downs, Host @@ -209,13 +209,13 @@ int8_t MAX3421e< SS, INTR >::Init() { /* check if device is connected */ regWr(rHCTL, bmSAMPLEBUS); // sample USB bus - while (!(regRd(rHCTL) & bmSAMPLEBUS)); //wait for sample operation to finish + while(!(regRd(rHCTL) & bmSAMPLEBUS)); //wait for sample operation to finish busprobe(); //check if anything is connected regWr(rHIRQ, bmCONDETIRQ); //clear connection detect interrupt regWr(rCPUCTL, 0x01); //enable interrupt pin - return ( 0); + return( 0); } /* probe bus to determine device presence and speed and switch host to this speed */ @@ -224,9 +224,9 @@ void MAX3421e< SS, INTR >::busprobe() { uint8_t bus_sample; bus_sample = regRd(rHRSL); //Get J,K status bus_sample &= (bmJSTATUS | bmKSTATUS); //zero the rest of the byte - switch (bus_sample) { //start full-speed or low-speed host + switch(bus_sample) { //start full-speed or low-speed host case( bmJSTATUS): - if ((regRd(rMODE) & bmLOWSPEED) == 0) { + if((regRd(rMODE) & bmLOWSPEED) == 0) { regWr(rMODE, MODE_FS_HOST); //start full-speed host vbusState = FSHOST; } else { @@ -235,7 +235,7 @@ void MAX3421e< SS, INTR >::busprobe() { } break; case( bmKSTATUS): - if ((regRd(rMODE) & bmLOWSPEED) == 0) { + if((regRd(rMODE) & bmLOWSPEED) == 0) { regWr(rMODE, MODE_LS_HOST); //start low-speed host vbusState = LSHOST; } else { @@ -262,7 +262,7 @@ uint8_t MAX3421e< SS, INTR >::Task(void) { //Serial.println( vbusState, HEX ); pinvalue = INTR::IsSet(); //Read(); //pinvalue = digitalRead( MAX_INT ); - if (pinvalue == 0) { + if(pinvalue == 0) { rcode = IntHandler(); } // pinvalue = digitalRead( MAX_GPX ); @@ -270,7 +270,7 @@ uint8_t MAX3421e< SS, INTR >::Task(void) { // GpxHandler(); // } // usbSM(); //USB state machine - return ( rcode); + return( rcode); } template< typename SS, typename INTR > @@ -281,13 +281,13 @@ uint8_t MAX3421e< SS, INTR >::IntHandler() { //if( HIRQ & bmFRAMEIRQ ) { //->1ms SOF interrupt handler // HIRQ_sendback |= bmFRAMEIRQ; //}//end FRAMEIRQ handling - if (HIRQ & bmCONDETIRQ) { + if(HIRQ & bmCONDETIRQ) { busprobe(); HIRQ_sendback |= bmCONDETIRQ; } /* End HIRQ interrupts handling, clear serviced IRQs */ regWr(rHIRQ, HIRQ_sendback); - return ( HIRQ_sendback); + return( HIRQ_sendback); } //template< typename SS, typename INTR > //uint8_t MAX3421e< SS, INTR >::GpxHandler() diff --git a/usbhub.cpp b/usbhub.cpp index 7693c2c7..52e20cfb 100644 --- a/usbhub.cpp +++ b/usbhub.cpp @@ -74,7 +74,7 @@ uint8_t USBHub::Init(uint8_t parent, uint8_t port, bool lowspeed) { p->lowspeed = lowspeed; // Get device descriptor - rcode = pUsb->getDevDescr(0, 0, 8, (uint8_t*) buf); + rcode = pUsb->getDevDescr(0, 0, 8, (uint8_t*)buf); p->lowspeed = false; @@ -89,17 +89,17 @@ uint8_t USBHub::Init(uint8_t parent, uint8_t port, bool lowspeed) { // Extract device class from device descriptor // If device class is not a hub return - if (((USB_DEVICE_DESCRIPTOR*) buf)->bDeviceClass != 0x09) + if (((USB_DEVICE_DESCRIPTOR*)buf)->bDeviceClass != 0x09) return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; // Allocate new address according to device class - bAddress = addrPool.AllocAddress(parent, (((USB_DEVICE_DESCRIPTOR*) buf)->bDeviceClass == 0x09) ? true : false, port); + bAddress = addrPool.AllocAddress(parent, (((USB_DEVICE_DESCRIPTOR*)buf)->bDeviceClass == 0x09) ? true : false, port); if (!bAddress) return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; // Extract Max Packet Size from the device descriptor - epInfo[0].maxPktSize = ((USB_DEVICE_DESCRIPTOR*) buf)->bMaxPacketSize0; + epInfo[0].maxPktSize = ((USB_DEVICE_DESCRIPTOR*)buf)->bMaxPacketSize0; // Assign new address to the device rcode = pUsb->setAddr(0, 0, bAddress); @@ -118,7 +118,7 @@ uint8_t USBHub::Init(uint8_t parent, uint8_t port, bool lowspeed) { p->epinfo = oldep_ptr; if (len) - rcode = pUsb->getDevDescr(bAddress, 0, len, (uint8_t*) buf); + rcode = pUsb->getDevDescr(bAddress, 0, len, (uint8_t*)buf); if (rcode) goto FailGetDevDescr; @@ -139,7 +139,7 @@ uint8_t USBHub::Init(uint8_t parent, uint8_t port, bool lowspeed) { goto FailGetHubDescr; // Save number of ports for future use - bNbrPorts = ((HubDescriptor*) buf)->bNbrPorts; + bNbrPorts = ((HubDescriptor*)buf)->bNbrPorts; bInitState = 2; @@ -148,7 +148,7 @@ uint8_t USBHub::Init(uint8_t parent, uint8_t port, bool lowspeed) { rcode = pUsb->getConfDescr(bAddress, 0, 8, 0, buf); 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); } if (rcode) diff --git a/usbhub.h b/usbhub.h index 98a8ed7a..0150c4b3 100644 --- a/usbhub.h +++ b/usbhub.h @@ -155,11 +155,11 @@ struct HubDescriptor { uint16_t TTThinkTime : 2; uint16_t PortIndicatorsSupported : 1; uint16_t Reserved : 8; - }__attribute__((packed)); + } __attribute__((packed)); uint8_t bPwrOn2PwrGood; uint8_t bHubContrCurrent; -}__attribute__((packed)); +} __attribute__((packed)); struct HubEvent { @@ -168,11 +168,11 @@ struct HubEvent { struct { uint16_t bmStatus; // port status bits uint16_t bmChange; // port status change bits - }__attribute__((packed)); + } __attribute__((packed)); uint32_t bmEvent; uint8_t evtBuff[4]; }; -}__attribute__((packed)); +} __attribute__((packed)); class USBHub : USBDeviceConfig { static bool bResetInitiated; // True when reset is triggered @@ -216,42 +216,42 @@ public: // Clear Hub Feature 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 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 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 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 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 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 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 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)); } void PrintHubPortStatus(USB *usbptr, uint8_t addr, uint8_t port, bool print_changes = false); diff --git a/xboxEnums.h b/xboxEnums.h index d66956f0..adf60f9b 100644 --- a/xboxEnums.h +++ b/xboxEnums.h @@ -1,15 +1,15 @@ /* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved. - + This software may be distributed and modified under the terms of the GNU General Public License version 2 (GPL2) as published by the Free Software Foundation and appearing in the file GPL2.TXT included in the packaging of this file. Please note that GPL2 Section 2[b] requires that all works based on this software must also be made publicly available under the terms of the GPL2 ("Copyleft"). - + Contact information ------------------- - + Kristian Lauszus, TKJ Electronics Web : http://www.tkjelectronics.com e-mail : kristianl@tkjelectronics.com @@ -22,43 +22,43 @@ /** Enum used to set special LED modes supported by the Xbox controller. */ enum LEDMode { - ROTATING = 0x0A, - FASTBLINK = 0x0B, - SLOWBLINK = 0x0C, - ALTERNATING = 0x0D, + ROTATING = 0x0A, + FASTBLINK = 0x0B, + SLOWBLINK = 0x0C, + ALTERNATING = 0x0D, }; /** Used to set the LEDs on the controllers */ const uint8_t XBOXLEDS[] PROGMEM = { - 0x02, // LED1 - 0x03, // LED2 - 0x04, // LED3 - 0x05, // LED4 - 0x01 // ALL - Used to blink all LEDs - }; -/** Buttons on the controllers */ + 0x02, // LED1 + 0x03, // LED2 + 0x04, // LED3 + 0x05, // LED4 + 0x01 // ALL - Used to blink all LEDs +}; +/** Buttons on the controllers */ const uint16_t XBOXBUTTONS[] PROGMEM = { - 0x0100, // UP - 0x0800, // RIGHT - 0x0200, // DOWN - 0x0400, // LEFT + 0x0100, // UP + 0x0800, // RIGHT + 0x0200, // DOWN + 0x0400, // LEFT - 0x2000, // BACK - 0x1000, // START - 0x4000, // L3 - 0x8000, // R3 + 0x2000, // BACK + 0x1000, // START + 0x4000, // L3 + 0x8000, // R3 - 0,0, // Skip L2 and R2 as these are analog buttons - 0x0001, // L1 - 0x0002, // R1 + 0, 0, // Skip L2 and R2 as these are analog buttons + 0x0001, // L1 + 0x0002, // R1 - 0x0020, // B - 0x0010, // A - 0x0040, // X - 0x0080, // Y + 0x0020, // B + 0x0010, // A + 0x0040, // X + 0x0080, // Y - 0x0004, // XBOX - 0x0008 // SYNC + 0x0004, // XBOX + 0x0008 // SYNC }; #endif \ No newline at end of file From adff5d790d1f186a59df7c1ef3302665eaf31b16 Mon Sep 17 00:00:00 2001 From: Kevin Mark Date: Sat, 30 Mar 2013 00:54:13 -0400 Subject: [PATCH 4/7] Overloaded PS3BT/PS3USB's setRumbleOn to accept custom rumble settings. --- PS3BT.cpp | 8 +- PS3BT.h | 284 +++++++++++++++++++++-------------------- PS3USB.cpp | 8 +- PS3USB.h | 364 +++++++++++++++++++++++++++-------------------------- 4 files changed, 343 insertions(+), 321 deletions(-) diff --git a/PS3BT.cpp b/PS3BT.cpp index 1912808c..d957a666 100644 --- a/PS3BT.cpp +++ b/PS3BT.cpp @@ -608,7 +608,13 @@ void PS3BT::setRumbleOn(Rumble mode) { HID_Command(HIDBuffer, HID_BUFFERSIZE); } } - +void PS3BT::setRumbleOn(uint8_t rightDuration, uint8_t rightPower, uint8_t leftDuration, uint8_t leftPower) { + HIDBuffer[3] = rightDuration; + HIDBuffer[4] = rightPower; + HIDBuffer[5] = leftDuration; + HIDBuffer[6] = leftPower; + HID_Command(HIDBuffer, HID_BUFFERSIZE); +} void PS3BT::setLedOff(LED a) { HIDBuffer[11] &= ~((uint8_t)((pgm_read_byte(&LEDS[(uint8_t)a]) & 0x0f) << 1)); HID_Command(HIDBuffer, HID_BUFFERSIZE); diff --git a/PS3BT.h b/PS3BT.h index 4b5ed90f..6b094b00 100644 --- a/PS3BT.h +++ b/PS3BT.h @@ -65,144 +65,152 @@ */ class PS3BT : public BluetoothService { public: - /** - * Constructor for the PS3BT class. - * @param pBtd Pointer to BTD class instance. - * @param btadr5,btadr4,btadr3,btadr2,btadr1,btadr0 - * Pass your dongles Bluetooth address into the constructor, - * This will set BTD#my_bdaddr, so you don't have to plug in the dongle before pairing with your controller. - */ - PS3BT(BTD *pBtd, uint8_t btadr5 = 0, uint8_t btadr4 = 0, uint8_t btadr3 = 0, uint8_t btadr2 = 0, uint8_t btadr1 = 0, uint8_t btadr0 = 0); - - /** @name BluetoothService implementation */ - /** - * Used to pass acldata to the services. - * @param ACLData Incoming acldata. - */ - virtual void ACLData(uint8_t* ACLData); - /** Used to run part of the state maschine. */ - virtual void Run(); - /** Use this to reset the service. */ - virtual void Reset(); - /** Used this to disconnect any of the controllers. */ - virtual void disconnect(); - /**@}*/ - - /** @name PS3 Controller functions */ - /** - * getButtonPress(Button b) will return true as long as the button is held down. - * - * While getButtonClick(Button b) will only return it once. - * - * So you instance if you need to increase a variable once you would use getButtonClick(Button b), - * but if you need to drive a robot forward you would use getButtonPress(Button b). - */ - bool getButtonPress(Button b); - bool getButtonClick(Button b); - /**@}*/ - /** @name PS3 Controller functions */ - /** - * Used to get the analog value from button presses. - * @param a The ::Button to read. - * The supported buttons are: - * ::UP, ::RIGHT, ::DOWN, ::LEFT, ::L1, ::L2, ::R1, ::R2, - * ::TRIANGLE, ::CIRCLE, ::CROSS, ::SQUARE, and ::T. - * @return Analog value in the range of 0-255. - */ - uint8_t getAnalogButton(Button a); - /** - * Used to read the analog joystick. - * @param a ::LeftHatX, ::LeftHatY, ::RightHatX, and ::RightHatY. - * @return Return the analog value in the range of 0-255. - */ - uint8_t getAnalogHat(AnalogHat a); - /** - * Used to read the sensors inside the Dualshock 3 and Move controller. - * @param a - * The Dualshock 3 has a 3-axis accelerometer and a 1-axis gyro inside. - * The Move controller has a 3-axis accelerometer, a 3-axis gyro, a 3-axis magnetometer - * and a temperature sensor inside. - * @return Return the raw sensor value. - */ - int16_t getSensor(Sensor a); - /** - * Use this to get ::Pitch and ::Roll calculated using the accelerometer. - * @param a Either ::Pitch or ::Roll. - * @return Return the angle in the range of 0-360. - */ - double getAngle(Angle a); - /** - * Read the sensors inside the Move controller. - * @param a ::aXmove, ::aYmove, ::aZmove, ::gXmove, ::gYmove, ::gZmove, ::mXmove, ::mYmove, and ::mXmove. - * @return The value in SI units. - */ - double get9DOFValues(Sensor a); - /** - * Get the ::Status from the controller. - * @param c The ::Status you want to read. - * @return True if correct and false if not. - */ - bool getStatus(Status c); - /** - * Read all the available ::Status from the controller. - * @return One large string with all the information. - */ - String getStatusString(); - /** - * Read the temperature from the Move controller. - * @return The temperature in degrees celsius. - */ - String getTemperature(); - - /** Used to set all LEDs and ::Rumble off. */ - void setAllOff(); - /** Turn off ::Rumble. */ - void setRumbleOff(); - /** - * Turn on ::Rumble. - * @param mode Either ::RumbleHigh or ::RumbleLow. - */ - void setRumbleOn(Rumble mode); - /** - * Turn the specific ::LED off. - * @param a The ::LED to turn off. - */ - void setLedOff(LED a); - /** - * Turn the specific ::LED on. - * @param a The ::LED to turn on. - */ - void setLedOn(LED a); - /** - * Toggle the specific ::LED. - * @param a The ::LED to toggle. - */ - void setLedToggle(LED a); - - /** - * Use this to set the Color using RGB values. - * @param r,g,b RGB value. - */ - void moveSetBulb(uint8_t r, uint8_t g, uint8_t b); - /** - * Use this to set the color using the predefined colors in ::Colors. - * @param color The desired color. - */ - void moveSetBulb(Colors color); - /** - * Set the rumble value inside the Move controller. - * @param rumble The desired value in the range from 64-255. - */ - void moveSetRumble(uint8_t rumble); - /**@}*/ - - /** Variable used to indicate if the normal playstation controller is successfully connected. */ - bool PS3Connected; - /** Variable used to indicate if the move controller is successfully connected. */ - bool PS3MoveConnected; - /** Variable used to indicate if the navigation controller is successfully connected. */ - bool PS3NavigationConnected; - + /** + * Constructor for the PS3BT class. + * @param pBtd Pointer to BTD class instance. + * @param btadr5,btadr4,btadr3,btadr2,btadr1,btadr0 + * Pass your dongles Bluetooth address into the constructor, + * This will set BTD#my_bdaddr, so you don't have to plug in the dongle before pairing with your controller. + */ + PS3BT(BTD *pBtd, uint8_t btadr5=0, uint8_t btadr4=0, uint8_t btadr3=0, uint8_t btadr2=0, uint8_t btadr1=0, uint8_t btadr0=0); + + /** @name BluetoothService implementation */ + /** + * Used to pass acldata to the services. + * @param ACLData Incoming acldata. + */ + virtual void ACLData(uint8_t* ACLData); + /** Used to run part of the state maschine. */ + virtual void Run(); + /** Use this to reset the service. */ + virtual void Reset(); + /** Used this to disconnect any of the controllers. */ + virtual void disconnect(); + /**@}*/ + + /** @name PS3 Controller functions */ + /** + * getButtonPress(Button b) will return true as long as the button is held down. + * + * While getButtonClick(Button b) will only return it once. + * + * So you instance if you need to increase a variable once you would use getButtonClick(Button b), + * but if you need to drive a robot forward you would use getButtonPress(Button b). + */ + bool getButtonPress(Button b); + bool getButtonClick(Button b); + /**@}*/ + /** @name PS3 Controller functions */ + /** + * Used to get the analog value from button presses. + * @param a The ::Button to read. + * The supported buttons are: + * ::UP, ::RIGHT, ::DOWN, ::LEFT, ::L1, ::L2, ::R1, ::R2, + * ::TRIANGLE, ::CIRCLE, ::CROSS, ::SQUARE, and ::T. + * @return Analog value in the range of 0-255. + */ + uint8_t getAnalogButton(Button a); + /** + * Used to read the analog joystick. + * @param a ::LeftHatX, ::LeftHatY, ::RightHatX, and ::RightHatY. + * @return Return the analog value in the range of 0-255. + */ + uint8_t getAnalogHat(AnalogHat a); + /** + * Used to read the sensors inside the Dualshock 3 and Move controller. + * @param a + * The Dualshock 3 has a 3-axis accelerometer and a 1-axis gyro inside. + * The Move controller has a 3-axis accelerometer, a 3-axis gyro, a 3-axis magnetometer + * and a temperature sensor inside. + * @return Return the raw sensor value. + */ + int16_t getSensor(Sensor a); + /** + * Use this to get ::Pitch and ::Roll calculated using the accelerometer. + * @param a Either ::Pitch or ::Roll. + * @return Return the angle in the range of 0-360. + */ + double getAngle(Angle a); + /** + * Read the sensors inside the Move controller. + * @param a ::aXmove, ::aYmove, ::aZmove, ::gXmove, ::gYmove, ::gZmove, ::mXmove, ::mYmove, and ::mXmove. + * @return The value in SI units. + */ + double get9DOFValues(Sensor a); + /** + * Get the ::Status from the controller. + * @param c The ::Status you want to read. + * @return True if correct and false if not. + */ + bool getStatus(Status c); + /** + * Read all the available ::Status from the controller. + * @return One large string with all the information. + */ + String getStatusString(); + /** + * Read the temperature from the Move controller. + * @return The temperature in degrees celsius. + */ + String getTemperature(); + + /** Used to set all LEDs and ::Rumble off. */ + void setAllOff(); + /** Turn off ::Rumble. */ + void setRumbleOff(); + /** + * Turn on ::Rumble. + * @param mode Either ::RumbleHigh or ::RumbleLow. + */ + void setRumbleOn(Rumble mode); + /** + * Turn on ::Rumble using custom duration and power. + * @param rightDuration The duration of the right/low rumble effect. + * @param rightPower The intensity of the right/low rumble effect. + * @param leftDuration The duration of the left/high rumble effect. + * @param leftPower The intensity of the left/high rumble effect. + */ + void setRumbleOn(uint8_t rightDuration, uint8_t rightPower, uint8_t leftDuration, uint8_t leftPower); + /** + * Turn the specific ::LED off. + * @param a The ::LED to turn off. + */ + void setLedOff(LED a); + /** + * Turn the specific ::LED on. + * @param a The ::LED to turn on. + */ + void setLedOn(LED a); + /** + * Toggle the specific ::LED. + * @param a The ::LED to toggle. + */ + void setLedToggle(LED a); + + /** + * Use this to set the Color using RGB values. + * @param r,g,b RGB value. + */ + void moveSetBulb(uint8_t r, uint8_t g, uint8_t b); + /** + * Use this to set the color using the predefined colors in ::Colors. + * @param color The desired color. + */ + void moveSetBulb(Colors color); + /** + * Set the rumble value inside the Move controller. + * @param rumble The desired value in the range from 64-255. + */ + void moveSetRumble(uint8_t rumble); + /**@}*/ + + /** Variable used to indicate if the normal playstation controller is successfully connected. */ + bool PS3Connected; + /** Variable used to indicate if the move controller is successfully connected. */ + bool PS3MoveConnected; + /** Variable used to indicate if the navigation controller is successfully connected. */ + bool PS3NavigationConnected; + private: /* mandatory members */ BTD *pBtd; diff --git a/PS3USB.cpp b/PS3USB.cpp index a7ca846a..b329e174 100644 --- a/PS3USB.cpp +++ b/PS3USB.cpp @@ -464,7 +464,13 @@ void PS3USB::setRumbleOn(Rumble mode) { PS3_Command(writeBuf, PS3_REPORT_BUFFER_SIZE); } } - +void PS3USB::setRumbleOn(uint8_t rightDuration, uint8_t rightPower, uint8_t leftDuration, uint8_t leftPower) { + writeBuf[1] = rightDuration; + writeBuf[2] = rightPower; + writeBuf[3] = leftDuration; + writeBuf[4] = leftPower; + PS3_Command(writeBuf, PS3_REPORT_BUFFER_SIZE); +} void PS3USB::setLedOff(LED a) { writeBuf[9] &= ~((uint8_t)((pgm_read_byte(&LEDS[(uint8_t)a]) & 0x0f) << 1)); PS3_Command(writeBuf, PS3_REPORT_BUFFER_SIZE); diff --git a/PS3USB.h b/PS3USB.h index adaa47e1..25c00415 100644 --- a/PS3USB.h +++ b/PS3USB.h @@ -63,192 +63,194 @@ */ class PS3USB : public USBDeviceConfig { public: - /** - * Constructor for the PS3USB class. - * @param pUsb Pointer to USB class instance. - * @param btadr5,btadr4,btadr3,btadr2,btadr1,btadr0 - * Pass your dongles Bluetooth address into the constructor, - * so you are able to pair the controller with a Bluetooth dongle. - */ - PS3USB(USB *pUsb, uint8_t btadr5 = 0, uint8_t btadr4 = 0, uint8_t btadr3 = 0, uint8_t btadr2 = 0, uint8_t btadr1 = 0, uint8_t btadr0 = 0); + /** + * Constructor for the PS3USB class. + * @param pUsb Pointer to USB class instance. + * @param btadr5,btadr4,btadr3,btadr2,btadr1,btadr0 + * Pass your dongles Bluetooth address into the constructor, + * so you are able to pair the controller with a Bluetooth dongle. + */ + PS3USB(USB *pUsb, uint8_t btadr5=0, uint8_t btadr4=0, uint8_t btadr3=0, uint8_t btadr2=0, uint8_t btadr1=0, uint8_t btadr0=0); + + /** @name USBDeviceConfig implementation */ + /** + * Initialize the PS3 Controller. + * @param parent Hub number. + * @param port Port number on the hub. + * @param lowspeed Speed of the device. + * @return 0 on success. + */ + virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed); + /** + * Release the USB device. + * @return 0 on success. + */ + virtual uint8_t Release(); + /** + * Poll the USB Input endpoins and run the state machines. + * @return 0 on success. + */ + virtual uint8_t Poll(); + /** + * Get the device address. + * @return The device address. + */ + virtual uint8_t GetAddress() { return bAddress; }; + /** + * Used to check if the controller has been initialized. + * @return True if it's ready. + */ + virtual bool isReady() { return bPollEnable; }; + /**@}*/ - /** @name USBDeviceConfig implementation */ - /** - * Initialize the PS3 Controller. - * @param parent Hub number. - * @param port Port number on the hub. - * @param lowspeed Speed of the device. - * @return 0 on success. - */ - virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed); - /** - * Release the USB device. - * @return 0 on success. - */ - virtual uint8_t Release(); - /** - * Poll the USB Input endpoins and run the state machines. - * @return 0 on success. - */ - virtual uint8_t Poll(); + /** + * Used to set the Bluetooth address inside the Dualshock 3 and Navigation controller. + * @param BDADDR Your dongles Bluetooth address. + */ + void setBdaddr(uint8_t* BDADDR); + /** + * Used to set the Bluetooth address inside the Move controller. + * @param BDADDR Your dongles Bluetooth address. + */ + void setMoveBdaddr(uint8_t* BDADDR); - /** - * Get the device address. - * @return The device address. - */ - virtual uint8_t GetAddress() { - return bAddress; - }; + /** @name PS3 Controller functions */ + /** + * getButtonPress(Button b) will return true as long as the button is held down. + * + * While getButtonClick(Button b) will only return it once. + * + * So you instance if you need to increase a variable once you would use getButtonClick(Button b), + * but if you need to drive a robot forward you would use getButtonPress(Button b). + */ + bool getButtonPress(Button b); + bool getButtonClick(Button b); + /**@}*/ + /** @name PS3 Controller functions */ + /** + * Used to get the analog value from button presses. + * @param a The ::Button to read. + * The supported buttons are: + * ::UP, ::RIGHT, ::DOWN, ::LEFT, ::L1, ::L2, ::R1, ::R2, + * ::TRIANGLE, ::CIRCLE, ::CROSS, ::SQUARE, and ::T. + * @return Analog value in the range of 0-255. + */ + uint8_t getAnalogButton(Button a); + /** + * Used to read the analog joystick. + * @param a ::LeftHatX, ::LeftHatY, ::RightHatX, and ::RightHatY. + * @return Return the analog value in the range of 0-255. + */ + uint8_t getAnalogHat(AnalogHat a); + /** + * Used to read the sensors inside the Dualshock 3 controller. + * @param a + * The Dualshock 3 has a 3-axis accelerometer and a 1-axis gyro inside. + * @return Return the raw sensor value. + */ + uint16_t getSensor(Sensor a); + /** + * Use this to get ::Pitch and ::Roll calculated using the accelerometer. + * @param a Either ::Pitch or ::Roll. + * @return Return the angle in the range of 0-360. + */ + double getAngle(Angle a); + /** + * Get the ::Status from the controller. + * @param c The ::Status you want to read. + * @return True if correct and false if not. + */ + bool getStatus(Status c); + /** + * Read all the available ::Status from the controller. + * @return One large string with all the information. + */ + String getStatusString(); - /** - * Used to check if the controller has been initialized. - * @return True if it's ready. - */ - virtual bool isReady() { - return bPollEnable; - }; - /**@}*/ + /** Used to set all LEDs and ::Rumble off. */ + void setAllOff(); + /** Turn off ::Rumble. */ + void setRumbleOff(); + /** + * Turn on ::Rumble. + * @param mode Either ::RumbleHigh or ::RumbleLow. + */ + void setRumbleOn(Rumble mode); + /** + * Turn on ::Rumble using custom duration and power. + * @param rightDuration The duration of the right/low rumble effect. + * @param rightPower The intensity of the right/low rumble effect. + * @param leftDuration The duration of the left/high rumble effect. + * @param leftPower The intensity of the left/high rumble effect. + */ + void setRumbleOn(uint8_t rightDuration, uint8_t rightPower, uint8_t leftDuration, uint8_t leftPower); + /** + * Turn the specific ::LED off. + * @param a The ::LED to turn off. + */ + void setLedOff(LED a); + /** + * Turn the specific ::LED on. + * @param a The ::LED to turn on. + */ + void setLedOn(LED a); + /** + * Toggle the specific ::LED. + * @param a The ::LED to toggle. + */ + void setLedToggle(LED a); + + /** + * Use this to set the Color using RGB values. + * @param r,g,b RGB value. + */ + void moveSetBulb(uint8_t r, uint8_t g, uint8_t b); + /** + * Use this to set the color using the predefined colors in ::Colors. + * @param color The desired color. + */ + void moveSetBulb(Colors color); + /** + * Set the rumble value inside the Move controller. + * @param rumble The desired value in the range from 64-255. + */ + void moveSetRumble(uint8_t rumble); + /**@}*/ - /** - * Used to set the Bluetooth address inside the Dualshock 3 and Navigation controller. - * @param BDADDR Your dongles Bluetooth address. - */ - void setBdaddr(uint8_t* BDADDR); - /** - * Used to set the Bluetooth address inside the Move controller. - * @param BDADDR Your dongles Bluetooth address. - */ - void setMoveBdaddr(uint8_t* BDADDR); + /** Variable used to indicate if the normal playstation controller is successfully connected. */ + bool PS3Connected; + /** Variable used to indicate if the move controller is successfully connected. */ + bool PS3MoveConnected; + /** Variable used to indicate if the navigation controller is successfully connected. */ + bool PS3NavigationConnected; + +protected: + /** Pointer to USB class instance. */ + USB *pUsb; + /** Device address. */ + uint8_t bAddress; + /** Endpoint info structure. */ + EpInfo epInfo[PS3_MAX_ENDPOINTS]; + +private: + bool bPollEnable; + + uint32_t timer; // used to continuously set PS3 Move controller Bulb and rumble values - /** @name PS3 Controller functions */ - /** - * getButtonPress(Button b) will return true as long as the button is held down. - * - * While getButtonClick(Button b) will only return it once. - * - * So you instance if you need to increase a variable once you would use getButtonClick(Button b), - * but if you need to drive a robot forward you would use getButtonPress(Button b). - */ - bool getButtonPress(Button b); - bool getButtonClick(Button b); - /**@}*/ - /** @name PS3 Controller functions */ - /** - * Used to get the analog value from button presses. - * @param a The ::Button to read. - * The supported buttons are: - * ::UP, ::RIGHT, ::DOWN, ::LEFT, ::L1, ::L2, ::R1, ::R2, - * ::TRIANGLE, ::CIRCLE, ::CROSS, ::SQUARE, and ::T. - * @return Analog value in the range of 0-255. - */ - uint8_t getAnalogButton(Button a); - /** - * Used to read the analog joystick. - * @param a ::LeftHatX, ::LeftHatY, ::RightHatX, and ::RightHatY. - * @return Return the analog value in the range of 0-255. - */ - uint8_t getAnalogHat(AnalogHat a); - /** - * Used to read the sensors inside the Dualshock 3 controller. - * @param a - * The Dualshock 3 has a 3-axis accelerometer and a 1-axis gyro inside. - * @return Return the raw sensor value. - */ - uint16_t getSensor(Sensor a); - /** - * Use this to get ::Pitch and ::Roll calculated using the accelerometer. - * @param a Either ::Pitch or ::Roll. - * @return Return the angle in the range of 0-360. - */ - double getAngle(Angle a); - /** - * Get the ::Status from the controller. - * @param c The ::Status you want to read. - * @return True if correct and false if not. - */ - bool getStatus(Status c); - /** - * Read all the available ::Status from the controller. - * @return One large string with all the information. - */ - String getStatusString(); + uint32_t ButtonState; + uint32_t OldButtonState; + uint32_t ButtonClickState; + + uint8_t my_bdaddr[6]; // Change to your dongles Bluetooth address in the constructor + uint8_t readBuf[EP_MAXPKTSIZE]; // General purpose buffer for input data + uint8_t writeBuf[EP_MAXPKTSIZE]; // General purpose buffer for output data + + void readReport(); // read incoming data + void printReport(); // print incoming date - Uncomment for debugging - /** Used to set all LEDs and ::Rumble off. */ - void setAllOff(); - /** Turn off ::Rumble. */ - void setRumbleOff(); - /** - * Turn on ::Rumble. - * @param mode Either ::RumbleHigh or ::RumbleLow. - */ - void setRumbleOn(Rumble mode); - /** - * Turn the specific ::LED off. - * @param a The ::LED to turn off. - */ - void setLedOff(LED a); - /** - * Turn the specific ::LED on. - * @param a The ::LED to turn on. - */ - void setLedOn(LED a); - /** - * Toggle the specific ::LED. - * @param a The ::LED to toggle. - */ - void setLedToggle(LED a); - - /** - * Use this to set the Color using RGB values. - * @param r,g,b RGB value. - */ - void moveSetBulb(uint8_t r, uint8_t g, uint8_t b); - /** - * Use this to set the color using the predefined colors in ::Colors. - * @param color The desired color. - */ - void moveSetBulb(Colors color); - /** - * Set the rumble value inside the Move controller. - * @param rumble The desired value in the range from 64-255. - */ - void moveSetRumble(uint8_t rumble); - /**@}*/ - - /** Variable used to indicate if the normal playstation controller is successfully connected. */ - bool PS3Connected; - /** Variable used to indicate if the move controller is successfully connected. */ - bool PS3MoveConnected; - /** Variable used to indicate if the navigation controller is successfully connected. */ - bool PS3NavigationConnected; - -protected: - /** Pointer to USB class instance. */ - USB *pUsb; - /** Device address. */ - uint8_t bAddress; - /** Endpoint info structure. */ - EpInfo epInfo[PS3_MAX_ENDPOINTS]; - -private: - bool bPollEnable; - - uint32_t timer; // used to continuously set PS3 Move controller Bulb and rumble values - - uint32_t ButtonState; - uint32_t OldButtonState; - uint32_t ButtonClickState; - - uint8_t my_bdaddr[6]; // Change to your dongles Bluetooth address in the constructor - uint8_t readBuf[EP_MAXPKTSIZE]; // General purpose buffer for input data - uint8_t writeBuf[EP_MAXPKTSIZE]; // General purpose buffer for output data - - void readReport(); // read incoming data - void printReport(); // print incoming date - Uncomment for debugging - - /* Private commands */ - void PS3_Command(uint8_t* data, uint16_t nbytes); - void enable_sixaxis(); // Command used to enable the Dualshock 3 and Navigation controller to send data via USB - void Move_Command(uint8_t* data, uint16_t nbytes); + /* Private commands */ + void PS3_Command(uint8_t* data, uint16_t nbytes); + void enable_sixaxis(); // Command used to enable the Dualshock 3 and Navigation controller to send data via USB + void Move_Command(uint8_t* data, uint16_t nbytes); }; #endif From 67a8989cefb9c123100fb568e4b3b1816280dc77 Mon Sep 17 00:00:00 2001 From: Kevin Mark Date: Sat, 30 Mar 2013 01:18:43 -0400 Subject: [PATCH 5/7] Removed duplicate code from PS3BT/PS3USB's setRumbleOn --- PS3BT.cpp | 24 +++++++----------------- PS3USB.cpp | 24 +++++++----------------- 2 files changed, 14 insertions(+), 34 deletions(-) diff --git a/PS3BT.cpp b/PS3BT.cpp index d957a666..e72a60ce 100644 --- a/PS3BT.cpp +++ b/PS3BT.cpp @@ -589,24 +589,14 @@ void PS3BT::setRumbleOff() { } void PS3BT::setRumbleOn(Rumble mode) { - /* Still not totally sure how it works, maybe something like this instead? - * 3 - duration_right - * 4 - power_right - * 5 - duration_left - * 6 - power_left - */ - if ((mode & 0x30) > 0) { - HIDBuffer[3] = 0xfe; - HIDBuffer[5] = 0xfe; - if (mode == RumbleHigh) { - HIDBuffer[4] = 0; //low mode off - HIDBuffer[6] = 0xff; //high mode on - } else { - HIDBuffer[4] = 0xff; //low mode on - HIDBuffer[6] = 0; //high mode off - } - HID_Command(HIDBuffer, HID_BUFFERSIZE); + if ((mode & 0x30) > 0) { + uint8_t power[2] = { 0xff, 0 }; // Defaults to RumbleLow + if (mode == RumbleHigh) { + power[0] = 0; + power[1] = 0xff; } + setRumbleOn(0xfe, power[0], 0xfe, power[1]); + } } void PS3BT::setRumbleOn(uint8_t rightDuration, uint8_t rightPower, uint8_t leftDuration, uint8_t leftPower) { HIDBuffer[3] = rightDuration; diff --git a/PS3USB.cpp b/PS3USB.cpp index b329e174..6e58286a 100644 --- a/PS3USB.cpp +++ b/PS3USB.cpp @@ -445,24 +445,14 @@ void PS3USB::setRumbleOff() { } void PS3USB::setRumbleOn(Rumble mode) { - /* Still not totally sure how it works, maybe something like this instead? - * 3 - duration_right - * 4 - power_right - * 5 - duration_left - * 6 - power_left - */ - if ((mode & 0x30) > 0) { - writeBuf[1] = 0xfe; - writeBuf[3] = 0xfe; - if (mode == RumbleHigh) { - writeBuf[2] = 0; //low mode off - writeBuf[4] = 0xff; //high mode on - } else { - writeBuf[2] = 0xff; //low mode on - writeBuf[4] = 0; //high mode off - } - PS3_Command(writeBuf, PS3_REPORT_BUFFER_SIZE); + if ((mode & 0x30) > 0) { + uint8_t power[2] = { 0xff, 0 }; // Defaults to RumbleLow + if (mode == RumbleHigh) { + power[0] = 0; + power[1] = 0xff; } + setRumbleOn(0xfe, power[0], 0xfe, power[1]); + } } void PS3USB::setRumbleOn(uint8_t rightDuration, uint8_t rightPower, uint8_t leftDuration, uint8_t leftPower) { writeBuf[1] = rightDuration; From f3342aa589d49c208745bf3a4fd51591312149bf Mon Sep 17 00:00:00 2001 From: Kevin Mark Date: Sat, 30 Mar 2013 04:15:25 -0400 Subject: [PATCH 6/7] Code cleanup --- PS3BT.cpp | 28 ++-- PS3BT.h | 294 +++++++++++++++++++++--------------------- PS3USB.cpp | 28 ++-- PS3USB.h | 372 +++++++++++++++++++++++++++-------------------------- 4 files changed, 366 insertions(+), 356 deletions(-) diff --git a/PS3BT.cpp b/PS3BT.cpp index e72a60ce..406507f3 100644 --- a/PS3BT.cpp +++ b/PS3BT.cpp @@ -589,22 +589,24 @@ void PS3BT::setRumbleOff() { } void PS3BT::setRumbleOn(Rumble mode) { - if ((mode & 0x30) > 0) { - uint8_t power[2] = { 0xff, 0 }; // Defaults to RumbleLow - if (mode == RumbleHigh) { - power[0] = 0; - power[1] = 0xff; + if ((mode & 0x30) > 0) { + uint8_t power[2] = { 0xff, 0 }; // Defaults to RumbleLow + if (mode == RumbleHigh) { + power[0] = 0; + power[1] = 0xff; + } + setRumbleOn(0xfe, power[0], 0xfe, power[1]); } - setRumbleOn(0xfe, power[0], 0xfe, power[1]); - } } + void PS3BT::setRumbleOn(uint8_t rightDuration, uint8_t rightPower, uint8_t leftDuration, uint8_t leftPower) { - HIDBuffer[3] = rightDuration; - HIDBuffer[4] = rightPower; - HIDBuffer[5] = leftDuration; - HIDBuffer[6] = leftPower; - HID_Command(HIDBuffer, HID_BUFFERSIZE); + HIDBuffer[3] = rightDuration; + HIDBuffer[4] = rightPower; + HIDBuffer[5] = leftDuration; + HIDBuffer[6] = leftPower; + HID_Command(HIDBuffer, HID_BUFFERSIZE); } + void PS3BT::setLedOff(LED a) { HIDBuffer[11] &= ~((uint8_t)((pgm_read_byte(&LEDS[(uint8_t)a]) & 0x0f) << 1)); HID_Command(HIDBuffer, HID_BUFFERSIZE); @@ -663,4 +665,4 @@ void PS3BT::moveSetRumble(uint8_t rumble) { HIDMoveBuffer[7] = rumble; HIDMove_Command(HIDMoveBuffer, HID_BUFFERSIZE); -} \ No newline at end of file +} diff --git a/PS3BT.h b/PS3BT.h index 6b094b00..ef0b7544 100644 --- a/PS3BT.h +++ b/PS3BT.h @@ -65,152 +65,152 @@ */ class PS3BT : public BluetoothService { public: - /** - * Constructor for the PS3BT class. - * @param pBtd Pointer to BTD class instance. - * @param btadr5,btadr4,btadr3,btadr2,btadr1,btadr0 - * Pass your dongles Bluetooth address into the constructor, - * This will set BTD#my_bdaddr, so you don't have to plug in the dongle before pairing with your controller. - */ - PS3BT(BTD *pBtd, uint8_t btadr5=0, uint8_t btadr4=0, uint8_t btadr3=0, uint8_t btadr2=0, uint8_t btadr1=0, uint8_t btadr0=0); - - /** @name BluetoothService implementation */ - /** - * Used to pass acldata to the services. - * @param ACLData Incoming acldata. - */ - virtual void ACLData(uint8_t* ACLData); - /** Used to run part of the state maschine. */ - virtual void Run(); - /** Use this to reset the service. */ - virtual void Reset(); - /** Used this to disconnect any of the controllers. */ - virtual void disconnect(); - /**@}*/ - - /** @name PS3 Controller functions */ - /** - * getButtonPress(Button b) will return true as long as the button is held down. - * - * While getButtonClick(Button b) will only return it once. - * - * So you instance if you need to increase a variable once you would use getButtonClick(Button b), - * but if you need to drive a robot forward you would use getButtonPress(Button b). - */ - bool getButtonPress(Button b); - bool getButtonClick(Button b); - /**@}*/ - /** @name PS3 Controller functions */ - /** - * Used to get the analog value from button presses. - * @param a The ::Button to read. - * The supported buttons are: - * ::UP, ::RIGHT, ::DOWN, ::LEFT, ::L1, ::L2, ::R1, ::R2, - * ::TRIANGLE, ::CIRCLE, ::CROSS, ::SQUARE, and ::T. - * @return Analog value in the range of 0-255. - */ - uint8_t getAnalogButton(Button a); - /** - * Used to read the analog joystick. - * @param a ::LeftHatX, ::LeftHatY, ::RightHatX, and ::RightHatY. - * @return Return the analog value in the range of 0-255. - */ - uint8_t getAnalogHat(AnalogHat a); - /** - * Used to read the sensors inside the Dualshock 3 and Move controller. - * @param a - * The Dualshock 3 has a 3-axis accelerometer and a 1-axis gyro inside. - * The Move controller has a 3-axis accelerometer, a 3-axis gyro, a 3-axis magnetometer - * and a temperature sensor inside. - * @return Return the raw sensor value. - */ - int16_t getSensor(Sensor a); - /** - * Use this to get ::Pitch and ::Roll calculated using the accelerometer. - * @param a Either ::Pitch or ::Roll. - * @return Return the angle in the range of 0-360. - */ - double getAngle(Angle a); - /** - * Read the sensors inside the Move controller. - * @param a ::aXmove, ::aYmove, ::aZmove, ::gXmove, ::gYmove, ::gZmove, ::mXmove, ::mYmove, and ::mXmove. - * @return The value in SI units. - */ - double get9DOFValues(Sensor a); - /** - * Get the ::Status from the controller. - * @param c The ::Status you want to read. - * @return True if correct and false if not. - */ - bool getStatus(Status c); - /** - * Read all the available ::Status from the controller. - * @return One large string with all the information. - */ - String getStatusString(); - /** - * Read the temperature from the Move controller. - * @return The temperature in degrees celsius. - */ - String getTemperature(); - - /** Used to set all LEDs and ::Rumble off. */ - void setAllOff(); - /** Turn off ::Rumble. */ - void setRumbleOff(); - /** - * Turn on ::Rumble. - * @param mode Either ::RumbleHigh or ::RumbleLow. - */ - void setRumbleOn(Rumble mode); - /** - * Turn on ::Rumble using custom duration and power. - * @param rightDuration The duration of the right/low rumble effect. - * @param rightPower The intensity of the right/low rumble effect. - * @param leftDuration The duration of the left/high rumble effect. - * @param leftPower The intensity of the left/high rumble effect. - */ - void setRumbleOn(uint8_t rightDuration, uint8_t rightPower, uint8_t leftDuration, uint8_t leftPower); - /** - * Turn the specific ::LED off. - * @param a The ::LED to turn off. - */ - void setLedOff(LED a); - /** - * Turn the specific ::LED on. - * @param a The ::LED to turn on. - */ - void setLedOn(LED a); - /** - * Toggle the specific ::LED. - * @param a The ::LED to toggle. - */ - void setLedToggle(LED a); - - /** - * Use this to set the Color using RGB values. - * @param r,g,b RGB value. - */ - void moveSetBulb(uint8_t r, uint8_t g, uint8_t b); - /** - * Use this to set the color using the predefined colors in ::Colors. - * @param color The desired color. - */ - void moveSetBulb(Colors color); - /** - * Set the rumble value inside the Move controller. - * @param rumble The desired value in the range from 64-255. - */ - void moveSetRumble(uint8_t rumble); - /**@}*/ - - /** Variable used to indicate if the normal playstation controller is successfully connected. */ - bool PS3Connected; - /** Variable used to indicate if the move controller is successfully connected. */ - bool PS3MoveConnected; - /** Variable used to indicate if the navigation controller is successfully connected. */ - bool PS3NavigationConnected; - + /** + * Constructor for the PS3BT class. + * @param pBtd Pointer to BTD class instance. + * @param btadr5,btadr4,btadr3,btadr2,btadr1,btadr0 + * Pass your dongles Bluetooth address into the constructor, + * This will set BTD#my_bdaddr, so you don't have to plug in the dongle before pairing with your controller. + */ + PS3BT(BTD *pBtd, uint8_t btadr5 = 0, uint8_t btadr4 = 0, uint8_t btadr3 = 0, uint8_t btadr2 = 0, uint8_t btadr1 = 0, uint8_t btadr0 = 0); + + /** @name BluetoothService implementation */ + /** + * Used to pass acldata to the services. + * @param ACLData Incoming acldata. + */ + virtual void ACLData(uint8_t* ACLData); + /** Used to run part of the state maschine. */ + virtual void Run(); + /** Use this to reset the service. */ + virtual void Reset(); + /** Used this to disconnect any of the controllers. */ + virtual void disconnect(); + /**@}*/ + + /** @name PS3 Controller functions */ + /** + * getButtonPress(Button b) will return true as long as the button is held down. + * + * While getButtonClick(Button b) will only return it once. + * + * So you instance if you need to increase a variable once you would use getButtonClick(Button b), + * but if you need to drive a robot forward you would use getButtonPress(Button b). + */ + bool getButtonPress(Button b); + bool getButtonClick(Button b); + /**@}*/ + /** @name PS3 Controller functions */ + /** + * Used to get the analog value from button presses. + * @param a The ::Button to read. + * The supported buttons are: + * ::UP, ::RIGHT, ::DOWN, ::LEFT, ::L1, ::L2, ::R1, ::R2, + * ::TRIANGLE, ::CIRCLE, ::CROSS, ::SQUARE, and ::T. + * @return Analog value in the range of 0-255. + */ + uint8_t getAnalogButton(Button a); + /** + * Used to read the analog joystick. + * @param a ::LeftHatX, ::LeftHatY, ::RightHatX, and ::RightHatY. + * @return Return the analog value in the range of 0-255. + */ + uint8_t getAnalogHat(AnalogHat a); + /** + * Used to read the sensors inside the Dualshock 3 and Move controller. + * @param a + * The Dualshock 3 has a 3-axis accelerometer and a 1-axis gyro inside. + * The Move controller has a 3-axis accelerometer, a 3-axis gyro, a 3-axis magnetometer + * and a temperature sensor inside. + * @return Return the raw sensor value. + */ + int16_t getSensor(Sensor a); + /** + * Use this to get ::Pitch and ::Roll calculated using the accelerometer. + * @param a Either ::Pitch or ::Roll. + * @return Return the angle in the range of 0-360. + */ + double getAngle(Angle a); + /** + * Read the sensors inside the Move controller. + * @param a ::aXmove, ::aYmove, ::aZmove, ::gXmove, ::gYmove, ::gZmove, ::mXmove, ::mYmove, and ::mXmove. + * @return The value in SI units. + */ + double get9DOFValues(Sensor a); + /** + * Get the ::Status from the controller. + * @param c The ::Status you want to read. + * @return True if correct and false if not. + */ + bool getStatus(Status c); + /** + * Read all the available ::Status from the controller. + * @return One large string with all the information. + */ + String getStatusString(); + /** + * Read the temperature from the Move controller. + * @return The temperature in degrees celsius. + */ + String getTemperature(); + + /** Used to set all LEDs and ::Rumble off. */ + void setAllOff(); + /** Turn off ::Rumble. */ + void setRumbleOff(); + /** + * Turn on ::Rumble. + * @param mode Either ::RumbleHigh or ::RumbleLow. + */ + void setRumbleOn(Rumble mode); + /** + * Turn on ::Rumble using custom duration and power. + * @param rightDuration The duration of the right/low rumble effect. + * @param rightPower The intensity of the right/low rumble effect. + * @param leftDuration The duration of the left/high rumble effect. + * @param leftPower The intensity of the left/high rumble effect. + */ + void setRumbleOn(uint8_t rightDuration, uint8_t rightPower, uint8_t leftDuration, uint8_t leftPower); + /** + * Turn the specific ::LED off. + * @param a The ::LED to turn off. + */ + void setLedOff(LED a); + /** + * Turn the specific ::LED on. + * @param a The ::LED to turn on. + */ + void setLedOn(LED a); + /** + * Toggle the specific ::LED. + * @param a The ::LED to toggle. + */ + void setLedToggle(LED a); + + /** + * Use this to set the Color using RGB values. + * @param r,g,b RGB value. + */ + void moveSetBulb(uint8_t r, uint8_t g, uint8_t b); + /** + * Use this to set the color using the predefined colors in ::Colors. + * @param color The desired color. + */ + void moveSetBulb(Colors color); + /** + * Set the rumble value inside the Move controller. + * @param rumble The desired value in the range from 64-255. + */ + void moveSetRumble(uint8_t rumble); + /**@}*/ + + /** Variable used to indicate if the normal playstation controller is successfully connected. */ + bool PS3Connected; + /** Variable used to indicate if the move controller is successfully connected. */ + bool PS3MoveConnected; + /** Variable used to indicate if the navigation controller is successfully connected. */ + bool PS3NavigationConnected; + private: /* mandatory members */ BTD *pBtd; @@ -251,4 +251,4 @@ private: void HIDMove_Command(uint8_t* data, uint8_t nbytes); void enable_sixaxis(); // Command used to enable the Dualshock 3 and Navigation controller to send data via Bluetooth }; -#endif \ No newline at end of file +#endif diff --git a/PS3USB.cpp b/PS3USB.cpp index 6e58286a..ae44f9c0 100644 --- a/PS3USB.cpp +++ b/PS3USB.cpp @@ -445,22 +445,24 @@ void PS3USB::setRumbleOff() { } void PS3USB::setRumbleOn(Rumble mode) { - if ((mode & 0x30) > 0) { - uint8_t power[2] = { 0xff, 0 }; // Defaults to RumbleLow - if (mode == RumbleHigh) { - power[0] = 0; - power[1] = 0xff; + if ((mode & 0x30) > 0x00) { + uint8_t power[2] = { 0xff, 0x00 }; // Defaults to RumbleLow + if (mode == RumbleHigh) { + power[0] = 0x00; + power[1] = 0xff; + } + setRumbleOn(0xfe, power[0], 0xfe, power[1]); } - setRumbleOn(0xfe, power[0], 0xfe, power[1]); - } } + void PS3USB::setRumbleOn(uint8_t rightDuration, uint8_t rightPower, uint8_t leftDuration, uint8_t leftPower) { - writeBuf[1] = rightDuration; - writeBuf[2] = rightPower; - writeBuf[3] = leftDuration; - writeBuf[4] = leftPower; - PS3_Command(writeBuf, PS3_REPORT_BUFFER_SIZE); + writeBuf[1] = rightDuration; + writeBuf[2] = rightPower; + writeBuf[3] = leftDuration; + writeBuf[4] = leftPower; + PS3_Command(writeBuf, PS3_REPORT_BUFFER_SIZE); } + void PS3USB::setLedOff(LED a) { writeBuf[9] &= ~((uint8_t)((pgm_read_byte(&LEDS[(uint8_t)a]) & 0x0f) << 1)); PS3_Command(writeBuf, PS3_REPORT_BUFFER_SIZE); @@ -560,4 +562,4 @@ void PS3USB::setMoveBdaddr(uint8_t* BDADDR) { PrintHex (my_bdaddr[0], 0x80); #endif return; -} \ No newline at end of file +} diff --git a/PS3USB.h b/PS3USB.h index 25c00415..05a9476c 100644 --- a/PS3USB.h +++ b/PS3USB.h @@ -63,194 +63,200 @@ */ class PS3USB : public USBDeviceConfig { public: - /** - * Constructor for the PS3USB class. - * @param pUsb Pointer to USB class instance. - * @param btadr5,btadr4,btadr3,btadr2,btadr1,btadr0 - * Pass your dongles Bluetooth address into the constructor, - * so you are able to pair the controller with a Bluetooth dongle. - */ - PS3USB(USB *pUsb, uint8_t btadr5=0, uint8_t btadr4=0, uint8_t btadr3=0, uint8_t btadr2=0, uint8_t btadr1=0, uint8_t btadr0=0); - - /** @name USBDeviceConfig implementation */ - /** - * Initialize the PS3 Controller. - * @param parent Hub number. - * @param port Port number on the hub. - * @param lowspeed Speed of the device. - * @return 0 on success. - */ - virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed); - /** - * Release the USB device. - * @return 0 on success. - */ - virtual uint8_t Release(); - /** - * Poll the USB Input endpoins and run the state machines. - * @return 0 on success. - */ - virtual uint8_t Poll(); - /** - * Get the device address. - * @return The device address. - */ - virtual uint8_t GetAddress() { return bAddress; }; - /** - * Used to check if the controller has been initialized. - * @return True if it's ready. - */ - virtual bool isReady() { return bPollEnable; }; - /**@}*/ + /** + * Constructor for the PS3USB class. + * @param pUsb Pointer to USB class instance. + * @param btadr5,btadr4,btadr3,btadr2,btadr1,btadr0 + * Pass your dongles Bluetooth address into the constructor, + * so you are able to pair the controller with a Bluetooth dongle. + */ + PS3USB(USB *pUsb, uint8_t btadr5 = 0, uint8_t btadr4 = 0, uint8_t btadr3 = 0, uint8_t btadr2 = 0, uint8_t btadr1 = 0, uint8_t btadr0 = 0); - /** - * Used to set the Bluetooth address inside the Dualshock 3 and Navigation controller. - * @param BDADDR Your dongles Bluetooth address. - */ - void setBdaddr(uint8_t* BDADDR); - /** - * Used to set the Bluetooth address inside the Move controller. - * @param BDADDR Your dongles Bluetooth address. - */ - void setMoveBdaddr(uint8_t* BDADDR); + /** @name USBDeviceConfig implementation */ + /** + * Initialize the PS3 Controller. + * @param parent Hub number. + * @param port Port number on the hub. + * @param lowspeed Speed of the device. + * @return 0 on success. + */ + virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed); + /** + * Release the USB device. + * @return 0 on success. + */ + virtual uint8_t Release(); + /** + * Poll the USB Input endpoins and run the state machines. + * @return 0 on success. + */ + virtual uint8_t Poll(); - /** @name PS3 Controller functions */ - /** - * getButtonPress(Button b) will return true as long as the button is held down. - * - * While getButtonClick(Button b) will only return it once. - * - * So you instance if you need to increase a variable once you would use getButtonClick(Button b), - * but if you need to drive a robot forward you would use getButtonPress(Button b). - */ - bool getButtonPress(Button b); - bool getButtonClick(Button b); - /**@}*/ - /** @name PS3 Controller functions */ - /** - * Used to get the analog value from button presses. - * @param a The ::Button to read. - * The supported buttons are: - * ::UP, ::RIGHT, ::DOWN, ::LEFT, ::L1, ::L2, ::R1, ::R2, - * ::TRIANGLE, ::CIRCLE, ::CROSS, ::SQUARE, and ::T. - * @return Analog value in the range of 0-255. - */ - uint8_t getAnalogButton(Button a); - /** - * Used to read the analog joystick. - * @param a ::LeftHatX, ::LeftHatY, ::RightHatX, and ::RightHatY. - * @return Return the analog value in the range of 0-255. - */ - uint8_t getAnalogHat(AnalogHat a); - /** - * Used to read the sensors inside the Dualshock 3 controller. - * @param a - * The Dualshock 3 has a 3-axis accelerometer and a 1-axis gyro inside. - * @return Return the raw sensor value. - */ - uint16_t getSensor(Sensor a); - /** - * Use this to get ::Pitch and ::Roll calculated using the accelerometer. - * @param a Either ::Pitch or ::Roll. - * @return Return the angle in the range of 0-360. - */ - double getAngle(Angle a); - /** - * Get the ::Status from the controller. - * @param c The ::Status you want to read. - * @return True if correct and false if not. - */ - bool getStatus(Status c); - /** - * Read all the available ::Status from the controller. - * @return One large string with all the information. - */ - String getStatusString(); + /** + * Get the device address. + * @return The device address. + */ + virtual uint8_t GetAddress() { + return bAddress; + }; - /** Used to set all LEDs and ::Rumble off. */ - void setAllOff(); - /** Turn off ::Rumble. */ - void setRumbleOff(); - /** - * Turn on ::Rumble. - * @param mode Either ::RumbleHigh or ::RumbleLow. - */ - void setRumbleOn(Rumble mode); - /** - * Turn on ::Rumble using custom duration and power. - * @param rightDuration The duration of the right/low rumble effect. - * @param rightPower The intensity of the right/low rumble effect. - * @param leftDuration The duration of the left/high rumble effect. - * @param leftPower The intensity of the left/high rumble effect. - */ - void setRumbleOn(uint8_t rightDuration, uint8_t rightPower, uint8_t leftDuration, uint8_t leftPower); - /** - * Turn the specific ::LED off. - * @param a The ::LED to turn off. - */ - void setLedOff(LED a); - /** - * Turn the specific ::LED on. - * @param a The ::LED to turn on. - */ - void setLedOn(LED a); - /** - * Toggle the specific ::LED. - * @param a The ::LED to toggle. - */ - void setLedToggle(LED a); - - /** - * Use this to set the Color using RGB values. - * @param r,g,b RGB value. - */ - void moveSetBulb(uint8_t r, uint8_t g, uint8_t b); - /** - * Use this to set the color using the predefined colors in ::Colors. - * @param color The desired color. - */ - void moveSetBulb(Colors color); - /** - * Set the rumble value inside the Move controller. - * @param rumble The desired value in the range from 64-255. - */ - void moveSetRumble(uint8_t rumble); - /**@}*/ + /** + * Used to check if the controller has been initialized. + * @return True if it's ready. + */ + virtual bool isReady() { + return bPollEnable; + }; + /**@}*/ - /** Variable used to indicate if the normal playstation controller is successfully connected. */ - bool PS3Connected; - /** Variable used to indicate if the move controller is successfully connected. */ - bool PS3MoveConnected; - /** Variable used to indicate if the navigation controller is successfully connected. */ - bool PS3NavigationConnected; - -protected: - /** Pointer to USB class instance. */ - USB *pUsb; - /** Device address. */ - uint8_t bAddress; - /** Endpoint info structure. */ - EpInfo epInfo[PS3_MAX_ENDPOINTS]; - -private: - bool bPollEnable; - - uint32_t timer; // used to continuously set PS3 Move controller Bulb and rumble values + /** + * Used to set the Bluetooth address inside the Dualshock 3 and Navigation controller. + * @param BDADDR Your dongles Bluetooth address. + */ + void setBdaddr(uint8_t* BDADDR); + /** + * Used to set the Bluetooth address inside the Move controller. + * @param BDADDR Your dongles Bluetooth address. + */ + void setMoveBdaddr(uint8_t* BDADDR); - uint32_t ButtonState; - uint32_t OldButtonState; - uint32_t ButtonClickState; - - uint8_t my_bdaddr[6]; // Change to your dongles Bluetooth address in the constructor - uint8_t readBuf[EP_MAXPKTSIZE]; // General purpose buffer for input data - uint8_t writeBuf[EP_MAXPKTSIZE]; // General purpose buffer for output data - - void readReport(); // read incoming data - void printReport(); // print incoming date - Uncomment for debugging + /** @name PS3 Controller functions */ + /** + * getButtonPress(Button b) will return true as long as the button is held down. + * + * While getButtonClick(Button b) will only return it once. + * + * So you instance if you need to increase a variable once you would use getButtonClick(Button b), + * but if you need to drive a robot forward you would use getButtonPress(Button b). + */ + bool getButtonPress(Button b); + bool getButtonClick(Button b); + /**@}*/ + /** @name PS3 Controller functions */ + /** + * Used to get the analog value from button presses. + * @param a The ::Button to read. + * The supported buttons are: + * ::UP, ::RIGHT, ::DOWN, ::LEFT, ::L1, ::L2, ::R1, ::R2, + * ::TRIANGLE, ::CIRCLE, ::CROSS, ::SQUARE, and ::T. + * @return Analog value in the range of 0-255. + */ + uint8_t getAnalogButton(Button a); + /** + * Used to read the analog joystick. + * @param a ::LeftHatX, ::LeftHatY, ::RightHatX, and ::RightHatY. + * @return Return the analog value in the range of 0-255. + */ + uint8_t getAnalogHat(AnalogHat a); + /** + * Used to read the sensors inside the Dualshock 3 controller. + * @param a + * The Dualshock 3 has a 3-axis accelerometer and a 1-axis gyro inside. + * @return Return the raw sensor value. + */ + uint16_t getSensor(Sensor a); + /** + * Use this to get ::Pitch and ::Roll calculated using the accelerometer. + * @param a Either ::Pitch or ::Roll. + * @return Return the angle in the range of 0-360. + */ + double getAngle(Angle a); + /** + * Get the ::Status from the controller. + * @param c The ::Status you want to read. + * @return True if correct and false if not. + */ + bool getStatus(Status c); + /** + * Read all the available ::Status from the controller. + * @return One large string with all the information. + */ + String getStatusString(); - /* Private commands */ - void PS3_Command(uint8_t* data, uint16_t nbytes); - void enable_sixaxis(); // Command used to enable the Dualshock 3 and Navigation controller to send data via USB - void Move_Command(uint8_t* data, uint16_t nbytes); + /** Used to set all LEDs and ::Rumble off. */ + void setAllOff(); + /** Turn off ::Rumble. */ + void setRumbleOff(); + /** + * Turn on ::Rumble. + * @param mode Either ::RumbleHigh or ::RumbleLow. + */ + void setRumbleOn(Rumble mode); + /** + * Turn on ::Rumble using custom duration and power. + * @param rightDuration The duration of the right/low rumble effect. + * @param rightPower The intensity of the right/low rumble effect. + * @param leftDuration The duration of the left/high rumble effect. + * @param leftPower The intensity of the left/high rumble effect. + */ + void setRumbleOn(uint8_t rightDuration, uint8_t rightPower, uint8_t leftDuration, uint8_t leftPower); + /** + * Turn the specific ::LED off. + * @param a The ::LED to turn off. + */ + void setLedOff(LED a); + /** + * Turn the specific ::LED on. + * @param a The ::LED to turn on. + */ + void setLedOn(LED a); + /** + * Toggle the specific ::LED. + * @param a The ::LED to toggle. + */ + void setLedToggle(LED a); + + /** + * Use this to set the Color using RGB values. + * @param r,g,b RGB value. + */ + void moveSetBulb(uint8_t r, uint8_t g, uint8_t b); + /** + * Use this to set the color using the predefined colors in ::Colors. + * @param color The desired color. + */ + void moveSetBulb(Colors color); + /** + * Set the rumble value inside the Move controller. + * @param rumble The desired value in the range from 64-255. + */ + void moveSetRumble(uint8_t rumble); + /**@}*/ + + /** Variable used to indicate if the normal playstation controller is successfully connected. */ + bool PS3Connected; + /** Variable used to indicate if the move controller is successfully connected. */ + bool PS3MoveConnected; + /** Variable used to indicate if the navigation controller is successfully connected. */ + bool PS3NavigationConnected; + +protected: + /** Pointer to USB class instance. */ + USB *pUsb; + /** Device address. */ + uint8_t bAddress; + /** Endpoint info structure. */ + EpInfo epInfo[PS3_MAX_ENDPOINTS]; + +private: + bool bPollEnable; + + uint32_t timer; // used to continuously set PS3 Move controller Bulb and rumble values + + uint32_t ButtonState; + uint32_t OldButtonState; + uint32_t ButtonClickState; + + uint8_t my_bdaddr[6]; // Change to your dongles Bluetooth address in the constructor + uint8_t readBuf[EP_MAXPKTSIZE]; // General purpose buffer for input data + uint8_t writeBuf[EP_MAXPKTSIZE]; // General purpose buffer for output data + + void readReport(); // read incoming data + void printReport(); // print incoming date - Uncomment for debugging + + /* Private commands */ + void PS3_Command(uint8_t* data, uint16_t nbytes); + void enable_sixaxis(); // Command used to enable the Dualshock 3 and Navigation controller to send data via USB + void Move_Command(uint8_t* data, uint16_t nbytes); }; #endif From 970ca7890e02de5c9c08241e83e45195d092e015 Mon Sep 17 00:00:00 2001 From: Kevin Mark Date: Sat, 30 Mar 2013 04:18:08 -0400 Subject: [PATCH 7/7] 0 -> 0x00 --- PS3BT.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/PS3BT.cpp b/PS3BT.cpp index 406507f3..088325b4 100644 --- a/PS3BT.cpp +++ b/PS3BT.cpp @@ -589,10 +589,10 @@ void PS3BT::setRumbleOff() { } void PS3BT::setRumbleOn(Rumble mode) { - if ((mode & 0x30) > 0) { - uint8_t power[2] = { 0xff, 0 }; // Defaults to RumbleLow + if ((mode & 0x30) > 0x00) { + uint8_t power[2] = { 0xff, 0x00 }; // Defaults to RumbleLow if (mode == RumbleHigh) { - power[0] = 0; + power[0] = 0x00; power[1] = 0xff; } setRumbleOn(0xfe, power[0], 0xfe, power[1]);