diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..6238b035 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,23 @@ +# Auto detect text files and perform LF normalization +* text=auto +* text eol=lf + +# Custom for Visual Studio +*.cs diff=csharp +*.sln merge=union +*.csproj merge=union +*.vbproj merge=union +*.fsproj merge=union +*.dbproj merge=union + +# Standard to msysgit +*.doc diff=astextplain +*.DOC diff=astextplain +*.docx diff=astextplain +*.DOCX diff=astextplain +*.dot diff=astextplain +*.DOT diff=astextplain +*.pdf diff=astextplain +*.PDF diff=astextplain +*.rtf diff=astextplain +*.RTF diff=astextplain diff --git a/BTD.cpp b/BTD.cpp index 42cf3d62..dbed9115 100755 --- a/BTD.cpp +++ b/BTD.cpp @@ -1343,7 +1343,7 @@ void BTD::setBdaddr(uint8_t* bdaddr) { buf[i + 2] = bdaddr[5 - i]; // Copy into buffer, has to be written reversed, so it is MSB first // 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); + pUsb->ctrlReq(bAddress, epInfo[BTD_CONTROL_PIPE].epAddr, bmREQ_HIDOUT, HID_REQUEST_SET_REPORT, 0xF5, 0x03, 0x00, 8, 8, buf, NULL); } void BTD::setMoveBdaddr(uint8_t* bdaddr) { @@ -1359,5 +1359,5 @@ void BTD::setMoveBdaddr(uint8_t* bdaddr) { 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); + pUsb->ctrlReq(bAddress, epInfo[BTD_CONTROL_PIPE].epAddr, bmREQ_HIDOUT, HID_REQUEST_SET_REPORT, 0x05, 0x03, 0x00, 11, 11, buf, NULL); } diff --git a/BTD.h b/BTD.h index 9949af15..b7683f65 100755 --- a/BTD.h +++ b/BTD.h @@ -19,7 +19,7 @@ #define _btd_h_ #include "Usb.h" -#include "Hid.h" +#include "hid.h" //PID and VID of the Sony PS3 devices #define PS3_VID 0x054C // Sony Corporation diff --git a/PS3USB.cpp b/PS3USB.cpp index c3217538..ee3a8d74 100644 --- a/PS3USB.cpp +++ b/PS3USB.cpp @@ -398,7 +398,7 @@ void PS3USB::printStatusString() { /* 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); + pUsb->ctrlReq(bAddress, epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HIDOUT, HID_REQUEST_SET_REPORT, 0x01, 0x02, 0x00, nbytes, nbytes, data, NULL); } void PS3USB::setAllOff() { @@ -470,14 +470,14 @@ void PS3USB::setBdaddr(uint8_t *bdaddr) { buf[i + 2] = bdaddr[5 - i]; // Copy into buffer, has to be written reversed, so it is MSB first // 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_HIDOUT, HID_REQUEST_SET_REPORT, 0xF5, 0x03, 0x00, 8, 8, buf, NULL); } void PS3USB::getBdaddr(uint8_t *bdaddr) { uint8_t buf[8]; // bmRequest = Device to host (0x80) | Class (0x20) | Interface (0x01) = 0xA1, bRequest = Get Report (0x01), Report ID (0xF5), Report Type (Feature 0x03), interface (0x00), datalength, datalength, data - pUsb->ctrlReq(bAddress, epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HID_IN, HID_REQUEST_GET_REPORT, 0xF5, 0x03, 0x00, 8, 8, buf, NULL); + pUsb->ctrlReq(bAddress, epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HIDIN, HID_REQUEST_GET_REPORT, 0xF5, 0x03, 0x00, 8, 8, buf, NULL); for(uint8_t i = 0; i < 6; i++) bdaddr[5 - i] = buf[i + 2]; // Copy into buffer reversed, so it is LSB first @@ -491,7 +491,7 @@ void PS3USB::enable_sixaxis() { // Command used to enable the Dualshock 3 and Na 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); + pUsb->ctrlReq(bAddress, epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HIDOUT, HID_REQUEST_SET_REPORT, 0xF4, 0x03, 0x00, 4, 4, cmd_buf, NULL); } /* Playstation Move Controller commands */ @@ -535,14 +535,14 @@ void PS3USB::setMoveBdaddr(uint8_t *bdaddr) { 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_HIDOUT, HID_REQUEST_SET_REPORT, 0x05, 0x03, 0x00, 11, 11, buf, NULL); } void PS3USB::getMoveBdaddr(uint8_t *bdaddr) { uint8_t buf[16]; // bmRequest = Device to host (0x80) | Class (0x20) | Interface (0x01) = 0xA1, bRequest = Get Report (0x01), Report ID (0x04), Report Type (Feature 0x03), interface (0x00), datalength, datalength, data - pUsb->ctrlReq(bAddress, epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HID_IN, HID_REQUEST_GET_REPORT, 0x04, 0x03, 0x00, 16, 16, buf, NULL); + pUsb->ctrlReq(bAddress, epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HIDIN, HID_REQUEST_GET_REPORT, 0x04, 0x03, 0x00, 16, 16, buf, NULL); for(uint8_t i = 0; i < 6; i++) bdaddr[i] = buf[10 + i]; @@ -553,7 +553,7 @@ void PS3USB::getMoveCalibration(uint8_t *data) { for(uint8_t i = 0; i < 3; i++) { // bmRequest = Device to host (0x80) | Class (0x20) | Interface (0x01) = 0xA1, bRequest = Get Report (0x01), Report ID (0x10), Report Type (Feature 0x03), interface (0x00), datalength, datalength, data - pUsb->ctrlReq(bAddress, epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HID_IN, HID_REQUEST_GET_REPORT, 0x10, 0x03, 0x00, 49, 49, buf, NULL); + pUsb->ctrlReq(bAddress, epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HIDIN, HID_REQUEST_GET_REPORT, 0x10, 0x03, 0x00, 49, 49, buf, NULL); for(byte j = 0; j < 49; j++) data[49 * i + j] = buf[j]; diff --git a/PS3USB.h b/PS3USB.h index ee8f8935..2eba9258 100644 --- a/PS3USB.h +++ b/PS3USB.h @@ -19,7 +19,7 @@ #define _ps3usb_h_ #include "Usb.h" -#include "Hid.h" +#include "hid.h" #include "PS3Enums.h" /* PS3 data taken from descriptors */ diff --git a/PS4BT.h b/PS4BT.h index 6be6463e..b7eb4b5a 100644 --- a/PS4BT.h +++ b/PS4BT.h @@ -118,4 +118,4 @@ private: pBtd->L2CAP_Command(hci_handle, data, nbytes, control_scid[0], control_scid[1]); }; }; -#endif \ No newline at end of file +#endif diff --git a/PS4Parser.cpp b/PS4Parser.cpp index ca992866..106d04ed 100644 --- a/PS4Parser.cpp +++ b/PS4Parser.cpp @@ -106,4 +106,4 @@ void PS4Parser::Parse(uint8_t len, uint8_t *buf) { if (ps4Output.reportChanged) sendOutputReport(&ps4Output); // Send output report -} \ No newline at end of file +} diff --git a/PS4Parser.h b/PS4Parser.h index 8b328342..51f08063 100644 --- a/PS4Parser.h +++ b/PS4Parser.h @@ -404,4 +404,4 @@ private: PS4Output ps4Output; uint8_t oldDpad; }; -#endif \ No newline at end of file +#endif diff --git a/PS4USB.h b/PS4USB.h index 8a9e12fa..b43079a6 100644 --- a/PS4USB.h +++ b/PS4USB.h @@ -127,4 +127,4 @@ protected: private: void (*pFuncOnInit)(void); // Pointer to function called in onInit() }; -#endif \ No newline at end of file +#endif diff --git a/PSBuzz.cpp b/PSBuzz.cpp index 4efd2b55..cc1cc464 100644 --- a/PSBuzz.cpp +++ b/PSBuzz.cpp @@ -78,5 +78,5 @@ void PSBuzz::setLedRaw(bool value, uint8_t controller) { void PSBuzz::PSBuzz_Command(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[0].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0x00, 0x02, 0x00, nbytes, nbytes, data, NULL); -}; \ No newline at end of file + pUsb->ctrlReq(bAddress, epInfo[0].epAddr, bmREQ_HIDOUT, HID_REQUEST_SET_REPORT, 0x00, 0x02, 0x00, nbytes, nbytes, data, NULL); +}; diff --git a/PSBuzz.h b/PSBuzz.h index 5043a086..8880d9e5 100644 --- a/PSBuzz.h +++ b/PSBuzz.h @@ -182,4 +182,4 @@ private: PSBUZZButtons psbuzzButtons, oldButtonState, buttonClickState; bool ledState[4]; }; -#endif \ No newline at end of file +#endif diff --git a/README.md b/README.md index 3e888baf..22f07ad6 100644 --- a/README.md +++ b/README.md @@ -285,7 +285,7 @@ More information about the controller can be found at the following sites: The shield is using SPI for communicating with the MAX3421E USB host controller. It uses the SCK, MISO and MOSI pins via the ICSP on your board. -Note this means that it uses pin 13, 12, 11 on an Arduino Uno, so these pins can not be used for anything else! +Note this means that it uses pin 13, 12, 11 on an Arduino Uno, so these pins can not be used for anything else than SPI communication! Furthermore it uses one pin as SS and one INT pin. These are by default located on pin 10 and 9 respectively. They can easily be reconfigured in case you need to use them for something else by cutting the jumper on the shield and then solder a wire from the pad to the new pin. @@ -308,4 +308,18 @@ See the "Interface modifications" section in the [hardware manual](https://www.c > When I plug my device into the USB connector nothing happens? * Try to connect a external power supply to the Arduino - this solves the problem in most cases. -* You can also use a powered hub between the device and the USB Host Shield. You should then include the USB hub library: ```#include ``` and create the instance like so: ```USBHub Hub1(&Usb);```. \ No newline at end of file +* You can also use a powered hub between the device and the USB Host Shield. You should then include the USB hub library: ```#include ``` and create the instance like so: ```USBHub Hub1(&Usb);```. + +> When I connecting my PS3 controller I get a output like this: + +``` +Dualshock 3 Controller Enabled + +LeftHatX: 0 LeftHatY: 0 RightHatX: 0 RightHatY: 0 +LeftHatX: 0 LeftHatY: 0 RightHatX: 0 RightHatY: 0 +LeftHatX: 0 LeftHatY: 0 RightHatX: 0 RightHatY: 0 +LeftHatX: 0 LeftHatY: 0 RightHatX: 0 RightHatY: 0 +LeftHatX: 0 LeftHatY: 0 RightHatX: 0 RightHatY: 0 +``` + +* This means that your dongle does not support 2.0+EDR, so you will need another dongle. Please see the following [list](https://github.com/felis/USB_Host_Shield_2.0/wiki/Bluetooth-dongles) for tested working dongles. diff --git a/Usb.cpp b/Usb.cpp index 37914046..3e07149a 100644 --- a/Usb.cpp +++ b/Usb.cpp @@ -1,812 +1,812 @@ -/* 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 - */ -/* USB functions */ - -#include "Usb.h" - -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(); -} - -/* Initialize data structures */ -void USB::init() { - //devConfigIndex = 0; - bmHubPre = 0; -} - -uint8_t USB::getUsbTaskState(void) { - return ( usb_task_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); - - if(!p || !p->epinfo) - return NULL; - - EpInfo *pep = p->epinfo; - - for(uint8_t i = 0; i < p->epcount; i++) { - if((pep)->epAddr == ep) - return pep; - - 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; - - UsbDevice *p = addrPool.GetUsbDevicePtr(addr); - - if(!p) - return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; - - p->address.devAddress = 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); - - if(!p) - return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; - - if(!p->epinfo) - return USB_ERROR_EPINFO_IS_NULL; - - *ppep = getEpInfoEntry(addr, ep); - - 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 - - uint8_t mode = regRd(rMODE); - - //Serial.print("\r\nMode: "); - //Serial.println( mode, HEX); - //Serial.print("\r\nLS: "); - //Serial.println(p->lowspeed, HEX); - - - - // 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; -} - -/* 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) { - bool direction = false; //request direction, IN or OUT - uint8_t rcode; - SETUP_PKT setup_pkt; - - EpInfo *pep = NULL; - uint16_t nak_limit = 0; - - rcode = SetAddress(addr, ep, &pep, nak_limit); - - if(rcode) - return rcode; - - 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 - - rcode = dispatchPkt(tokSETUP, ep, nak_limit); //dispatch packet - - if(rcode) //return HRSLT if not zero - return ( rcode); - - if(dataptr != NULL) //data stage, if present - { - if(direction) //IN transfer - { - uint16_t left = total; - - pep->bmRcvToggle = 1; //bmRCVTOG1; - - while(left) { - // Bytes read into buffer - uint16_t read = nbytes; - //uint16_t read = (leftbmRcvToggle = (regRd(rHRSL) & bmSNDTOGRD) ? 0 : 1; - continue; - } - - if(rcode) - return rcode; - - // Invoke callback function if inTransfer completed successfully and callback function pointer is specified - if(!rcode && p) - ((USBReadParser*)p)->Parse(read, dataptr, total - left); - - 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 rcode = SetAddress(addr, ep, &pep, nak_limit); - - if(rcode) { - USBTRACE3("(USB::InTransfer) SetAddress Failed ", rcode, 0x81); - USBTRACE3("(USB::InTransfer) addr requested ", addr, 0x81); - USBTRACE3("(USB::InTransfer) ep requested ", ep, 0x81); - 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; - - 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 - - // use a 'break' to exit this loop - while(1) { - rcode = dispatchPkt(tokIN, pep->epAddr, nak_limit); //IN packet to EP-'endpoint'. Function takes care of NAKS. - if(rcode == hrTOGERR) { - // yes, we flip it wrong here so that next time it is actually correct! - pep->bmRcvToggle = (regRd(rHRSL) & bmSNDTOGRD) ? 0 : 1; - regWr(rHCTL, (pep->bmRcvToggle) ? bmRCVTOG1 : bmRCVTOG0); //set toggle value - continue; - } - if(rcode) { - //printf(">>>>>>>> Problem! dispatchPkt %2.2x\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 absence of RCVDAVIRQ makes sense is when toggle error occurred. 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 \r\n", pktsize); - // This would be OK, but... - //assert(pktsize <= nbytes); - if(pktsize > nbytes) { - // This can happen. Use of assert on Arduino locks up the Arduino. - // So I will trim the value, and hope for the best. - //printf(">>>>>>>> Problem! Wanted %i bytes but got %i.\r\n", nbytes, pktsize); - pktsize = nbytes; - } - - int16_t mem_left = (int16_t)nbytes - *((int16_t*)nbytesptr); - - if(mem_left < 0) - mem_left = 0; - - data = bytesRd(rRCVFIFO, ((pktsize > mem_left) ? mem_left : pktsize), data); - - 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 = 0; - - uint8_t rcode = SetAddress(addr, ep, &pep, nak_limit); - - if(rcode) - return rcode; - - 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 = 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); - - while(rcode && ((long)(millis() - timeout) < 0L)) { - switch(rcode) { - case hrNAK: - nak_count++; - if(nak_limit && (nak_count == nak_limit)) - goto breakout; - //return ( rcode); - break; - case hrTIMEOUT: - retry_count++; - if(retry_count == USB_RETRY_LIMIT) - goto breakout; - //return ( rcode); - break; - case hrTOGERR: - // yes, we flip it wrong here so that next time it is actually correct! - pep->bmSndToggle = (regRd(rHRSL) & bmSNDTOGRD) ? 0 : 1; - regWr(rHCTL, (pep->bmSndToggle) ? bmSNDTOG1 : bmSNDTOG0); //set toggle value - break; - default: - goto breakout; - }//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... -breakout: - - 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 = hrSUCCESS; - uint8_t retry_count = 0; - uint16_t nak_count = 0; - - while((long)(millis() - timeout) < 0L) { - regWr(rHXFR, (token | ep)); //launch the transfer - rcode = USB_ERROR_TRANSFER_TIMEOUT; - - while((long)(millis() - timeout) < 0L) //wait for transfer completion - { - tmpdata = regRd(rHIRQ); - - if(tmpdata & bmHXFRDNIRQ) { - regWr(rHIRQ, bmHXFRDNIRQ); //clear the interrupt - rcode = 0x00; - break; - }//if( tmpdata & bmHXFRDNIRQ - - }//while ( millis() < timeout - - //if (rcode != 0x00) //exit if timeout - // return ( rcode); - - rcode = (regRd(rHRSL) & 0x0f); //analyze transfer result - - 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); -} - -/* USB main task. Performs enumeration/cleanup */ -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; - - MAX3421E::Task(); - - 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; - //intentional fallthrough - 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; i < USB_NUMDEVICES; i++) - if(devConfig[i]) - rcode = devConfig[i]->Poll(); - - switch(usb_task_state) { - case USB_DETACHED_SUBSTATE_INITIALIZE: - init(); - - 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: //settle time for just attached device - if((long)(millis() - delay) >= 0L) - usb_task_state = USB_ATTACHED_SUBSTATE_RESET_DEVICE; - else break; // don't fall through - 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 _and_ 20ms has passed we can continue - /* - if (delay < millis()) //20ms passed - usb_task_state = USB_STATE_CONFIGURING; - */ - usb_task_state = USB_ATTACHED_SUBSTATE_WAIT_RESET; - delay = millis() + 20; - } - break; - case USB_ATTACHED_SUBSTATE_WAIT_RESET: - if((long)(millis() - delay) >= 0L) usb_task_state = USB_STATE_CONFIGURING; - else break; // don't fall through - case USB_STATE_CONFIGURING: - - //Serial.print("\r\nConf.LS: "); - //Serial.println(lowspeed, HEX); - - 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: - //MAX3421E::Init(); - 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::AttemptConfig(uint8_t driver, uint8_t parent, uint8_t port, bool lowspeed) { - //printf("AttemptConfig: parent = %i, port = %i\r\n", parent, port); - uint8_t retries = 0; - -again: - uint8_t rcode = devConfig[driver]->ConfigureDevice(parent, port, lowspeed); - if(rcode == USB_ERROR_CONFIG_REQUIRES_ADDITIONAL_RESET) { - if(parent == 0) { - // Send a bus reset on the root interface. - regWr(rHCTL, bmBUSRST); //issue bus reset - delay(102); // delay 102ms, compensate for clock inaccuracy. - } else { - // reset parent port - devConfig[parent]->ResetHubPort(port); - } - } else if(rcode == hrJERR && retries < 3) { // Some devices returns this when plugged in - trying to initialize the device again usually works - delay(100); - retries++; - goto again; - } else if(rcode) - return rcode; - - rcode = devConfig[driver]->Init(parent, port, lowspeed); - if(rcode == hrJERR && retries < 3) { // Some devices returns this when plugged in - trying to initialize the device again usually works - delay(100); - retries++; - goto again; - } - if(rcode) { - // Issue a bus reset, because the device may be in a limbo state - if(parent == 0) { - // Send a bus reset on the root interface. - regWr(rHCTL, bmBUSRST); //issue bus reset - delay(102); // delay 102ms, compensate for clock inaccuracy. - } else { - // reset parent port - devConfig[parent]->ResetHubPort(port); - } - } - return rcode; -} - -/* - * This is broken. We need to enumerate differently. - * It causes major problems with several devices if detected in an unexpected order. - * - * - * Oleg - I wouldn't do anything before the newly connected device is considered sane. - * i.e.(delays are not indicated for brevity): - * 1. reset - * 2. GetDevDescr(); - * 3a. If ACK, continue with allocating address, addressing, etc. - * 3b. Else reset again, count resets, stop at some number (5?). - * 4. When max.number of resets is reached, toggle power/fail - * If desired, this could be modified by performing two resets with GetDevDescr() in the middle - however, from my experience, if a device answers to GDD() - * it doesn't need to be reset again - * New steps proposal: - * 1: get address pool instance. exit on fail - * 2: pUsb->getDevDescr(0, 0, constBufSize, (uint8_t*)buf). exit on fail. - * 3: bus reset, 100ms delay - * 4: set address - * 5: pUsb->setEpInfoEntry(bAddress, 1, epInfo), exit on fail - * 6: while (configurations) { - * for(each configuration) { - * for (each driver) { - * 6a: Ask device if it likes configuration. Returns 0 on OK. - * If successful, the driver configured device. - * The driver now owns the endpoints, and takes over managing them. - * The following will need codes: - * Everything went well, instance consumed, exit with success. - * Instance already in use, ignore it, try next driver. - * Not a supported device, ignore it, try next driver. - * Not a supported configuration for this device, ignore it, try next driver. - * Could not configure device, fatal, exit with fail. - * } - * } - * } - * 7: for(each driver) { - * 7a: Ask device if it knows this VID/PID. Acts exactly like 6a, but using VID/PID - * 8: if we get here, no driver likes the device plugged in, so exit failure. - * - */ -uint8_t USB::Configuring(uint8_t parent, uint8_t port, bool lowspeed) { - //uint8_t bAddress = 0; - //printf("Configuring: parent = %i, port = %i\r\n", parent, port); - uint8_t devConfigIndex; - uint8_t rcode = 0; - uint8_t buf[sizeof (USB_DEVICE_DESCRIPTOR)]; - USB_DEVICE_DESCRIPTOR *udd = reinterpret_cast(buf); - UsbDevice *p = NULL; - EpInfo *oldep_ptr = NULL; - EpInfo epInfo; - - epInfo.epAddr = 0; - epInfo.maxPktSize = 8; - epInfo.epAttribs = 0; - epInfo.bmNakPower = USB_NAK_MAX_POWER; - - //delay(2000); - AddressPool &addrPool = GetAddressPool(); - // Get pointer to pseudo device with address 0 assigned - p = addrPool.GetUsbDevicePtr(0); - if(!p) { - //printf("Configuring error: USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL\r\n"); - return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; - } - - // 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 = getDevDescr(0, 0, sizeof (USB_DEVICE_DESCRIPTOR), (uint8_t*)buf); - - // Restore p->epinfo - p->epinfo = oldep_ptr; - - if(rcode) { - //printf("Configuring error: Can't get USB_DEVICE_DESCRIPTOR\r\n"); - return rcode; - } - - // to-do? - // Allocate new address according to device class - //bAddress = addrPool.AllocAddress(parent, false, port); - - uint16_t vid = udd->idVendor; - uint16_t pid = udd->idProduct; - uint8_t klass = udd->bDeviceClass; - uint8_t subklass = udd->bDeviceSubClass; - // Attempt to configure if VID/PID or device class matches with a driver - // Qualify with subclass too. - // - // VID/PID & class tests default to false for drivers not yet ported - // subclass defaults to true, so you don't have to define it if you don't have to. - // - for(devConfigIndex = 0; devConfigIndex < USB_NUMDEVICES; devConfigIndex++) { - if(!devConfig[devConfigIndex]) continue; // no driver - if(devConfig[devConfigIndex]->GetAddress()) continue; // consumed - if(devConfig[devConfigIndex]->DEVSUBCLASSOK(subklass) && (devConfig[devConfigIndex]->VIDPIDOK(vid, pid) || devConfig[devConfigIndex]->DEVCLASSOK(klass))) { - rcode = AttemptConfig(devConfigIndex, parent, port, lowspeed); - if(rcode != USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED) - break; - } - } - - if(devConfigIndex < USB_NUMDEVICES) { - return rcode; - } - - - // blindly attempt to configure - for(devConfigIndex = 0; devConfigIndex < USB_NUMDEVICES; devConfigIndex++) { - if(!devConfig[devConfigIndex]) continue; - if(devConfig[devConfigIndex]->GetAddress()) continue; // consumed - if(devConfig[devConfigIndex]->DEVSUBCLASSOK(subklass) && (devConfig[devConfigIndex]->VIDPIDOK(vid, pid) || devConfig[devConfigIndex]->DEVCLASSOK(klass))) continue; // If this is true it means it must have returned USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED above - rcode = AttemptConfig(devConfigIndex, parent, port, lowspeed); - - //printf("ERROR ENUMERATING %2.2x\r\n", rcode); - 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 - 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]) continue; - 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)); -} -//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)); -} - -/* Requests Configuration Descriptor. Sends two Get Conf Descr requests. The first one gets the total length of all descriptors, then the second one requests this - total length. The length of the first request can be shorter ( 4 bytes ), however, there are devices which won't work unless this length is set to 9 */ -uint8_t USB::getConfDescr(uint8_t addr, uint8_t ep, uint8_t conf, USBReadParser *p) { - const uint8_t bufSize = 64; - uint8_t buf[bufSize]; - USB_CONFIGURATION_DESCRIPTOR *ucd = reinterpret_cast(buf); - - uint8_t ret = getConfDescr(addr, ep, 9, conf, buf); - - if(ret) - return ret; - - uint16_t total = ucd->wTotalLength; - - //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)); -} -//set address - -uint8_t USB::setAddr(uint8_t oldaddr, uint8_t ep, uint8_t newaddr) { - uint8_t rcode = ctrlReq(oldaddr, ep, bmREQ_SET, USB_REQUEST_SET_ADDRESS, newaddr, 0x00, 0x0000, 0x0000, 0x0000, NULL, NULL); - //delay(2); //per USB 2.0 sect.9.2.6.3 - delay(300); // Older spec says you should wait at least 200ms - return rcode; - //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)); -} - -#endif // defined(USB_METHODS_INLINE) +/* 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 + */ +/* USB functions */ + +#include "Usb.h" + +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(); +} + +/* Initialize data structures */ +void USB::init() { + //devConfigIndex = 0; + bmHubPre = 0; +} + +uint8_t USB::getUsbTaskState(void) { + return ( usb_task_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); + + if(!p || !p->epinfo) + return NULL; + + EpInfo *pep = p->epinfo; + + for(uint8_t i = 0; i < p->epcount; i++) { + if((pep)->epAddr == ep) + return pep; + + 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; + + UsbDevice *p = addrPool.GetUsbDevicePtr(addr); + + if(!p) + return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; + + p->address.devAddress = 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); + + if(!p) + return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; + + if(!p->epinfo) + return USB_ERROR_EPINFO_IS_NULL; + + *ppep = getEpInfoEntry(addr, ep); + + 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 + + uint8_t mode = regRd(rMODE); + + //Serial.print("\r\nMode: "); + //Serial.println( mode, HEX); + //Serial.print("\r\nLS: "); + //Serial.println(p->lowspeed, HEX); + + + + // 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; +} + +/* 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) { + bool direction = false; //request direction, IN or OUT + uint8_t rcode; + SETUP_PKT setup_pkt; + + EpInfo *pep = NULL; + uint16_t nak_limit = 0; + + rcode = SetAddress(addr, ep, &pep, &nak_limit); + + if(rcode) + return rcode; + + 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 + + rcode = dispatchPkt(tokSETUP, ep, nak_limit); //dispatch packet + + if(rcode) //return HRSLT if not zero + return ( rcode); + + if(dataptr != NULL) //data stage, if present + { + if(direction) //IN transfer + { + uint16_t left = total; + + pep->bmRcvToggle = 1; //bmRCVTOG1; + + while(left) { + // Bytes read into buffer + uint16_t read = nbytes; + //uint16_t read = (leftbmRcvToggle = (regRd(rHRSL) & bmSNDTOGRD) ? 0 : 1; + continue; + } + + if(rcode) + return rcode; + + // Invoke callback function if inTransfer completed successfully and callback function pointer is specified + if(!rcode && p) + ((USBReadParser*)p)->Parse(read, dataptr, total - left); + + 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 rcode = SetAddress(addr, ep, &pep, &nak_limit); + + if(rcode) { + USBTRACE3("(USB::InTransfer) SetAddress Failed ", rcode, 0x81); + USBTRACE3("(USB::InTransfer) addr requested ", addr, 0x81); + USBTRACE3("(USB::InTransfer) ep requested ", ep, 0x81); + 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; + + 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 + + // use a 'break' to exit this loop + while(1) { + rcode = dispatchPkt(tokIN, pep->epAddr, nak_limit); //IN packet to EP-'endpoint'. Function takes care of NAKS. + if(rcode == hrTOGERR) { + // yes, we flip it wrong here so that next time it is actually correct! + pep->bmRcvToggle = (regRd(rHRSL) & bmSNDTOGRD) ? 0 : 1; + regWr(rHCTL, (pep->bmRcvToggle) ? bmRCVTOG1 : bmRCVTOG0); //set toggle value + continue; + } + if(rcode) { + //printf(">>>>>>>> Problem! dispatchPkt %2.2x\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 absence of RCVDAVIRQ makes sense is when toggle error occurred. 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 \r\n", pktsize); + // This would be OK, but... + //assert(pktsize <= nbytes); + if(pktsize > nbytes) { + // This can happen. Use of assert on Arduino locks up the Arduino. + // So I will trim the value, and hope for the best. + //printf(">>>>>>>> Problem! Wanted %i bytes but got %i.\r\n", nbytes, pktsize); + pktsize = nbytes; + } + + int16_t mem_left = (int16_t)nbytes - *((int16_t*)nbytesptr); + + if(mem_left < 0) + mem_left = 0; + + data = bytesRd(rRCVFIFO, ((pktsize > mem_left) ? mem_left : pktsize), data); + + 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 = 0; + + uint8_t rcode = SetAddress(addr, ep, &pep, &nak_limit); + + if(rcode) + return rcode; + + 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 = 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); + + while(rcode && ((long)(millis() - timeout) < 0L)) { + switch(rcode) { + case hrNAK: + nak_count++; + if(nak_limit && (nak_count == nak_limit)) + goto breakout; + //return ( rcode); + break; + case hrTIMEOUT: + retry_count++; + if(retry_count == USB_RETRY_LIMIT) + goto breakout; + //return ( rcode); + break; + case hrTOGERR: + // yes, we flip it wrong here so that next time it is actually correct! + pep->bmSndToggle = (regRd(rHRSL) & bmSNDTOGRD) ? 0 : 1; + regWr(rHCTL, (pep->bmSndToggle) ? bmSNDTOG1 : bmSNDTOG0); //set toggle value + break; + default: + goto breakout; + }//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... +breakout: + + 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 = hrSUCCESS; + uint8_t retry_count = 0; + uint16_t nak_count = 0; + + while((long)(millis() - timeout) < 0L) { + regWr(rHXFR, (token | ep)); //launch the transfer + rcode = USB_ERROR_TRANSFER_TIMEOUT; + + while((long)(millis() - timeout) < 0L) //wait for transfer completion + { + tmpdata = regRd(rHIRQ); + + if(tmpdata & bmHXFRDNIRQ) { + regWr(rHIRQ, bmHXFRDNIRQ); //clear the interrupt + rcode = 0x00; + break; + }//if( tmpdata & bmHXFRDNIRQ + + }//while ( millis() < timeout + + //if (rcode != 0x00) //exit if timeout + // return ( rcode); + + rcode = (regRd(rHRSL) & 0x0f); //analyze transfer result + + 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); +} + +/* USB main task. Performs enumeration/cleanup */ +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; + + MAX3421E::Task(); + + 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; + //intentional fallthrough + 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; i < USB_NUMDEVICES; i++) + if(devConfig[i]) + rcode = devConfig[i]->Poll(); + + switch(usb_task_state) { + case USB_DETACHED_SUBSTATE_INITIALIZE: + init(); + + 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: //settle time for just attached device + if((long)(millis() - delay) >= 0L) + usb_task_state = USB_ATTACHED_SUBSTATE_RESET_DEVICE; + else break; // don't fall through + 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 _and_ 20ms has passed we can continue + /* + if (delay < millis()) //20ms passed + usb_task_state = USB_STATE_CONFIGURING; + */ + usb_task_state = USB_ATTACHED_SUBSTATE_WAIT_RESET; + delay = millis() + 20; + } + break; + case USB_ATTACHED_SUBSTATE_WAIT_RESET: + if((long)(millis() - delay) >= 0L) usb_task_state = USB_STATE_CONFIGURING; + else break; // don't fall through + case USB_STATE_CONFIGURING: + + //Serial.print("\r\nConf.LS: "); + //Serial.println(lowspeed, HEX); + + 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: + //MAX3421E::Init(); + 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::AttemptConfig(uint8_t driver, uint8_t parent, uint8_t port, bool lowspeed) { + //printf("AttemptConfig: parent = %i, port = %i\r\n", parent, port); + uint8_t retries = 0; + +again: + uint8_t rcode = devConfig[driver]->ConfigureDevice(parent, port, lowspeed); + if(rcode == USB_ERROR_CONFIG_REQUIRES_ADDITIONAL_RESET) { + if(parent == 0) { + // Send a bus reset on the root interface. + regWr(rHCTL, bmBUSRST); //issue bus reset + delay(102); // delay 102ms, compensate for clock inaccuracy. + } else { + // reset parent port + devConfig[parent]->ResetHubPort(port); + } + } else if(rcode == hrJERR && retries < 3) { // Some devices returns this when plugged in - trying to initialize the device again usually works + delay(100); + retries++; + goto again; + } else if(rcode) + return rcode; + + rcode = devConfig[driver]->Init(parent, port, lowspeed); + if(rcode == hrJERR && retries < 3) { // Some devices returns this when plugged in - trying to initialize the device again usually works + delay(100); + retries++; + goto again; + } + if(rcode) { + // Issue a bus reset, because the device may be in a limbo state + if(parent == 0) { + // Send a bus reset on the root interface. + regWr(rHCTL, bmBUSRST); //issue bus reset + delay(102); // delay 102ms, compensate for clock inaccuracy. + } else { + // reset parent port + devConfig[parent]->ResetHubPort(port); + } + } + return rcode; +} + +/* + * This is broken. We need to enumerate differently. + * It causes major problems with several devices if detected in an unexpected order. + * + * + * Oleg - I wouldn't do anything before the newly connected device is considered sane. + * i.e.(delays are not indicated for brevity): + * 1. reset + * 2. GetDevDescr(); + * 3a. If ACK, continue with allocating address, addressing, etc. + * 3b. Else reset again, count resets, stop at some number (5?). + * 4. When max.number of resets is reached, toggle power/fail + * If desired, this could be modified by performing two resets with GetDevDescr() in the middle - however, from my experience, if a device answers to GDD() + * it doesn't need to be reset again + * New steps proposal: + * 1: get address pool instance. exit on fail + * 2: pUsb->getDevDescr(0, 0, constBufSize, (uint8_t*)buf). exit on fail. + * 3: bus reset, 100ms delay + * 4: set address + * 5: pUsb->setEpInfoEntry(bAddress, 1, epInfo), exit on fail + * 6: while (configurations) { + * for(each configuration) { + * for (each driver) { + * 6a: Ask device if it likes configuration. Returns 0 on OK. + * If successful, the driver configured device. + * The driver now owns the endpoints, and takes over managing them. + * The following will need codes: + * Everything went well, instance consumed, exit with success. + * Instance already in use, ignore it, try next driver. + * Not a supported device, ignore it, try next driver. + * Not a supported configuration for this device, ignore it, try next driver. + * Could not configure device, fatal, exit with fail. + * } + * } + * } + * 7: for(each driver) { + * 7a: Ask device if it knows this VID/PID. Acts exactly like 6a, but using VID/PID + * 8: if we get here, no driver likes the device plugged in, so exit failure. + * + */ +uint8_t USB::Configuring(uint8_t parent, uint8_t port, bool lowspeed) { + //uint8_t bAddress = 0; + //printf("Configuring: parent = %i, port = %i\r\n", parent, port); + uint8_t devConfigIndex; + uint8_t rcode = 0; + uint8_t buf[sizeof (USB_DEVICE_DESCRIPTOR)]; + USB_DEVICE_DESCRIPTOR *udd = reinterpret_cast(buf); + UsbDevice *p = NULL; + EpInfo *oldep_ptr = NULL; + EpInfo epInfo; + + epInfo.epAddr = 0; + epInfo.maxPktSize = 8; + epInfo.epAttribs = 0; + epInfo.bmNakPower = USB_NAK_MAX_POWER; + + //delay(2000); + AddressPool &addrPool = GetAddressPool(); + // Get pointer to pseudo device with address 0 assigned + p = addrPool.GetUsbDevicePtr(0); + if(!p) { + //printf("Configuring error: USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL\r\n"); + return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; + } + + // 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 = getDevDescr(0, 0, sizeof (USB_DEVICE_DESCRIPTOR), (uint8_t*)buf); + + // Restore p->epinfo + p->epinfo = oldep_ptr; + + if(rcode) { + //printf("Configuring error: Can't get USB_DEVICE_DESCRIPTOR\r\n"); + return rcode; + } + + // to-do? + // Allocate new address according to device class + //bAddress = addrPool.AllocAddress(parent, false, port); + + uint16_t vid = udd->idVendor; + uint16_t pid = udd->idProduct; + uint8_t klass = udd->bDeviceClass; + uint8_t subklass = udd->bDeviceSubClass; + // Attempt to configure if VID/PID or device class matches with a driver + // Qualify with subclass too. + // + // VID/PID & class tests default to false for drivers not yet ported + // subclass defaults to true, so you don't have to define it if you don't have to. + // + for(devConfigIndex = 0; devConfigIndex < USB_NUMDEVICES; devConfigIndex++) { + if(!devConfig[devConfigIndex]) continue; // no driver + if(devConfig[devConfigIndex]->GetAddress()) continue; // consumed + if(devConfig[devConfigIndex]->DEVSUBCLASSOK(subklass) && (devConfig[devConfigIndex]->VIDPIDOK(vid, pid) || devConfig[devConfigIndex]->DEVCLASSOK(klass))) { + rcode = AttemptConfig(devConfigIndex, parent, port, lowspeed); + if(rcode != USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED) + break; + } + } + + if(devConfigIndex < USB_NUMDEVICES) { + return rcode; + } + + + // blindly attempt to configure + for(devConfigIndex = 0; devConfigIndex < USB_NUMDEVICES; devConfigIndex++) { + if(!devConfig[devConfigIndex]) continue; + if(devConfig[devConfigIndex]->GetAddress()) continue; // consumed + if(devConfig[devConfigIndex]->DEVSUBCLASSOK(subklass) && (devConfig[devConfigIndex]->VIDPIDOK(vid, pid) || devConfig[devConfigIndex]->DEVCLASSOK(klass))) continue; // If this is true it means it must have returned USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED above + rcode = AttemptConfig(devConfigIndex, parent, port, lowspeed); + + //printf("ERROR ENUMERATING %2.2x\r\n", rcode); + 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 + 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]) continue; + 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)); +} +//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)); +} + +/* Requests Configuration Descriptor. Sends two Get Conf Descr requests. The first one gets the total length of all descriptors, then the second one requests this + total length. The length of the first request can be shorter ( 4 bytes ), however, there are devices which won't work unless this length is set to 9 */ +uint8_t USB::getConfDescr(uint8_t addr, uint8_t ep, uint8_t conf, USBReadParser *p) { + const uint8_t bufSize = 64; + uint8_t buf[bufSize]; + USB_CONFIGURATION_DESCRIPTOR *ucd = reinterpret_cast(buf); + + uint8_t ret = getConfDescr(addr, ep, 9, conf, buf); + + if(ret) + return ret; + + uint16_t total = ucd->wTotalLength; + + //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)); +} +//set address + +uint8_t USB::setAddr(uint8_t oldaddr, uint8_t ep, uint8_t newaddr) { + uint8_t rcode = ctrlReq(oldaddr, ep, bmREQ_SET, USB_REQUEST_SET_ADDRESS, newaddr, 0x00, 0x0000, 0x0000, 0x0000, NULL, NULL); + //delay(2); //per USB 2.0 sect.9.2.6.3 + delay(300); // Older spec says you should wait at least 200ms + return rcode; + //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)); +} + +#endif // defined(USB_METHODS_INLINE) diff --git a/Usb.h b/Usb.h index 8fbac80d..fa801891 100644 --- a/Usb.h +++ b/Usb.h @@ -1,41 +1,41 @@ -/* 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 - */ -/* USB functions */ -#ifndef _usb_h_ -#define _usb_h_ - -// WARNING: Do not change the order of includes, or stuff will break! -#include -#include -#include - -// None of these should ever be included by a driver, or a user's sketch. -#include "settings.h" -#include "printhex.h" -#include "avrpins.h" -#include "message.h" -#include "hexdump.h" -#include "sink_parser.h" -#include "max3421e.h" -#include "address.h" -#include "usb_ch9.h" -#include "usbhost.h" -#include "UsbCore.h" -#include "parsetools.h" -#include "confdescparser.h" - -#endif //_usb_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 + */ +/* USB functions */ +#ifndef _usb_h_ +#define _usb_h_ + +// WARNING: Do not change the order of includes, or stuff will break! +#include +#include +#include + +// None of these should ever be included by a driver, or a user's sketch. +#include "settings.h" +#include "printhex.h" +#include "avrpins.h" +#include "message.h" +#include "hexdump.h" +#include "sink_parser.h" +#include "max3421e.h" +#include "address.h" +#include "usb_ch9.h" +#include "usbhost.h" +#include "UsbCore.h" +#include "parsetools.h" +#include "confdescparser.h" + +#endif //_usb_h_ diff --git a/UsbCore.h b/UsbCore.h index 0ec2b445..d76f1858 100644 --- a/UsbCore.h +++ b/UsbCore.h @@ -18,7 +18,7 @@ e-mail : support@circuitsathome.com #if !defined(_usb_h_) || defined(USBCORE_H) #error "Never include UsbCore.h directly; include Usb.h instead" #else -#define USBCORE_H +#define USBCORE_H // Not used anymore? If anyone uses this, please let us know so that this may be // moved to the proper place, settings.h. @@ -46,57 +46,57 @@ typedef MAX3421e MAX3421E; // Official Arduinos (UNO, Duemilanove, Mega #define bmREQ_SET USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_STANDARD|USB_SETUP_RECIPIENT_DEVICE //set request type for all but 'set feature' and 'set interface' #define bmREQ_CL_GET_INTF USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE //get interface request type -// D7 data transfer direction (0 - host-to-device, 1 - device-to-host) -// D6-5 Type (0- standard, 1 - class, 2 - vendor, 3 - reserved) -// D4-0 Recipient (0 - device, 1 - interface, 2 - endpoint, 3 - other, 4..31 - reserved) +// D7 data transfer direction (0 - host-to-device, 1 - device-to-host) +// D6-5 Type (0- standard, 1 - class, 2 - vendor, 3 - reserved) +// D4-0 Recipient (0 - device, 1 - interface, 2 - endpoint, 3 - other, 4..31 - reserved) // 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_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_MASS_STORAGE 0x08 // Mass Storage -#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_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_APP_SPECIFIC 0xfe // Application Specific -#define USB_CLASS_VENDOR_SPECIFIC 0xff // Vendor Specific +#define USB_CLASS_USE_CLASS_INFO 0x00 // Use Class Info in the Interface Descriptors +#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_MASS_STORAGE 0x08 // Mass Storage +#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_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_APP_SPECIFIC 0xfe // Application Specific +#define USB_CLASS_VENDOR_SPECIFIC 0xff // Vendor Specific // Additional Error Codes -#define USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED 0xD1 -#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_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_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED 0xD1 +#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_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_CONFIG_REQUIRES_ADDITIONAL_RESET 0xE0 #define USB_ERROR_FailGetDevDescr 0xE1 #define USB_ERROR_FailSetDevTblEntry 0xE2 #define USB_ERROR_FailGetConfDescr 0xE3 -#define USB_ERROR_TRANSFER_TIMEOUT 0xFF +#define USB_ERROR_TRANSFER_TIMEOUT 0xFF -#define USB_XFER_TIMEOUT 10000 //30000 // (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 // 3 retry limit for a transfer -#define USB_SETTLE_DELAY 200 //settle delay in milliseconds +#define USB_XFER_TIMEOUT 5000 // (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 // 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 @@ -258,7 +258,7 @@ public: private: void init(); - uint8_t SetAddress(uint8_t addr, uint8_t ep, EpInfo **ppep, uint16_t &nak_limit); + uint8_t SetAddress(uint8_t addr, uint8_t ep, EpInfo **ppep, uint16_t *nak_limit); uint8_t OutTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t nbytes, uint8_t *data); uint8_t InTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t *nbytesptr, uint8_t *data); uint8_t AttemptConfig(uint8_t driver, uint8_t parent, uint8_t port, bool lowspeed); @@ -293,4 +293,4 @@ inline uint8_t USB::setConf(uint8_t addr, uint8_t ep, uint8_t conf_value) { #endif // defined(USB_METHODS_INLINE) -#endif /* USBCORE_H */ +#endif /* USBCORE_H */ diff --git a/WiiCameraReadme.md b/WiiCameraReadme.md index 2309b4f9..8577d73f 100644 --- a/WiiCameraReadme.md +++ b/WiiCameraReadme.md @@ -10,4 +10,4 @@ This library implements the following settings: * Data Format: Extended mode (0x03). Full mode is not working yet. The output reports 0x3e and 0x3f need tampering with * In this mode the camera outputs x and y coordinates and a size dimension for the 4 brightest points. -Again, read through to get an understanding of the camera and its settings. \ No newline at end of file +Again, read through to get an understanding of the camera and its settings. diff --git a/XBOXOLD.cpp b/XBOXOLD.cpp index 78e6e9a5..990b67ca 100644 --- a/XBOXOLD.cpp +++ b/XBOXOLD.cpp @@ -320,7 +320,7 @@ int16_t XBOXOLD::getAnalogHat(AnalogHatEnum a) { /* Xbox Controller commands */ void XBOXOLD::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); + pUsb->ctrlReq(bAddress, epInfo[XBOX_CONTROL_PIPE].epAddr, bmREQ_HIDOUT, HID_REQUEST_SET_REPORT, 0x00, 0x02, 0x00, nbytes, nbytes, data, NULL); } void XBOXOLD::setRumbleOn(uint8_t lValue, uint8_t rValue) { diff --git a/XBOXOLD.h b/XBOXOLD.h index 0219c5a4..9a36b5cc 100644 --- a/XBOXOLD.h +++ b/XBOXOLD.h @@ -19,7 +19,7 @@ #define _xboxold_h_ #include "Usb.h" -#include "Hid.h" +#include "hid.h" #include "controllerEnums.h" /* Data Xbox taken from descriptors */ diff --git a/XBOXUSB.cpp b/XBOXUSB.cpp index ddece21b..ee0536e2 100644 --- a/XBOXUSB.cpp +++ b/XBOXUSB.cpp @@ -314,7 +314,7 @@ int16_t XBOXUSB::getAnalogHat(AnalogHatEnum 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); + pUsb->ctrlReq(bAddress, epInfo[XBOX_CONTROL_PIPE].epAddr, bmREQ_HIDOUT, HID_REQUEST_SET_REPORT, 0x00, 0x02, 0x00, nbytes, nbytes, data, NULL); } void XBOXUSB::setLedRaw(uint8_t value) { diff --git a/XBOXUSB.h b/XBOXUSB.h index de814489..1ab37851 100644 --- a/XBOXUSB.h +++ b/XBOXUSB.h @@ -19,7 +19,7 @@ #define _xboxusb_h_ #include "Usb.h" -#include "Hid.h" +#include "hid.h" #include "xboxEnums.h" /* Data Xbox 360 taken from descriptors */ diff --git a/address.h b/address.h index 158e287d..c3e1b314 100644 --- a/address.h +++ b/address.h @@ -1,282 +1,282 @@ -/* 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(_usb_h_) || defined(__ADDRESS_H__) -#error "Never include address.h directly; include Usb.h instead" -#else -#define __ADDRESS_H__ - - - -/* NAK powers. To save space in endpoint data structure, amount of retries before giving up and returning 0x4 is stored in */ -/* bmNakPower as a power of 2. The actual nak_limit is then calculated as nak_limit = ( 2^bmNakPower - 1) */ -#define USB_NAK_MAX_POWER 15 //NAK binary order maximum value -#define USB_NAK_DEFAULT 14 //default 32K-1 NAKs before giving up -#define USB_NAK_NOWAIT 1 //Single NAK stops transfer -#define USB_NAK_NONAK 0 //Do not count NAKs, stop retrying after USB Timeout - -struct EpInfo { - uint8_t epAddr; // Endpoint address - uint8_t maxPktSize; // Maximum packet size - - union { - uint8_t epAttribs; - - struct { - 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)); - -// 7 6 5 4 3 2 1 0 -// --------------------------------- -// | | H | P | P | P | A | A | A | -// --------------------------------- -// -// H - if 1 the address is a hub address -// P - parent hub address -// A - device address / port number in case of hub -// - -struct UsbDeviceAddress { - - union { - - struct { - uint8_t bmAddress : 3; // device address/port number - uint8_t bmParent : 3; // parent hub address - uint8_t bmHub : 1; // hub flag - uint8_t bmReserved : 1; // reserved, must be zero - } __attribute__((packed)); - uint8_t devAddress; - }; -} __attribute__((packed)); - -#define bmUSB_DEV_ADDR_ADDRESS 0x07 -#define bmUSB_DEV_ADDR_PARENT 0x38 -#define bmUSB_DEV_ADDR_HUB 0x40 - -struct UsbDevice { - EpInfo *epinfo; // endpoint info pointer - UsbDeviceAddress address; - uint8_t epcount; // number of endpoints - bool lowspeed; // indicates if a device is the low speed one - // uint8_t devclass; // device class -} __attribute__((packed)); - -class AddressPool { -public: - virtual UsbDevice* GetUsbDevicePtr(uint8_t addr) = 0; - virtual uint8_t AllocAddress(uint8_t parent, bool is_hub = false, uint8_t port = 0) = 0; - virtual void FreeAddress(uint8_t addr) = 0; -}; - -typedef void (*UsbDeviceHandleFunc)(UsbDevice *pdev); - -#define ADDR_ERROR_INVALID_INDEX 0xFF -#define ADDR_ERROR_INVALID_ADDRESS 0xFF - -template -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 - - UsbDevice thePool[MAX_DEVICES_ALLOWED]; - - // Initializes address pool entry - - void InitEntry(uint8_t index) { - thePool[index].address.devAddress = 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; i++) { - if(thePool[i].address.devAddress == address) - return i; - } - return 0; - }; - - // 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(thePool[i].address.bmParent == addr.bmAddress) - return i; - } - return 0; - }; - - // Frees address entry specified by index parameter - - void FreeAddressByIndex(uint8_t index) { - // Zero field is reserved and should not be affected - if(index == 0) - return; - - UsbDeviceAddress uda = thePool[index].address; - // If a hub was switched off all port addresses should be freed - if(uda.bmHub == 1) { - for(uint8_t i = 1; (i = FindChildIndex(uda, i));) - FreeAddressByIndex(i); - - // If the hub had the last allocated address, hubCounter should be decremented - if(hubCounter == uda.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; - }; - -public: - - AddressPoolImpl() : hubCounter(0) { - // Zero address is reserved - InitEntry(0); - - thePool[0].address.devAddress = 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; - - InitAllAddresses(); - }; - - // Returns a pointer to a specified address entry - - virtual UsbDevice* GetUsbDevicePtr(uint8_t addr) { - if(!addr) - return thePool; - - uint8_t index = FindAddressIndex(addr); - - return (!index) ? NULL : thePool + index; - }; - - // Performs an operation specified by pfunc for each addressed device - - void ForEachUsbDevice(UsbDeviceHandleFunc pfunc) { - if(!pfunc) - return; - - for(uint8_t i = 1; i < MAX_DEVICES_ALLOWED; i++) - if(thePool[i].address.devAddress) - pfunc(thePool + i); - }; - - // Allocates new address - - virtual uint8_t AllocAddress(uint8_t parent, bool is_hub = false, uint8_t port = 0) { - /* if (parent != 0 && port == 0) - USB_HOST_SERIAL.println("PRT:0"); */ - UsbDeviceAddress _parent; - _parent.devAddress = parent; - if(_parent.bmReserved || port > 7) - //if(parent > 127 || port > 7) - return 0; - - 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 - return 0; - - if(_parent.devAddress == 0) { - if(is_hub) { - thePool[index].address.devAddress = 0x41; - hubCounter++; - } else - thePool[index].address.devAddress = 1; - - return thePool[index].address.devAddress; - } - - UsbDeviceAddress addr; - addr.devAddress = 0; // Ensure all bits are zero - addr.bmParent = _parent.bmAddress; - if(is_hub) { - addr.bmHub = 1; - addr.bmAddress = ++hubCounter; - } else { - addr.bmHub = 0; - addr.bmAddress = port; - } - thePool[index].address = addr; - /* - USB_HOST_SERIAL.print("Addr:"); - USB_HOST_SERIAL.print(addr.bmHub, HEX); - USB_HOST_SERIAL.print("."); - USB_HOST_SERIAL.print(addr.bmParent, HEX); - USB_HOST_SERIAL.print("."); - USB_HOST_SERIAL.println(addr.bmAddress, HEX); - */ - return thePool[index].address.devAddress; - }; - - // 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; i +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 + + UsbDevice thePool[MAX_DEVICES_ALLOWED]; + + // Initializes address pool entry + + void InitEntry(uint8_t index) { + thePool[index].address.devAddress = 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; i++) { + if(thePool[i].address.devAddress == address) + return i; + } + return 0; + }; + + // 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(thePool[i].address.bmParent == addr.bmAddress) + return i; + } + return 0; + }; + + // Frees address entry specified by index parameter + + void FreeAddressByIndex(uint8_t index) { + // Zero field is reserved and should not be affected + if(index == 0) + return; + + UsbDeviceAddress uda = thePool[index].address; + // If a hub was switched off all port addresses should be freed + if(uda.bmHub == 1) { + for(uint8_t i = 1; (i = FindChildIndex(uda, i));) + FreeAddressByIndex(i); + + // If the hub had the last allocated address, hubCounter should be decremented + if(hubCounter == uda.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; + }; + +public: + + AddressPoolImpl() : hubCounter(0) { + // Zero address is reserved + InitEntry(0); + + thePool[0].address.devAddress = 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; + + InitAllAddresses(); + }; + + // Returns a pointer to a specified address entry + + virtual UsbDevice* GetUsbDevicePtr(uint8_t addr) { + if(!addr) + return thePool; + + uint8_t index = FindAddressIndex(addr); + + return (!index) ? NULL : thePool + index; + }; + + // Performs an operation specified by pfunc for each addressed device + + void ForEachUsbDevice(UsbDeviceHandleFunc pfunc) { + if(!pfunc) + return; + + for(uint8_t i = 1; i < MAX_DEVICES_ALLOWED; i++) + if(thePool[i].address.devAddress) + pfunc(thePool + i); + }; + + // Allocates new address + + virtual uint8_t AllocAddress(uint8_t parent, bool is_hub = false, uint8_t port = 0) { + /* if (parent != 0 && port == 0) + USB_HOST_SERIAL.println("PRT:0"); */ + UsbDeviceAddress _parent; + _parent.devAddress = parent; + if(_parent.bmReserved || port > 7) + //if(parent > 127 || port > 7) + return 0; + + 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 + return 0; + + if(_parent.devAddress == 0) { + if(is_hub) { + thePool[index].address.devAddress = 0x41; + hubCounter++; + } else + thePool[index].address.devAddress = 1; + + return thePool[index].address.devAddress; + } + + UsbDeviceAddress addr; + addr.devAddress = 0; // Ensure all bits are zero + addr.bmParent = _parent.bmAddress; + if(is_hub) { + addr.bmHub = 1; + addr.bmAddress = ++hubCounter; + } else { + addr.bmHub = 0; + addr.bmAddress = port; + } + thePool[index].address = addr; + /* + USB_HOST_SERIAL.print("Addr:"); + USB_HOST_SERIAL.print(addr.bmHub, HEX); + USB_HOST_SERIAL.print("."); + USB_HOST_SERIAL.print(addr.bmParent, HEX); + USB_HOST_SERIAL.print("."); + USB_HOST_SERIAL.println(addr.bmAddress, HEX); + */ + return thePool[index].address.devAddress; + }; + + // 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 - } -} - -uint8_t ADK::ConfigureDevice(uint8_t parent, uint8_t port, bool lowspeed) { - return Init(parent, port, lowspeed); // Just call Init. Yes, really! -} - -/* 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)]; - USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast(buf); - uint8_t rcode; - uint8_t num_of_conf; // number of configurations - UsbDevice *p = NULL; - EpInfo *oldep_ptr = NULL; - - // 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 = udd->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); - // Spec says you should wait at least 200ms. - //delay(300); - - 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(udd->idVendor == ADK_VID && - (udd->idProduct == ADK_PID || udd->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 = udd->bNumConfigurations; - - //USBTRACE2("\r\nNC:",num_of_conf); - for(uint8_t i = 0; i < num_of_conf; i++) { - ConfigDescParser < 0, 0, 0, 0 > confDescrParser(this); - delay(1); - rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser); -#if defined(XOOM) - //added by Jaylen Scott Vanorden - if(rcode) { - USBTRACE2("\r\nGot 1st bad code for config: ", rcode); - // 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 FailSetConfDescr; - } - /* 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; - delay(1); - rcode = getProto((uint8_t*) & adkproto); -#if defined(XOOM) - //added by Jaylen Scott Vanorden - if(rcode) { - USBTRACE2("\r\nGot 1st bad code for proto: ", rcode); - // Try once more - rcode = getProto((uint8_t*) & adkproto); - } -#endif - if(rcode) { - goto FailGetProto; //init fails - } - USBTRACE2("\r\nADK protocol rev. ", adkproto); - } - - delay(100); - - //sending ID strings - sendStr(ACCESSORY_STRING_MANUFACTURER, manufacturer); - delay(10); - sendStr(ACCESSORY_STRING_MODEL, model); - delay(10); - sendStr(ACCESSORY_STRING_DESCRIPTION, description); - delay(10); - sendStr(ACCESSORY_STRING_VERSION, version); - delay(10); - sendStr(ACCESSORY_STRING_URI, uri); - delay(10); - sendStr(ACCESSORY_STRING_SERIAL, serial); - - delay(100); - - //switch to accessory mode - //the Android phone will reset - rcode = switchAcc(); - if(rcode) { - goto FailSwAcc; //init fails - } - rcode = USB_ERROR_CONFIG_REQUIRES_ADDITIONAL_RESET; - delay(100); // Give Android a chance to do its reset. This is a guess, and possibly could be lower. - goto SwAttempt; //switch to accessory mode attempted - - /* diagnostic messages */ -FailGetDevDescr: -#ifdef DEBUG_USB_HOST - NotifyFailGetDevDescr(rcode); - goto Fail; -#endif - -FailSetDevTblEntry: -#ifdef DEBUG_USB_HOST - NotifyFailSetDevTblEntry(rcode); - goto Fail; -#endif - -FailGetConfDescr: -#ifdef DEBUG_USB_HOST - NotifyFailGetConfDescr(rcode); - goto Fail; -#endif - -FailSetConfDescr: -#ifdef DEBUG_USB_HOST - NotifyFailSetConfDescr(rcode); - goto Fail; -#endif - -FailGetProto: -#ifdef DEBUG_USB_HOST - USBTRACE("\r\ngetProto:"); - goto Fail; -#endif - -FailSwAcc: -#ifdef DEBUG_USB_HOST - USBTRACE("\r\nswAcc:"); - goto Fail; -#endif - - //FailOnInit: - // USBTRACE("OnInit:"); - // goto Fail; - // -SwAttempt: -#ifdef DEBUG_USB_HOST - USBTRACE("\r\nAccessory mode switch attempt"); -Fail: -#endif - //USBTRACE2("\r\nADK Init Failed, error code: ", rcode); - //NotifyFail(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; - - if((pep->bmAttributes & 0x02) == 2) { - uint8_t 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); -} +/* 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 = 0; + epInfo[i].bmNakPower = (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER; + }//for(uint8_t i=0; iRegisterDeviceClass(this); //set devConfig[] entry + } +} + +uint8_t ADK::ConfigureDevice(uint8_t parent, uint8_t port, bool lowspeed) { + return Init(parent, port, lowspeed); // Just call Init. Yes, really! +} + +/* 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)]; + USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast(buf); + uint8_t rcode; + uint8_t num_of_conf; // number of configurations + UsbDevice *p = NULL; + EpInfo *oldep_ptr = NULL; + + // 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 = udd->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); + // Spec says you should wait at least 200ms. + //delay(300); + + 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(udd->idVendor == ADK_VID && + (udd->idProduct == ADK_PID || udd->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 = udd->bNumConfigurations; + + //USBTRACE2("\r\nNC:",num_of_conf); + for(uint8_t i = 0; i < num_of_conf; i++) { + ConfigDescParser < 0, 0, 0, 0 > confDescrParser(this); + delay(1); + rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser); +#if defined(XOOM) + //added by Jaylen Scott Vanorden + if(rcode) { + USBTRACE2("\r\nGot 1st bad code for config: ", rcode); + // 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 FailSetConfDescr; + } + /* 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; + delay(1); + rcode = getProto((uint8_t*) & adkproto); +#if defined(XOOM) + //added by Jaylen Scott Vanorden + if(rcode) { + USBTRACE2("\r\nGot 1st bad code for proto: ", rcode); + // Try once more + rcode = getProto((uint8_t*) & adkproto); + } +#endif + if(rcode) { + goto FailGetProto; //init fails + } + USBTRACE2("\r\nADK protocol rev. ", adkproto); + } + + delay(100); + + //sending ID strings + sendStr(ACCESSORY_STRING_MANUFACTURER, manufacturer); + delay(10); + sendStr(ACCESSORY_STRING_MODEL, model); + delay(10); + sendStr(ACCESSORY_STRING_DESCRIPTION, description); + delay(10); + sendStr(ACCESSORY_STRING_VERSION, version); + delay(10); + sendStr(ACCESSORY_STRING_URI, uri); + delay(10); + sendStr(ACCESSORY_STRING_SERIAL, serial); + + delay(100); + + //switch to accessory mode + //the Android phone will reset + rcode = switchAcc(); + if(rcode) { + goto FailSwAcc; //init fails + } + rcode = USB_ERROR_CONFIG_REQUIRES_ADDITIONAL_RESET; + delay(100); // Give Android a chance to do its reset. This is a guess, and possibly could be lower. + goto SwAttempt; //switch to accessory mode attempted + + /* diagnostic messages */ +FailGetDevDescr: +#ifdef DEBUG_USB_HOST + NotifyFailGetDevDescr(rcode); + goto Fail; +#endif + +FailSetDevTblEntry: +#ifdef DEBUG_USB_HOST + NotifyFailSetDevTblEntry(rcode); + goto Fail; +#endif + +FailGetConfDescr: +#ifdef DEBUG_USB_HOST + NotifyFailGetConfDescr(rcode); + goto Fail; +#endif + +FailSetConfDescr: +#ifdef DEBUG_USB_HOST + NotifyFailSetConfDescr(rcode); + goto Fail; +#endif + +FailGetProto: +#ifdef DEBUG_USB_HOST + USBTRACE("\r\ngetProto:"); + goto Fail; +#endif + +FailSwAcc: +#ifdef DEBUG_USB_HOST + USBTRACE("\r\nswAcc:"); + goto Fail; +#endif + + //FailOnInit: + // USBTRACE("OnInit:"); + // goto Fail; + // +SwAttempt: +#ifdef DEBUG_USB_HOST + USBTRACE("\r\nAccessory mode switch attempt"); +Fail: +#endif + //USBTRACE2("\r\nADK Init Failed, error code: ", rcode); + //NotifyFail(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; + + if((pep->bmAttributes & 0x02) == 2) { + uint8_t 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); + D_PrintHex (ep_ptr->bLength, 0x80); + Notify(PSTR("\r\nType:\t\t"), 0x80); + D_PrintHex (ep_ptr->bDescriptorType, 0x80); + Notify(PSTR("\r\nAddress:\t"), 0x80); + D_PrintHex (ep_ptr->bEndpointAddress, 0x80); + Notify(PSTR("\r\nAttributes:\t"), 0x80); + D_PrintHex (ep_ptr->bmAttributes, 0x80); + Notify(PSTR("\r\nMaxPktSize:\t"), 0x80); + D_PrintHex (ep_ptr->wMaxPacketSize, 0x80); + Notify(PSTR("\r\nPoll Intrv:\t"), 0x80); + D_PrintHex (ep_ptr->bInterval, 0x80); + Notify(PSTR("\r\n"), 0x80); +} diff --git a/adk.h b/adk.h index a167f425..4a2920b8 100644 --- a/adk.h +++ b/adk.h @@ -1,140 +1,140 @@ -/* 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 "Usb.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 - uint8_t ConfigureDevice(uint8_t parent, uint8_t port, bool lowspeed); - uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed); - uint8_t Release(); - - virtual uint8_t Poll() { - return 0; - }; - - virtual uint8_t GetAddress() { - return bAddress; - }; - - virtual bool isReady() { - return ready; - }; - - virtual bool VIDPIDOK(uint16_t vid, uint16_t pid) { - return (vid == ADK_VID && (pid == ADK_PID || pid == ADB_PID)); - }; - - //UsbConfigXtracter implementation - 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_ +/* 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 "Usb.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 + uint8_t ConfigureDevice(uint8_t parent, uint8_t port, bool lowspeed); + uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed); + uint8_t Release(); + + virtual uint8_t Poll() { + return 0; + }; + + virtual uint8_t GetAddress() { + return bAddress; + }; + + virtual bool isReady() { + return ready; + }; + + virtual bool VIDPIDOK(uint16_t vid, uint16_t pid) { + return (vid == ADK_VID && (pid == ADK_PID || pid == ADB_PID)); + }; + + //UsbConfigXtracter implementation + 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_ diff --git a/avrpins.h b/avrpins.h index 46bcf722..7acf492a 100644 --- a/avrpins.h +++ b/avrpins.h @@ -1,1117 +1,1117 @@ -/* 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 - */ - -/* derived from Konstantin Chizhov's AVR port templates */ - -#if !defined(_usb_h_) || defined(_avrpins_h_) -#error "Never include avrpins.h directly; include Usb.h instead" -#else -#define _avrpins_h_ - -#if defined(__AVR__) - -// pointers are 16 bits on AVR -#define pgm_read_pointer(p) pgm_read_word(p) - -// Support for these boards needs to be manually activated in settings.h or in a makefile -#if !defined(BOARD_MEGA_ADK) && defined(__AVR_ATmega2560__) && (USE_UHS_MEGA_ADK || defined(ARDUINO_AVR_ADK)) -#define BOARD_MEGA_ADK -#elif !defined(BOARD_BLACK_WIDDOW) && USE_UHS_BLACK_WIDDOW -#define BOARD_BLACK_WIDDOW -#endif - -#ifdef PORTA -#define USE_PORTA -#endif -#ifdef PORTB -#define USE_PORTB -#endif -#ifdef PORTC -#define USE_PORTC -#endif -#ifdef PORTD -#define USE_PORTD -#endif -#ifdef PORTE -#define USE_PORTE -#endif -#ifdef PORTF -#define USE_PORTF -#endif -#ifdef PORTG -#define USE_PORTG -#endif -#ifdef PORTH -#define USE_PORTH -#endif -#ifdef PORTJ -#define USE_PORTJ -#endif -#ifdef PORTK -#define USE_PORTK -#endif -#ifdef PORTL -#define USE_PORTL -#endif -#ifdef PORTQ -#define USE_PORTQ -#endif -#ifdef PORTR -#define USE_PORTR -#endif - -#ifdef TCCR0A -#define USE_TCCR0A -#endif -#ifdef TCCR1A -#define USE_TCCR1A -#endif -#ifdef TCCR2A -#define USE_TCCR2A -#endif - -//Port definitions for AtTiny, AtMega families. - -#define MAKE_PORT(portName, ddrName, pinName, className, ID) \ - class className{\ - public:\ - typedef uint8_t DataT;\ - public:\ - static void Write(DataT value){portName = value;}\ - static void ClearAndSet(DataT clearMask, DataT value){portName = (portName & ~clearMask) | value;}\ - static DataT Read(){return portName;}\ - static void DirWrite(DataT value){ddrName = value;}\ - static DataT DirRead(){return ddrName;}\ - static void Set(DataT value){portName |= value;}\ - static void Clear(DataT value){portName &= ~value;}\ - static void Toggle(DataT value){portName ^= value;}\ - static void DirSet(DataT value){ddrName |= value;}\ - static void DirClear(DataT value){ddrName &= ~value;}\ - static void DirToggle(DataT value){ddrName ^= value;}\ - static DataT PinRead(){return pinName;}\ - enum{Id = ID};\ - enum{Width=sizeof(DataT)*8};\ - }; - -// TCCR registers to set/clear Arduino PWM -#define MAKE_TCCR(TccrName, className) \ - class className{\ - public:\ - typedef uint8_t DataT;\ - public:\ - static void Write(DataT value){TccrName = value;}\ - static void ClearAndSet(DataT clearMask, DataT value){TccrName = (TccrName & ~clearMask) | value;}\ - static DataT Read(){return TccrName;}\ - static void Set(DataT value){TccrName |= value;}\ - static void Clear(DataT value){TccrName &= ~value;}\ - static void Toggle(DataT value){TccrName ^= value;}\ - enum{Width=sizeof(DataT)*8};\ - }; - -#ifdef USE_PORTA - -MAKE_PORT(PORTA, DDRA, PINA, Porta, 'A') -#endif -#ifdef USE_PORTB -MAKE_PORT(PORTB, DDRB, PINB, Portb, 'B') -#endif -#ifdef USE_PORTC -MAKE_PORT(PORTC, DDRC, PINC, Portc, 'C') -#endif -#ifdef USE_PORTD -MAKE_PORT(PORTD, DDRD, PIND, Portd, 'D') -#endif -#ifdef USE_PORTE -MAKE_PORT(PORTE, DDRE, PINE, Porte, 'E') -#endif -#ifdef USE_PORTF -MAKE_PORT(PORTF, DDRF, PINF, Portf, 'F') -#endif -#ifdef USE_PORTG -MAKE_PORT(PORTG, DDRG, PING, Portg, 'G') -#endif -#ifdef USE_PORTH -MAKE_PORT(PORTH, DDRH, PINH, Porth, 'H') -#endif -#ifdef USE_PORTJ -MAKE_PORT(PORTJ, DDRJ, PINJ, Portj, 'J') -#endif -#ifdef USE_PORTK -MAKE_PORT(PORTK, DDRK, PINK, Portk, 'K') -#endif -#ifdef USE_PORTL -MAKE_PORT(PORTL, DDRL, PINL, Portl, 'L') -#endif -#ifdef USE_PORTQ -MAKE_PORT(PORTQ, DDRQ, PINQ, Portq, 'Q') -#endif -#ifdef USE_PORTR -MAKE_PORT(PORTR, DDRR, PINR, Portr, 'R') -#endif - -#ifdef USE_TCCR0A -MAKE_TCCR(TCCR0A, Tccr0a) -#endif -#ifdef USE_TCCR1A -MAKE_TCCR(TCCR1A, Tccr1a) -#endif -#ifdef USE_TCCR2A -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 - }; - - static void Set() { - PORT::Set(1 << PIN); - } - - static void Set(uint8_t val) { - if(val) - Set(); - else Clear(); - } - - static void SetDir(uint8_t val) { - if(val) - SetDirWrite(); - else SetDirRead(); - } - - static void Clear() { - PORT::Clear(1 << PIN); - } - - static void Toggle() { - PORT::Toggle(1 << PIN); - } - - static void SetDirRead() { - PORT::DirClear(1 << PIN); - } - - static void SetDirWrite() { - PORT::DirSet(1 << PIN); - } - - static uint8_t IsSet() { - return PORT::PinRead() & (uint8_t)(1 << PIN); - } - - static void WaiteForSet() { - while(IsSet() == 0) { - } - } - - static void WaiteForClear() { - while(IsSet()) { - } - } -}; //class TPin... - -// 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 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; -#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; -#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; -#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; -#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; -#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; -#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; -#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; -#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; -#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; -#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; -#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; -#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; -#endif - -#ifdef USE_TCCR0A -typedef TCom Tc0a; //P6 -typedef TCom Tc0b; //P5 -#endif - -#ifdef USE_TCCR1A -typedef TCom Tc1a; //P9 -typedef TCom Tc1b; //P10 -#endif - -#ifdef USE_TCCR2A -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(); - } -}; - -/* pin definitions for cases where it's necessary to clear compare output mode bits */ - -//typedef Tp_Tc P3; //Arduino pin 3 -//typedef Tp_Tc P5; //Arduino pin 5 -//typedef Tp_Tc P6; //Arduino pin 6 -//typedef Tp_Tc P9; //Arduino pin 9 -//typedef Tp_Tc P10; //Arduino pin 10 -//typedef Tp_Tc P11; //Arduino pin 11 - -/* Arduino pin definitions */ -#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) -// "Mega" Arduino pin numbers - -#define P0 Pe0 -#define P1 Pe1 -#define P2 Pe4 -#define P3 Pe5 -#define P4 Pg5 -#define P5 Pe3 -#define P6 Ph3 -#define P7 Ph4 - -#define P8 Ph5 -#define P9 Ph6 -#define P10 Pb4 -#define P11 Pb5 -#define P12 Pb6 -#define P13 Pb7 - -#define P14 Pj1 -#define P15 Pj0 -#define P16 Ph1 -#define P17 Ph0 -#define P18 Pd3 -#define P19 Pd2 -#define P20 Pd1 -#define P21 Pd0 - -#define P22 Pa0 -#define P23 Pa1 -#define P24 Pa2 -#define P25 Pa3 -#define P26 Pa4 -#define P27 Pa5 -#define P28 Pa6 -#define P29 Pa7 -#define P30 Pc7 -#define P31 Pc6 -#define P32 Pc5 -#define P33 Pc4 -#define P34 Pc3 -#define P35 Pc2 -#define P36 Pc1 -#define P37 Pc0 - -#define P38 Pd7 -#define P39 Pg2 -#define P40 Pg1 -#define P41 Pg0 -#define P42 Pl7 -#define P43 Pl6 -#define P44 Pl5 -#define P45 Pl4 -#define P46 Pl3 -#define P47 Pl2 -#define P48 Pl1 -#define P49 Pl0 -#define P50 Pb3 -#define P51 Pb2 -#define P52 Pb1 -#define P53 Pb0 - -#ifdef BOARD_MEGA_ADK // These pins are not broken out on the Arduino ADK -#define P54 Pe6 // INT on Arduino ADK -#define P55 Pj2 // MAX_RESET on Arduino ADK -#endif - -// "Mega" pin numbers - -#elif defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__) -// "Classic" Arduino pin numbers - -#define P0 Pd0 -#define P1 Pd1 -#define P2 Pd2 -#define P3 Pd3 -#define P4 Pd4 -#define P5 Pd5 -#define P6 Pd6 -#define P7 Pd7 - -#define P8 Pb0 -#define P9 Pb1 -#define P10 Pb2 -#define P11 Pb3 -#define P12 Pb4 -#define P13 Pb5 - -#define P14 Pc0 -#define P15 Pc1 -#define P16 Pc2 -#define P17 Pc3 -#define P18 Pc4 -#define P19 Pc5 - -// "Classic" Arduino pin numbers - -#elif defined(CORE_TEENSY) && defined(__AVR_ATmega32U4__) -// Teensy 2.0 pin numbers -// http://www.pjrc.com/teensy/pinout.html -#define P0 Pb0 -#define P1 Pb1 -#define P2 Pb2 -#define P3 Pb3 -#define P4 Pb7 -#define P5 Pd0 -#define P6 Pd1 -#define P7 Pd2 -#define P8 Pd3 -#define P9 Pc6 -#define P10 Pc7 -#define P11 Pd6 -#define P12 Pd7 -#define P13 Pb4 -#define P14 Pb5 -#define P15 Pb6 -#define P16 Pf7 -#define P17 Pf6 -#define P18 Pf5 -#define P19 Pf4 -#define P20 Pf1 -#define P21 Pf0 -#define P22 Pd4 -#define P23 Pd5 -#define P24 Pe6 -// Teensy 2.0 - -#elif 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 - -// Arduino Leonardo pin numbers - -#elif defined(CORE_TEENSY) && (defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)) -// Teensy++ 1.0 and 2.0 pin numbers -// http://www.pjrc.com/teensy/pinout.html -#define P0 Pd0 -#define P1 Pd1 -#define P2 Pd2 -#define P3 Pd3 -#define P4 Pd4 -#define P5 Pd5 -#define P6 Pd6 -#define P7 Pd7 -#define P8 Pe0 -#define P9 Pe1 -#define P10 Pc0 -#define P11 Pc1 -#define P12 Pc2 -#define P13 Pc3 -#define P14 Pc4 -#define P15 Pc5 -#define P16 Pc6 -#define P17 Pc7 -#define P18 Pe6 -#define P19 Pe7 -#define P20 Pb0 -#define P21 Pb1 -#define P22 Pb2 -#define P23 Pb3 -#define P24 Pb4 -#define P25 Pb5 -#define P26 Pb6 -#define P27 Pb7 -#define P28 Pa0 -#define P29 Pa1 -#define P30 Pa2 -#define P31 Pa3 -#define P32 Pa4 -#define P33 Pa5 -#define P34 Pa6 -#define P35 Pa7 -#define P36 Pe4 -#define P37 Pe5 -#define P38 Pf0 -#define P39 Pf1 -#define P40 Pf2 -#define P41 Pf3 -#define P42 Pf4 -#define P43 Pf5 -#define P44 Pf6 -#define P45 Pf7 -// Teensy++ 1.0 and 2.0 - -#elif defined(ARDUINO_AVR_BALANDUINO) && (defined(__AVR_ATmega644__) || defined(__AVR_ATmega1284P__)) -// Balanduino pin numbers -// http://balanduino.net/ -#define P0 Pd0 /* 0 - PD0 */ -#define P1 Pd1 /* 1 - PD1 */ - -#if BALANDUINO_REVISION < 13 - #define P2 Pb2 /* 2 - PB2 */ - #define P3 Pd6 /* 3 - PD6 */ - #define P4 Pd7 /* 4 - PD7 */ - #define P5 Pb3 /* 5 - PB3 */ -#else - #define P2 Pd2 /* 2 - PD2 */ - #define P3 Pd3 /* 3 - PD3 */ - #define P4 Pd6 /* 4 - PD6 */ - #define P5 Pd7 /* 5 - PD7 */ -#endif - -#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 Pc1 /* 13 - PC1 */ -#define P14 Pc0 /* 14 - PC0 */ - -#if BALANDUINO_REVISION < 13 - #define P15 Pd2 /* 15 - PD2 */ - #define P16 Pd3 /* 16 - PD3 */ -#else - #define P15 Pb2 /* 15 - PB2 */ - #define P16 Pb3 /* 16 - PB2 */ -#endif - -#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 */ -// Balanduino - -#elif defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) -// Sanguino pin numbers -// Homepage: http://sanguino.cc/hardware -// Hardware add-on: https://github.com/Lauszus/Sanguino -#define P0 Pb0 -#define P1 Pb1 -#define P2 Pb2 -#define P3 Pb3 -#define P4 Pb4 -#define P5 Pb5 -#define P6 Pb6 -#define P7 Pb7 -#define P8 Pd0 -#define P9 Pd1 -#define P10 Pd2 -#define P11 Pd3 -#define P12 Pd4 -#define P13 Pd5 -#define P14 Pd6 -#define P15 Pd7 -#define P16 Pc0 -#define P17 Pc1 -#define P18 Pc2 -#define P19 Pc3 -#define P20 Pc4 -#define P21 Pc5 -#define P22 Pc6 -#define P23 Pc7 -#define P24 Pa0 -#define P25 Pa1 -#define P26 Pa2 -#define P27 Pa3 -#define P28 Pa4 -#define P29 Pa5 -#define P30 Pa6 -#define P31 Pa7 -// Sanguino - -#else -#error "Please define board in avrpins.h" - -#endif // Arduino pin definitions - -#elif defined(__arm__) - -// pointers are 32 bits on ARM -#define pgm_read_pointer(p) pgm_read_dword(p) - -#if defined(CORE_TEENSY) && (defined(__MK20DX128__) || defined(__MK20DX256__)) - -#include "core_pins.h" -#include "avr_emulation.h" - -#define GPIO_BITBAND_ADDR(reg, bit) (((uint32_t)&(reg) - 0x40000000) * 32 + (bit) * 4 + 0x42000000) -#define GPIO_BITBAND_PTR(reg, bit) ((uint8_t *)GPIO_BITBAND_ADDR((reg), (bit))) - -#define MAKE_PIN(className, baseReg, pinNum, configReg) \ -class className { \ -public: \ - static void Set() { \ - *GPIO_BITBAND_PTR(baseReg, pinNum) = 1; \ - } \ - static void Clear() { \ - *GPIO_BITBAND_PTR(baseReg, pinNum) = 0; \ - } \ - static void SetDirRead() { \ - configReg = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1); \ - *(GPIO_BITBAND_PTR(baseReg, pinNum) + 640) = 0; \ - } \ - static void SetDirWrite() { \ - configReg = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1); \ - *(GPIO_BITBAND_PTR(baseReg, pinNum) + 640) = 1; \ - } \ - static uint8_t IsSet() { \ - return *(GPIO_BITBAND_PTR(baseReg, pinNum) + 512); \ - } \ -}; - -MAKE_PIN(P0, CORE_PIN0_PORTREG, CORE_PIN0_BIT, CORE_PIN0_CONFIG); -MAKE_PIN(P1, CORE_PIN1_PORTREG, CORE_PIN1_BIT, CORE_PIN1_CONFIG); -MAKE_PIN(P2, CORE_PIN2_PORTREG, CORE_PIN2_BIT, CORE_PIN2_CONFIG); -MAKE_PIN(P3, CORE_PIN3_PORTREG, CORE_PIN3_BIT, CORE_PIN3_CONFIG); -MAKE_PIN(P4, CORE_PIN4_PORTREG, CORE_PIN4_BIT, CORE_PIN4_CONFIG); -MAKE_PIN(P5, CORE_PIN5_PORTREG, CORE_PIN5_BIT, CORE_PIN5_CONFIG); -MAKE_PIN(P6, CORE_PIN6_PORTREG, CORE_PIN6_BIT, CORE_PIN6_CONFIG); -MAKE_PIN(P7, CORE_PIN7_PORTREG, CORE_PIN7_BIT, CORE_PIN7_CONFIG); -MAKE_PIN(P8, CORE_PIN8_PORTREG, CORE_PIN8_BIT, CORE_PIN8_CONFIG); -MAKE_PIN(P9, CORE_PIN9_PORTREG, CORE_PIN9_BIT, CORE_PIN9_CONFIG); -MAKE_PIN(P10, CORE_PIN10_PORTREG, CORE_PIN10_BIT, CORE_PIN10_CONFIG); -MAKE_PIN(P11, CORE_PIN11_PORTREG, CORE_PIN11_BIT, CORE_PIN11_CONFIG); -MAKE_PIN(P12, CORE_PIN12_PORTREG, CORE_PIN12_BIT, CORE_PIN12_CONFIG); -MAKE_PIN(P13, CORE_PIN13_PORTREG, CORE_PIN13_BIT, CORE_PIN13_CONFIG); -MAKE_PIN(P14, CORE_PIN14_PORTREG, CORE_PIN14_BIT, CORE_PIN14_CONFIG); -MAKE_PIN(P15, CORE_PIN15_PORTREG, CORE_PIN15_BIT, CORE_PIN15_CONFIG); -MAKE_PIN(P16, CORE_PIN16_PORTREG, CORE_PIN16_BIT, CORE_PIN16_CONFIG); -MAKE_PIN(P17, CORE_PIN17_PORTREG, CORE_PIN17_BIT, CORE_PIN17_CONFIG); -MAKE_PIN(P18, CORE_PIN18_PORTREG, CORE_PIN18_BIT, CORE_PIN18_CONFIG); -MAKE_PIN(P19, CORE_PIN19_PORTREG, CORE_PIN19_BIT, CORE_PIN19_CONFIG); -MAKE_PIN(P20, CORE_PIN20_PORTREG, CORE_PIN20_BIT, CORE_PIN20_CONFIG); -MAKE_PIN(P21, CORE_PIN21_PORTREG, CORE_PIN21_BIT, CORE_PIN21_CONFIG); -MAKE_PIN(P22, CORE_PIN22_PORTREG, CORE_PIN22_BIT, CORE_PIN22_CONFIG); -MAKE_PIN(P23, CORE_PIN23_PORTREG, CORE_PIN23_BIT, CORE_PIN23_CONFIG); -MAKE_PIN(P24, CORE_PIN24_PORTREG, CORE_PIN24_BIT, CORE_PIN24_CONFIG); -MAKE_PIN(P25, CORE_PIN25_PORTREG, CORE_PIN25_BIT, CORE_PIN25_CONFIG); -MAKE_PIN(P26, CORE_PIN26_PORTREG, CORE_PIN26_BIT, CORE_PIN26_CONFIG); -MAKE_PIN(P27, CORE_PIN27_PORTREG, CORE_PIN27_BIT, CORE_PIN27_CONFIG); -MAKE_PIN(P28, CORE_PIN28_PORTREG, CORE_PIN28_BIT, CORE_PIN28_CONFIG); -MAKE_PIN(P29, CORE_PIN29_PORTREG, CORE_PIN29_BIT, CORE_PIN29_CONFIG); -MAKE_PIN(P30, CORE_PIN30_PORTREG, CORE_PIN30_BIT, CORE_PIN30_CONFIG); -MAKE_PIN(P31, CORE_PIN31_PORTREG, CORE_PIN31_BIT, CORE_PIN31_CONFIG); -MAKE_PIN(P32, CORE_PIN32_PORTREG, CORE_PIN32_BIT, CORE_PIN32_CONFIG); -MAKE_PIN(P33, CORE_PIN33_PORTREG, CORE_PIN33_BIT, CORE_PIN33_CONFIG); - -#undef MAKE_PIN - -#elif defined(ARDUINO_SAM_DUE) && defined(__SAM3X8E__) - -// SetDirRead: -// Disable interrupts -// Disable the pull up resistor -// Set to INPUT -// Enable PIO - -// SetDirWrite: -// Disable interrupts -// Disable the pull up resistor -// Set to OUTPUT -// Enable PIO - -#define MAKE_PIN(className, pio, pinMask) \ -class className { \ -public: \ - static void Set() { \ - pio->PIO_SODR = pinMask; \ - } \ - static void Clear() { \ - pio->PIO_CODR = pinMask; \ - } \ - static void SetDirRead() { \ - pio->PIO_IDR = pinMask ; \ - pio->PIO_PUDR = pinMask; \ - pio->PIO_ODR = pinMask; \ - pio->PIO_PER = pinMask; \ - } \ - static void SetDirWrite() { \ - pio->PIO_IDR = pinMask ; \ - pio->PIO_PUDR = pinMask; \ - pio->PIO_OER = pinMask; \ - pio->PIO_PER = pinMask; \ - } \ - static uint8_t IsSet() { \ - return pio->PIO_PDSR & pinMask; \ - } \ -}; - -// See: http://arduino.cc/en/Hacking/PinMappingSAM3X and variant.cpp - -MAKE_PIN(P0, PIOA, PIO_PA8); -MAKE_PIN(P1, PIOA, PIO_PA9); -MAKE_PIN(P2, PIOB, PIO_PB25); -MAKE_PIN(P3, PIOC, PIO_PC28); -MAKE_PIN(P4, PIOC, PIO_PC26); -MAKE_PIN(P5, PIOC, PIO_PC25); -MAKE_PIN(P6, PIOC, PIO_PC24); -MAKE_PIN(P7, PIOC, PIO_PC23); -MAKE_PIN(P8, PIOC, PIO_PC22); -MAKE_PIN(P9, PIOC, PIO_PC21); -MAKE_PIN(P10, PIOC, PIO_PC29); -MAKE_PIN(P11, PIOD, PIO_PD7); -MAKE_PIN(P12, PIOD, PIO_PD8); -MAKE_PIN(P13, PIOB, PIO_PB27); -MAKE_PIN(P14, PIOD, PIO_PD4); -MAKE_PIN(P15, PIOD, PIO_PD5); -MAKE_PIN(P16, PIOA, PIO_PA13); -MAKE_PIN(P17, PIOA, PIO_PA12); -MAKE_PIN(P18, PIOA, PIO_PA11); -MAKE_PIN(P19, PIOA, PIO_PA10); -MAKE_PIN(P20, PIOB, PIO_PB12); -MAKE_PIN(P21, PIOB, PIO_PB13); -MAKE_PIN(P22, PIOB, PIO_PB26); -MAKE_PIN(P23, PIOA, PIO_PA14); -MAKE_PIN(P24, PIOA, PIO_PA15); -MAKE_PIN(P25, PIOD, PIO_PD0); -MAKE_PIN(P26, PIOD, PIO_PD1); -MAKE_PIN(P27, PIOD, PIO_PD2); -MAKE_PIN(P28, PIOD, PIO_PD3); -MAKE_PIN(P29, PIOD, PIO_PD6); -MAKE_PIN(P30, PIOD, PIO_PD9); -MAKE_PIN(P31, PIOA, PIO_PA7); -MAKE_PIN(P32, PIOD, PIO_PD10); -MAKE_PIN(P33, PIOC, PIO_PC1); -MAKE_PIN(P34, PIOC, PIO_PC2); -MAKE_PIN(P35, PIOC, PIO_PC3); -MAKE_PIN(P36, PIOC, PIO_PC4); -MAKE_PIN(P37, PIOC, PIO_PC5); -MAKE_PIN(P38, PIOC, PIO_PC6); -MAKE_PIN(P39, PIOC, PIO_PC7); -MAKE_PIN(P40, PIOC, PIO_PC8); -MAKE_PIN(P41, PIOC, PIO_PC9); -MAKE_PIN(P42, PIOA, PIO_PA19); -MAKE_PIN(P43, PIOA, PIO_PA20); -MAKE_PIN(P44, PIOC, PIO_PC19); -MAKE_PIN(P45, PIOC, PIO_PC18); -MAKE_PIN(P46, PIOC, PIO_PC17); -MAKE_PIN(P47, PIOC, PIO_PC16); -MAKE_PIN(P48, PIOC, PIO_PC15); -MAKE_PIN(P49, PIOC, PIO_PC14); -MAKE_PIN(P50, PIOC, PIO_PC13); -MAKE_PIN(P51, PIOC, PIO_PC12); -MAKE_PIN(P52, PIOB, PIO_PB21); -MAKE_PIN(P53, PIOB, PIO_PB14); -MAKE_PIN(P54, PIOA, PIO_PA16); -MAKE_PIN(P55, PIOA, PIO_PA24); -MAKE_PIN(P56, PIOA, PIO_PA23); -MAKE_PIN(P57, PIOA, PIO_PA22); -MAKE_PIN(P58, PIOA, PIO_PA6); -MAKE_PIN(P59, PIOA, PIO_PA4); -MAKE_PIN(P60, PIOA, PIO_PA3); -MAKE_PIN(P61, PIOA, PIO_PA2); -MAKE_PIN(P62, PIOB, PIO_PB17); -MAKE_PIN(P63, PIOB, PIO_PB18); -MAKE_PIN(P64, PIOB, PIO_PB19); -MAKE_PIN(P65, PIOB, PIO_PB20); -MAKE_PIN(P66, PIOB, PIO_PB15); -MAKE_PIN(P67, PIOB, PIO_PB16); -MAKE_PIN(P68, PIOA, PIO_PA1); -MAKE_PIN(P69, PIOA, PIO_PA0); -MAKE_PIN(P70, PIOA, PIO_PA17); -MAKE_PIN(P71, PIOA, PIO_PA18); -MAKE_PIN(P72, PIOC, PIO_PC30); -MAKE_PIN(P73, PIOA, PIO_PA21); -MAKE_PIN(P74, PIOA, PIO_PA25); // MISO -MAKE_PIN(P75, PIOA, PIO_PA26); // MOSI -MAKE_PIN(P76, PIOA, PIO_PA27); // CLK -MAKE_PIN(P77, PIOA, PIO_PA28); -MAKE_PIN(P78, PIOB, PIO_PB23); // Unconnected - -#undef MAKE_PIN - -#elif defined(RBL_NRF51822) - -#define MAKE_PIN(className, pin) \ -class className { \ -public: \ - static void Set() { \ - nrf_gpio_pin_set(pin); \ - } \ - static void Clear() { \ - nrf_gpio_pin_clear(pin); \ - } \ - static void SetDirRead() { \ - nrf_gpio_cfg_input(pin, NRF_GPIO_PIN_NOPULL); \ - } \ - static void SetDirWrite() { \ - nrf_gpio_cfg_output(pin); \ - } \ - static uint8_t IsSet() { \ - return (uint8_t)nrf_gpio_pin_read(pin); \ - } \ -}; - -// See: pin_transform.c in RBL nRF51822 SDK -MAKE_PIN(P0, Pin_nRF51822_to_Arduino(D0)); -MAKE_PIN(P1, Pin_nRF51822_to_Arduino(D1)); -MAKE_PIN(P2, Pin_nRF51822_to_Arduino(D2)); -MAKE_PIN(P3, Pin_nRF51822_to_Arduino(D3)); -MAKE_PIN(P4, Pin_nRF51822_to_Arduino(D4)); -MAKE_PIN(P5, Pin_nRF51822_to_Arduino(D5)); -MAKE_PIN(P6, Pin_nRF51822_to_Arduino(D6)); -MAKE_PIN(P7, Pin_nRF51822_to_Arduino(D7)); -MAKE_PIN(P8, Pin_nRF51822_to_Arduino(D8)); -MAKE_PIN(P9, Pin_nRF51822_to_Arduino(D9)); // INT -MAKE_PIN(P10, Pin_nRF51822_to_Arduino(D10)); // SS -MAKE_PIN(P11, Pin_nRF51822_to_Arduino(D11)); -MAKE_PIN(P12, Pin_nRF51822_to_Arduino(D12)); -MAKE_PIN(P13, Pin_nRF51822_to_Arduino(D13)); -MAKE_PIN(P14, Pin_nRF51822_to_Arduino(D14)); -MAKE_PIN(P15, Pin_nRF51822_to_Arduino(D15)); -MAKE_PIN(P17, Pin_nRF51822_to_Arduino(D17)); // MISO -MAKE_PIN(P18, Pin_nRF51822_to_Arduino(D18)); // MOSI -MAKE_PIN(P16, Pin_nRF51822_to_Arduino(D16)); // CLK -MAKE_PIN(P19, Pin_nRF51822_to_Arduino(D19)); -MAKE_PIN(P20, Pin_nRF51822_to_Arduino(D20)); -MAKE_PIN(P21, Pin_nRF51822_to_Arduino(D21)); -MAKE_PIN(P22, Pin_nRF51822_to_Arduino(D22)); -MAKE_PIN(P23, Pin_nRF51822_to_Arduino(D23)); -MAKE_PIN(P24, Pin_nRF51822_to_Arduino(D24)); - -#undef MAKE_PIN - -#else -#error "Please define board in avrpins.h" - -#endif - -#elif defined(__ARDUINO_X86__) // Intel Galileo - -#include - -// Pointers are 32 bits on x86 -#define pgm_read_pointer(p) pgm_read_dword(p) - -#define MAKE_PIN(className, pin) \ -class className { \ -public: \ - static void Set() { \ - digitalWrite(pin, HIGH); \ - } \ - static void Clear() { \ - digitalWrite(pin, LOW); \ - } \ - static void SetDirRead() { \ - pinMode(pin, INPUT); \ - } \ - static void SetDirWrite() { \ - pinMode(pin, OUTPUT); \ - } \ - static uint8_t IsSet() { \ - return digitalRead(pin); \ - } \ -}; - -MAKE_PIN(P0, 0); -MAKE_PIN(P1, 1); -MAKE_PIN(P2, 2); -MAKE_PIN(P3, 3); -MAKE_PIN(P4, 4); -MAKE_PIN(P5, 5); -MAKE_PIN(P6, 6); -MAKE_PIN(P7, 7); -MAKE_PIN(P8, 8); -MAKE_PIN(P9, 9); -MAKE_PIN(P10, 10); -MAKE_PIN(P11, 11); -MAKE_PIN(P12, 12); -MAKE_PIN(P13, 13); -MAKE_PIN(P14, 14); // A0 -MAKE_PIN(P15, 15); // A1 -MAKE_PIN(P16, 16); // A2 -MAKE_PIN(P17, 17); // A3 -MAKE_PIN(P18, 18); // A4 -MAKE_PIN(P19, 19); // A5 - -#undef MAKE_PIN - -#elif defined(__MIPSEL__) -// MIPSEL (MIPS architecture using a little endian byte order) - -// MIPS size_t = 4 -#define pgm_read_pointer(p) pgm_read_dword(p) - -#define MAKE_PIN(className, pin) \ -class className { \ -public: \ - static void Set() { \ - digitalWrite(pin, HIGH);\ - } \ - static void Clear() { \ - digitalWrite(pin, LOW); \ - } \ - static void SetDirRead() { \ - pinMode(pin, INPUT); \ - } \ - static void SetDirWrite() { \ - pinMode(pin, OUTPUT); \ - } \ - static uint8_t IsSet() { \ - return digitalRead(pin); \ - } \ -}; - -// 0 .. 13 - Digital pins -MAKE_PIN(P0, 0); // RX -MAKE_PIN(P1, 1); // TX -MAKE_PIN(P2, 2); // -MAKE_PIN(P3, 3); // -MAKE_PIN(P4, 4); // -MAKE_PIN(P5, 5); // -MAKE_PIN(P6, 6); // -MAKE_PIN(P7, 7); // -MAKE_PIN(P8, 8); // -MAKE_PIN(P9, 9); // -MAKE_PIN(P10, 10); // -MAKE_PIN(P11, 11); // -MAKE_PIN(P12, 12); // -MAKE_PIN(P13, 13); // - -#undef MAKE_PIN - -#else -#error "Please define board in avrpins.h" - -#endif - -#endif //_avrpins_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 + */ + +/* derived from Konstantin Chizhov's AVR port templates */ + +#if !defined(_usb_h_) || defined(_avrpins_h_) +#error "Never include avrpins.h directly; include Usb.h instead" +#else +#define _avrpins_h_ + +#if defined(__AVR__) + +// pointers are 16 bits on AVR +#define pgm_read_pointer(p) pgm_read_word(p) + +// Support for these boards needs to be manually activated in settings.h or in a makefile +#if !defined(BOARD_MEGA_ADK) && defined(__AVR_ATmega2560__) && (USE_UHS_MEGA_ADK || defined(ARDUINO_AVR_ADK)) +#define BOARD_MEGA_ADK +#elif !defined(BOARD_BLACK_WIDDOW) && USE_UHS_BLACK_WIDDOW +#define BOARD_BLACK_WIDDOW +#endif + +#ifdef PORTA +#define USE_PORTA +#endif +#ifdef PORTB +#define USE_PORTB +#endif +#ifdef PORTC +#define USE_PORTC +#endif +#ifdef PORTD +#define USE_PORTD +#endif +#ifdef PORTE +#define USE_PORTE +#endif +#ifdef PORTF +#define USE_PORTF +#endif +#ifdef PORTG +#define USE_PORTG +#endif +#ifdef PORTH +#define USE_PORTH +#endif +#ifdef PORTJ +#define USE_PORTJ +#endif +#ifdef PORTK +#define USE_PORTK +#endif +#ifdef PORTL +#define USE_PORTL +#endif +#ifdef PORTQ +#define USE_PORTQ +#endif +#ifdef PORTR +#define USE_PORTR +#endif + +#ifdef TCCR0A +#define USE_TCCR0A +#endif +#ifdef TCCR1A +#define USE_TCCR1A +#endif +#ifdef TCCR2A +#define USE_TCCR2A +#endif + +//Port definitions for AtTiny, AtMega families. + +#define MAKE_PORT(portName, ddrName, pinName, className, ID) \ + class className{\ + public:\ + typedef uint8_t DataT;\ + public:\ + static void Write(DataT value){portName = value;}\ + static void ClearAndSet(DataT clearMask, DataT value){portName = (portName & ~clearMask) | value;}\ + static DataT Read(){return portName;}\ + static void DirWrite(DataT value){ddrName = value;}\ + static DataT DirRead(){return ddrName;}\ + static void Set(DataT value){portName |= value;}\ + static void Clear(DataT value){portName &= ~value;}\ + static void Toggle(DataT value){portName ^= value;}\ + static void DirSet(DataT value){ddrName |= value;}\ + static void DirClear(DataT value){ddrName &= ~value;}\ + static void DirToggle(DataT value){ddrName ^= value;}\ + static DataT PinRead(){return pinName;}\ + enum{Id = ID};\ + enum{Width=sizeof(DataT)*8};\ + }; + +// TCCR registers to set/clear Arduino PWM +#define MAKE_TCCR(TccrName, className) \ + class className{\ + public:\ + typedef uint8_t DataT;\ + public:\ + static void Write(DataT value){TccrName = value;}\ + static void ClearAndSet(DataT clearMask, DataT value){TccrName = (TccrName & ~clearMask) | value;}\ + static DataT Read(){return TccrName;}\ + static void Set(DataT value){TccrName |= value;}\ + static void Clear(DataT value){TccrName &= ~value;}\ + static void Toggle(DataT value){TccrName ^= value;}\ + enum{Width=sizeof(DataT)*8};\ + }; + +#ifdef USE_PORTA + +MAKE_PORT(PORTA, DDRA, PINA, Porta, 'A') +#endif +#ifdef USE_PORTB +MAKE_PORT(PORTB, DDRB, PINB, Portb, 'B') +#endif +#ifdef USE_PORTC +MAKE_PORT(PORTC, DDRC, PINC, Portc, 'C') +#endif +#ifdef USE_PORTD +MAKE_PORT(PORTD, DDRD, PIND, Portd, 'D') +#endif +#ifdef USE_PORTE +MAKE_PORT(PORTE, DDRE, PINE, Porte, 'E') +#endif +#ifdef USE_PORTF +MAKE_PORT(PORTF, DDRF, PINF, Portf, 'F') +#endif +#ifdef USE_PORTG +MAKE_PORT(PORTG, DDRG, PING, Portg, 'G') +#endif +#ifdef USE_PORTH +MAKE_PORT(PORTH, DDRH, PINH, Porth, 'H') +#endif +#ifdef USE_PORTJ +MAKE_PORT(PORTJ, DDRJ, PINJ, Portj, 'J') +#endif +#ifdef USE_PORTK +MAKE_PORT(PORTK, DDRK, PINK, Portk, 'K') +#endif +#ifdef USE_PORTL +MAKE_PORT(PORTL, DDRL, PINL, Portl, 'L') +#endif +#ifdef USE_PORTQ +MAKE_PORT(PORTQ, DDRQ, PINQ, Portq, 'Q') +#endif +#ifdef USE_PORTR +MAKE_PORT(PORTR, DDRR, PINR, Portr, 'R') +#endif + +#ifdef USE_TCCR0A +MAKE_TCCR(TCCR0A, Tccr0a) +#endif +#ifdef USE_TCCR1A +MAKE_TCCR(TCCR1A, Tccr1a) +#endif +#ifdef USE_TCCR2A +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 + }; + + static void Set() { + PORT::Set(1 << PIN); + } + + static void Set(uint8_t val) { + if(val) + Set(); + else Clear(); + } + + static void SetDir(uint8_t val) { + if(val) + SetDirWrite(); + else SetDirRead(); + } + + static void Clear() { + PORT::Clear(1 << PIN); + } + + static void Toggle() { + PORT::Toggle(1 << PIN); + } + + static void SetDirRead() { + PORT::DirClear(1 << PIN); + } + + static void SetDirWrite() { + PORT::DirSet(1 << PIN); + } + + static uint8_t IsSet() { + return PORT::PinRead() & (uint8_t)(1 << PIN); + } + + static void WaiteForSet() { + while(IsSet() == 0) { + } + } + + static void WaiteForClear() { + while(IsSet()) { + } + } +}; //class TPin... + +// 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 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; +#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; +#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; +#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; +#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; +#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; +#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; +#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; +#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; +#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; +#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; +#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; +#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; +#endif + +#ifdef USE_TCCR0A +typedef TCom Tc0a; //P6 +typedef TCom Tc0b; //P5 +#endif + +#ifdef USE_TCCR1A +typedef TCom Tc1a; //P9 +typedef TCom Tc1b; //P10 +#endif + +#ifdef USE_TCCR2A +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(); + } +}; + +/* pin definitions for cases where it's necessary to clear compare output mode bits */ + +//typedef Tp_Tc P3; //Arduino pin 3 +//typedef Tp_Tc P5; //Arduino pin 5 +//typedef Tp_Tc P6; //Arduino pin 6 +//typedef Tp_Tc P9; //Arduino pin 9 +//typedef Tp_Tc P10; //Arduino pin 10 +//typedef Tp_Tc P11; //Arduino pin 11 + +/* Arduino pin definitions */ +#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) +// "Mega" Arduino pin numbers + +#define P0 Pe0 +#define P1 Pe1 +#define P2 Pe4 +#define P3 Pe5 +#define P4 Pg5 +#define P5 Pe3 +#define P6 Ph3 +#define P7 Ph4 + +#define P8 Ph5 +#define P9 Ph6 +#define P10 Pb4 +#define P11 Pb5 +#define P12 Pb6 +#define P13 Pb7 + +#define P14 Pj1 +#define P15 Pj0 +#define P16 Ph1 +#define P17 Ph0 +#define P18 Pd3 +#define P19 Pd2 +#define P20 Pd1 +#define P21 Pd0 + +#define P22 Pa0 +#define P23 Pa1 +#define P24 Pa2 +#define P25 Pa3 +#define P26 Pa4 +#define P27 Pa5 +#define P28 Pa6 +#define P29 Pa7 +#define P30 Pc7 +#define P31 Pc6 +#define P32 Pc5 +#define P33 Pc4 +#define P34 Pc3 +#define P35 Pc2 +#define P36 Pc1 +#define P37 Pc0 + +#define P38 Pd7 +#define P39 Pg2 +#define P40 Pg1 +#define P41 Pg0 +#define P42 Pl7 +#define P43 Pl6 +#define P44 Pl5 +#define P45 Pl4 +#define P46 Pl3 +#define P47 Pl2 +#define P48 Pl1 +#define P49 Pl0 +#define P50 Pb3 +#define P51 Pb2 +#define P52 Pb1 +#define P53 Pb0 + +#ifdef BOARD_MEGA_ADK // These pins are not broken out on the Arduino ADK +#define P54 Pe6 // INT on Arduino ADK +#define P55 Pj2 // MAX_RESET on Arduino ADK +#endif + +// "Mega" pin numbers + +#elif defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__) +// "Classic" Arduino pin numbers + +#define P0 Pd0 +#define P1 Pd1 +#define P2 Pd2 +#define P3 Pd3 +#define P4 Pd4 +#define P5 Pd5 +#define P6 Pd6 +#define P7 Pd7 + +#define P8 Pb0 +#define P9 Pb1 +#define P10 Pb2 +#define P11 Pb3 +#define P12 Pb4 +#define P13 Pb5 + +#define P14 Pc0 +#define P15 Pc1 +#define P16 Pc2 +#define P17 Pc3 +#define P18 Pc4 +#define P19 Pc5 + +// "Classic" Arduino pin numbers + +#elif defined(CORE_TEENSY) && defined(__AVR_ATmega32U4__) +// Teensy 2.0 pin numbers +// http://www.pjrc.com/teensy/pinout.html +#define P0 Pb0 +#define P1 Pb1 +#define P2 Pb2 +#define P3 Pb3 +#define P4 Pb7 +#define P5 Pd0 +#define P6 Pd1 +#define P7 Pd2 +#define P8 Pd3 +#define P9 Pc6 +#define P10 Pc7 +#define P11 Pd6 +#define P12 Pd7 +#define P13 Pb4 +#define P14 Pb5 +#define P15 Pb6 +#define P16 Pf7 +#define P17 Pf6 +#define P18 Pf5 +#define P19 Pf4 +#define P20 Pf1 +#define P21 Pf0 +#define P22 Pd4 +#define P23 Pd5 +#define P24 Pe6 +// Teensy 2.0 + +#elif 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 + +// Arduino Leonardo pin numbers + +#elif defined(CORE_TEENSY) && (defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)) +// Teensy++ 1.0 and 2.0 pin numbers +// http://www.pjrc.com/teensy/pinout.html +#define P0 Pd0 +#define P1 Pd1 +#define P2 Pd2 +#define P3 Pd3 +#define P4 Pd4 +#define P5 Pd5 +#define P6 Pd6 +#define P7 Pd7 +#define P8 Pe0 +#define P9 Pe1 +#define P10 Pc0 +#define P11 Pc1 +#define P12 Pc2 +#define P13 Pc3 +#define P14 Pc4 +#define P15 Pc5 +#define P16 Pc6 +#define P17 Pc7 +#define P18 Pe6 +#define P19 Pe7 +#define P20 Pb0 +#define P21 Pb1 +#define P22 Pb2 +#define P23 Pb3 +#define P24 Pb4 +#define P25 Pb5 +#define P26 Pb6 +#define P27 Pb7 +#define P28 Pa0 +#define P29 Pa1 +#define P30 Pa2 +#define P31 Pa3 +#define P32 Pa4 +#define P33 Pa5 +#define P34 Pa6 +#define P35 Pa7 +#define P36 Pe4 +#define P37 Pe5 +#define P38 Pf0 +#define P39 Pf1 +#define P40 Pf2 +#define P41 Pf3 +#define P42 Pf4 +#define P43 Pf5 +#define P44 Pf6 +#define P45 Pf7 +// Teensy++ 1.0 and 2.0 + +#elif defined(ARDUINO_AVR_BALANDUINO) && (defined(__AVR_ATmega644__) || defined(__AVR_ATmega1284P__)) +// Balanduino pin numbers +// http://balanduino.net/ +#define P0 Pd0 /* 0 - PD0 */ +#define P1 Pd1 /* 1 - PD1 */ + +#if BALANDUINO_REVISION < 13 + #define P2 Pb2 /* 2 - PB2 */ + #define P3 Pd6 /* 3 - PD6 */ + #define P4 Pd7 /* 4 - PD7 */ + #define P5 Pb3 /* 5 - PB3 */ +#else + #define P2 Pd2 /* 2 - PD2 */ + #define P3 Pd3 /* 3 - PD3 */ + #define P4 Pd6 /* 4 - PD6 */ + #define P5 Pd7 /* 5 - PD7 */ +#endif + +#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 Pc1 /* 13 - PC1 */ +#define P14 Pc0 /* 14 - PC0 */ + +#if BALANDUINO_REVISION < 13 + #define P15 Pd2 /* 15 - PD2 */ + #define P16 Pd3 /* 16 - PD3 */ +#else + #define P15 Pb2 /* 15 - PB2 */ + #define P16 Pb3 /* 16 - PB2 */ +#endif + +#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 */ +// Balanduino + +#elif defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) +// Sanguino pin numbers +// Homepage: http://sanguino.cc/hardware +// Hardware add-on: https://github.com/Lauszus/Sanguino +#define P0 Pb0 +#define P1 Pb1 +#define P2 Pb2 +#define P3 Pb3 +#define P4 Pb4 +#define P5 Pb5 +#define P6 Pb6 +#define P7 Pb7 +#define P8 Pd0 +#define P9 Pd1 +#define P10 Pd2 +#define P11 Pd3 +#define P12 Pd4 +#define P13 Pd5 +#define P14 Pd6 +#define P15 Pd7 +#define P16 Pc0 +#define P17 Pc1 +#define P18 Pc2 +#define P19 Pc3 +#define P20 Pc4 +#define P21 Pc5 +#define P22 Pc6 +#define P23 Pc7 +#define P24 Pa0 +#define P25 Pa1 +#define P26 Pa2 +#define P27 Pa3 +#define P28 Pa4 +#define P29 Pa5 +#define P30 Pa6 +#define P31 Pa7 +// Sanguino + +#else +#error "Please define board in avrpins.h" + +#endif // Arduino pin definitions + +#elif defined(__arm__) + +// pointers are 32 bits on ARM +#define pgm_read_pointer(p) pgm_read_dword(p) + +#if defined(CORE_TEENSY) && (defined(__MK20DX128__) || defined(__MK20DX256__)) + +#include "core_pins.h" +#include "avr_emulation.h" + +#define GPIO_BITBAND_ADDR(reg, bit) (((uint32_t)&(reg) - 0x40000000) * 32 + (bit) * 4 + 0x42000000) +#define GPIO_BITBAND_PTR(reg, bit) ((uint8_t *)GPIO_BITBAND_ADDR((reg), (bit))) + +#define MAKE_PIN(className, baseReg, pinNum, configReg) \ +class className { \ +public: \ + static void Set() { \ + *GPIO_BITBAND_PTR(baseReg, pinNum) = 1; \ + } \ + static void Clear() { \ + *GPIO_BITBAND_PTR(baseReg, pinNum) = 0; \ + } \ + static void SetDirRead() { \ + configReg = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1); \ + *(GPIO_BITBAND_PTR(baseReg, pinNum) + 640) = 0; \ + } \ + static void SetDirWrite() { \ + configReg = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1); \ + *(GPIO_BITBAND_PTR(baseReg, pinNum) + 640) = 1; \ + } \ + static uint8_t IsSet() { \ + return *(GPIO_BITBAND_PTR(baseReg, pinNum) + 512); \ + } \ +}; + +MAKE_PIN(P0, CORE_PIN0_PORTREG, CORE_PIN0_BIT, CORE_PIN0_CONFIG); +MAKE_PIN(P1, CORE_PIN1_PORTREG, CORE_PIN1_BIT, CORE_PIN1_CONFIG); +MAKE_PIN(P2, CORE_PIN2_PORTREG, CORE_PIN2_BIT, CORE_PIN2_CONFIG); +MAKE_PIN(P3, CORE_PIN3_PORTREG, CORE_PIN3_BIT, CORE_PIN3_CONFIG); +MAKE_PIN(P4, CORE_PIN4_PORTREG, CORE_PIN4_BIT, CORE_PIN4_CONFIG); +MAKE_PIN(P5, CORE_PIN5_PORTREG, CORE_PIN5_BIT, CORE_PIN5_CONFIG); +MAKE_PIN(P6, CORE_PIN6_PORTREG, CORE_PIN6_BIT, CORE_PIN6_CONFIG); +MAKE_PIN(P7, CORE_PIN7_PORTREG, CORE_PIN7_BIT, CORE_PIN7_CONFIG); +MAKE_PIN(P8, CORE_PIN8_PORTREG, CORE_PIN8_BIT, CORE_PIN8_CONFIG); +MAKE_PIN(P9, CORE_PIN9_PORTREG, CORE_PIN9_BIT, CORE_PIN9_CONFIG); +MAKE_PIN(P10, CORE_PIN10_PORTREG, CORE_PIN10_BIT, CORE_PIN10_CONFIG); +MAKE_PIN(P11, CORE_PIN11_PORTREG, CORE_PIN11_BIT, CORE_PIN11_CONFIG); +MAKE_PIN(P12, CORE_PIN12_PORTREG, CORE_PIN12_BIT, CORE_PIN12_CONFIG); +MAKE_PIN(P13, CORE_PIN13_PORTREG, CORE_PIN13_BIT, CORE_PIN13_CONFIG); +MAKE_PIN(P14, CORE_PIN14_PORTREG, CORE_PIN14_BIT, CORE_PIN14_CONFIG); +MAKE_PIN(P15, CORE_PIN15_PORTREG, CORE_PIN15_BIT, CORE_PIN15_CONFIG); +MAKE_PIN(P16, CORE_PIN16_PORTREG, CORE_PIN16_BIT, CORE_PIN16_CONFIG); +MAKE_PIN(P17, CORE_PIN17_PORTREG, CORE_PIN17_BIT, CORE_PIN17_CONFIG); +MAKE_PIN(P18, CORE_PIN18_PORTREG, CORE_PIN18_BIT, CORE_PIN18_CONFIG); +MAKE_PIN(P19, CORE_PIN19_PORTREG, CORE_PIN19_BIT, CORE_PIN19_CONFIG); +MAKE_PIN(P20, CORE_PIN20_PORTREG, CORE_PIN20_BIT, CORE_PIN20_CONFIG); +MAKE_PIN(P21, CORE_PIN21_PORTREG, CORE_PIN21_BIT, CORE_PIN21_CONFIG); +MAKE_PIN(P22, CORE_PIN22_PORTREG, CORE_PIN22_BIT, CORE_PIN22_CONFIG); +MAKE_PIN(P23, CORE_PIN23_PORTREG, CORE_PIN23_BIT, CORE_PIN23_CONFIG); +MAKE_PIN(P24, CORE_PIN24_PORTREG, CORE_PIN24_BIT, CORE_PIN24_CONFIG); +MAKE_PIN(P25, CORE_PIN25_PORTREG, CORE_PIN25_BIT, CORE_PIN25_CONFIG); +MAKE_PIN(P26, CORE_PIN26_PORTREG, CORE_PIN26_BIT, CORE_PIN26_CONFIG); +MAKE_PIN(P27, CORE_PIN27_PORTREG, CORE_PIN27_BIT, CORE_PIN27_CONFIG); +MAKE_PIN(P28, CORE_PIN28_PORTREG, CORE_PIN28_BIT, CORE_PIN28_CONFIG); +MAKE_PIN(P29, CORE_PIN29_PORTREG, CORE_PIN29_BIT, CORE_PIN29_CONFIG); +MAKE_PIN(P30, CORE_PIN30_PORTREG, CORE_PIN30_BIT, CORE_PIN30_CONFIG); +MAKE_PIN(P31, CORE_PIN31_PORTREG, CORE_PIN31_BIT, CORE_PIN31_CONFIG); +MAKE_PIN(P32, CORE_PIN32_PORTREG, CORE_PIN32_BIT, CORE_PIN32_CONFIG); +MAKE_PIN(P33, CORE_PIN33_PORTREG, CORE_PIN33_BIT, CORE_PIN33_CONFIG); + +#undef MAKE_PIN + +#elif defined(ARDUINO_SAM_DUE) && defined(__SAM3X8E__) + +// SetDirRead: +// Disable interrupts +// Disable the pull up resistor +// Set to INPUT +// Enable PIO + +// SetDirWrite: +// Disable interrupts +// Disable the pull up resistor +// Set to OUTPUT +// Enable PIO + +#define MAKE_PIN(className, pio, pinMask) \ +class className { \ +public: \ + static void Set() { \ + pio->PIO_SODR = pinMask; \ + } \ + static void Clear() { \ + pio->PIO_CODR = pinMask; \ + } \ + static void SetDirRead() { \ + pio->PIO_IDR = pinMask ; \ + pio->PIO_PUDR = pinMask; \ + pio->PIO_ODR = pinMask; \ + pio->PIO_PER = pinMask; \ + } \ + static void SetDirWrite() { \ + pio->PIO_IDR = pinMask ; \ + pio->PIO_PUDR = pinMask; \ + pio->PIO_OER = pinMask; \ + pio->PIO_PER = pinMask; \ + } \ + static uint8_t IsSet() { \ + return pio->PIO_PDSR & pinMask; \ + } \ +}; + +// See: http://arduino.cc/en/Hacking/PinMappingSAM3X and variant.cpp + +MAKE_PIN(P0, PIOA, PIO_PA8); +MAKE_PIN(P1, PIOA, PIO_PA9); +MAKE_PIN(P2, PIOB, PIO_PB25); +MAKE_PIN(P3, PIOC, PIO_PC28); +MAKE_PIN(P4, PIOC, PIO_PC26); +MAKE_PIN(P5, PIOC, PIO_PC25); +MAKE_PIN(P6, PIOC, PIO_PC24); +MAKE_PIN(P7, PIOC, PIO_PC23); +MAKE_PIN(P8, PIOC, PIO_PC22); +MAKE_PIN(P9, PIOC, PIO_PC21); +MAKE_PIN(P10, PIOC, PIO_PC29); +MAKE_PIN(P11, PIOD, PIO_PD7); +MAKE_PIN(P12, PIOD, PIO_PD8); +MAKE_PIN(P13, PIOB, PIO_PB27); +MAKE_PIN(P14, PIOD, PIO_PD4); +MAKE_PIN(P15, PIOD, PIO_PD5); +MAKE_PIN(P16, PIOA, PIO_PA13); +MAKE_PIN(P17, PIOA, PIO_PA12); +MAKE_PIN(P18, PIOA, PIO_PA11); +MAKE_PIN(P19, PIOA, PIO_PA10); +MAKE_PIN(P20, PIOB, PIO_PB12); +MAKE_PIN(P21, PIOB, PIO_PB13); +MAKE_PIN(P22, PIOB, PIO_PB26); +MAKE_PIN(P23, PIOA, PIO_PA14); +MAKE_PIN(P24, PIOA, PIO_PA15); +MAKE_PIN(P25, PIOD, PIO_PD0); +MAKE_PIN(P26, PIOD, PIO_PD1); +MAKE_PIN(P27, PIOD, PIO_PD2); +MAKE_PIN(P28, PIOD, PIO_PD3); +MAKE_PIN(P29, PIOD, PIO_PD6); +MAKE_PIN(P30, PIOD, PIO_PD9); +MAKE_PIN(P31, PIOA, PIO_PA7); +MAKE_PIN(P32, PIOD, PIO_PD10); +MAKE_PIN(P33, PIOC, PIO_PC1); +MAKE_PIN(P34, PIOC, PIO_PC2); +MAKE_PIN(P35, PIOC, PIO_PC3); +MAKE_PIN(P36, PIOC, PIO_PC4); +MAKE_PIN(P37, PIOC, PIO_PC5); +MAKE_PIN(P38, PIOC, PIO_PC6); +MAKE_PIN(P39, PIOC, PIO_PC7); +MAKE_PIN(P40, PIOC, PIO_PC8); +MAKE_PIN(P41, PIOC, PIO_PC9); +MAKE_PIN(P42, PIOA, PIO_PA19); +MAKE_PIN(P43, PIOA, PIO_PA20); +MAKE_PIN(P44, PIOC, PIO_PC19); +MAKE_PIN(P45, PIOC, PIO_PC18); +MAKE_PIN(P46, PIOC, PIO_PC17); +MAKE_PIN(P47, PIOC, PIO_PC16); +MAKE_PIN(P48, PIOC, PIO_PC15); +MAKE_PIN(P49, PIOC, PIO_PC14); +MAKE_PIN(P50, PIOC, PIO_PC13); +MAKE_PIN(P51, PIOC, PIO_PC12); +MAKE_PIN(P52, PIOB, PIO_PB21); +MAKE_PIN(P53, PIOB, PIO_PB14); +MAKE_PIN(P54, PIOA, PIO_PA16); +MAKE_PIN(P55, PIOA, PIO_PA24); +MAKE_PIN(P56, PIOA, PIO_PA23); +MAKE_PIN(P57, PIOA, PIO_PA22); +MAKE_PIN(P58, PIOA, PIO_PA6); +MAKE_PIN(P59, PIOA, PIO_PA4); +MAKE_PIN(P60, PIOA, PIO_PA3); +MAKE_PIN(P61, PIOA, PIO_PA2); +MAKE_PIN(P62, PIOB, PIO_PB17); +MAKE_PIN(P63, PIOB, PIO_PB18); +MAKE_PIN(P64, PIOB, PIO_PB19); +MAKE_PIN(P65, PIOB, PIO_PB20); +MAKE_PIN(P66, PIOB, PIO_PB15); +MAKE_PIN(P67, PIOB, PIO_PB16); +MAKE_PIN(P68, PIOA, PIO_PA1); +MAKE_PIN(P69, PIOA, PIO_PA0); +MAKE_PIN(P70, PIOA, PIO_PA17); +MAKE_PIN(P71, PIOA, PIO_PA18); +MAKE_PIN(P72, PIOC, PIO_PC30); +MAKE_PIN(P73, PIOA, PIO_PA21); +MAKE_PIN(P74, PIOA, PIO_PA25); // MISO +MAKE_PIN(P75, PIOA, PIO_PA26); // MOSI +MAKE_PIN(P76, PIOA, PIO_PA27); // CLK +MAKE_PIN(P77, PIOA, PIO_PA28); +MAKE_PIN(P78, PIOB, PIO_PB23); // Unconnected + +#undef MAKE_PIN + +#elif defined(RBL_NRF51822) + +#define MAKE_PIN(className, pin) \ +class className { \ +public: \ + static void Set() { \ + nrf_gpio_pin_set(pin); \ + } \ + static void Clear() { \ + nrf_gpio_pin_clear(pin); \ + } \ + static void SetDirRead() { \ + nrf_gpio_cfg_input(pin, NRF_GPIO_PIN_NOPULL); \ + } \ + static void SetDirWrite() { \ + nrf_gpio_cfg_output(pin); \ + } \ + static uint8_t IsSet() { \ + return (uint8_t)nrf_gpio_pin_read(pin); \ + } \ +}; + +// See: pin_transform.c in RBL nRF51822 SDK +MAKE_PIN(P0, Pin_nRF51822_to_Arduino(D0)); +MAKE_PIN(P1, Pin_nRF51822_to_Arduino(D1)); +MAKE_PIN(P2, Pin_nRF51822_to_Arduino(D2)); +MAKE_PIN(P3, Pin_nRF51822_to_Arduino(D3)); +MAKE_PIN(P4, Pin_nRF51822_to_Arduino(D4)); +MAKE_PIN(P5, Pin_nRF51822_to_Arduino(D5)); +MAKE_PIN(P6, Pin_nRF51822_to_Arduino(D6)); +MAKE_PIN(P7, Pin_nRF51822_to_Arduino(D7)); +MAKE_PIN(P8, Pin_nRF51822_to_Arduino(D8)); +MAKE_PIN(P9, Pin_nRF51822_to_Arduino(D9)); // INT +MAKE_PIN(P10, Pin_nRF51822_to_Arduino(D10)); // SS +MAKE_PIN(P11, Pin_nRF51822_to_Arduino(D11)); +MAKE_PIN(P12, Pin_nRF51822_to_Arduino(D12)); +MAKE_PIN(P13, Pin_nRF51822_to_Arduino(D13)); +MAKE_PIN(P14, Pin_nRF51822_to_Arduino(D14)); +MAKE_PIN(P15, Pin_nRF51822_to_Arduino(D15)); +MAKE_PIN(P17, Pin_nRF51822_to_Arduino(D17)); // MISO +MAKE_PIN(P18, Pin_nRF51822_to_Arduino(D18)); // MOSI +MAKE_PIN(P16, Pin_nRF51822_to_Arduino(D16)); // CLK +MAKE_PIN(P19, Pin_nRF51822_to_Arduino(D19)); +MAKE_PIN(P20, Pin_nRF51822_to_Arduino(D20)); +MAKE_PIN(P21, Pin_nRF51822_to_Arduino(D21)); +MAKE_PIN(P22, Pin_nRF51822_to_Arduino(D22)); +MAKE_PIN(P23, Pin_nRF51822_to_Arduino(D23)); +MAKE_PIN(P24, Pin_nRF51822_to_Arduino(D24)); + +#undef MAKE_PIN + +#else +#error "Please define board in avrpins.h" + +#endif + +#elif defined(__ARDUINO_X86__) // Intel Galileo + +#include + +// Pointers are 32 bits on x86 +#define pgm_read_pointer(p) pgm_read_dword(p) + +#define MAKE_PIN(className, pin) \ +class className { \ +public: \ + static void Set() { \ + digitalWrite(pin, HIGH); \ + } \ + static void Clear() { \ + digitalWrite(pin, LOW); \ + } \ + static void SetDirRead() { \ + pinMode(pin, INPUT); \ + } \ + static void SetDirWrite() { \ + pinMode(pin, OUTPUT); \ + } \ + static uint8_t IsSet() { \ + return digitalRead(pin); \ + } \ +}; + +MAKE_PIN(P0, 0); +MAKE_PIN(P1, 1); +MAKE_PIN(P2, 2); +MAKE_PIN(P3, 3); +MAKE_PIN(P4, 4); +MAKE_PIN(P5, 5); +MAKE_PIN(P6, 6); +MAKE_PIN(P7, 7); +MAKE_PIN(P8, 8); +MAKE_PIN(P9, 9); +MAKE_PIN(P10, 10); +MAKE_PIN(P11, 11); +MAKE_PIN(P12, 12); +MAKE_PIN(P13, 13); +MAKE_PIN(P14, 14); // A0 +MAKE_PIN(P15, 15); // A1 +MAKE_PIN(P16, 16); // A2 +MAKE_PIN(P17, 17); // A3 +MAKE_PIN(P18, 18); // A4 +MAKE_PIN(P19, 19); // A5 + +#undef MAKE_PIN + +#elif defined(__MIPSEL__) +// MIPSEL (MIPS architecture using a little endian byte order) + +// MIPS size_t = 4 +#define pgm_read_pointer(p) pgm_read_dword(p) + +#define MAKE_PIN(className, pin) \ +class className { \ +public: \ + static void Set() { \ + digitalWrite(pin, HIGH);\ + } \ + static void Clear() { \ + digitalWrite(pin, LOW); \ + } \ + static void SetDirRead() { \ + pinMode(pin, INPUT); \ + } \ + static void SetDirWrite() { \ + pinMode(pin, OUTPUT); \ + } \ + static uint8_t IsSet() { \ + return digitalRead(pin); \ + } \ +}; + +// 0 .. 13 - Digital pins +MAKE_PIN(P0, 0); // RX +MAKE_PIN(P1, 1); // TX +MAKE_PIN(P2, 2); // +MAKE_PIN(P3, 3); // +MAKE_PIN(P4, 4); // +MAKE_PIN(P5, 5); // +MAKE_PIN(P6, 6); // +MAKE_PIN(P7, 7); // +MAKE_PIN(P8, 8); // +MAKE_PIN(P9, 9); // +MAKE_PIN(P10, 10); // +MAKE_PIN(P11, 11); // +MAKE_PIN(P12, 12); // +MAKE_PIN(P13, 13); // + +#undef MAKE_PIN + +#else +#error "Please define board in avrpins.h" + +#endif + +#endif //_avrpins_h_ diff --git a/cdc_XR21B1411.cpp b/cdc_XR21B1411.cpp new file mode 100644 index 00000000..74df8c3b --- /dev/null +++ b/cdc_XR21B1411.cpp @@ -0,0 +1,211 @@ +/* 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 "cdc_XR21B1411.h" + +XR21B1411::XR21B1411(USB *p, CDCAsyncOper *pasync) : +ACM(p, pasync) { + // Is this needed?? + _enhanced_status = enhanced_features(); // Set up features +} + +uint8_t XR21B1411::Init(uint8_t parent, uint8_t port, bool lowspeed) { + const uint8_t constBufSize = sizeof (USB_DEVICE_DESCRIPTOR); + + uint8_t buf[constBufSize]; + USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast(buf); + + uint8_t rcode; + UsbDevice *p = NULL; + EpInfo *oldep_ptr = NULL; + uint8_t num_of_conf; // number of configurations + + AddressPool &addrPool = pUsb->GetAddressPool(); + + USBTRACE("XR 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 = udd->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 = udd->bNumConfigurations; + + if((((udd->idVendor != 0x2890U) || (udd->idProduct != 0x0201U)) && ((udd->idVendor != 0x04e2U) || (udd->idProduct != 0x1411U)))) + return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; + + // Assign epInfo to epinfo pointer + rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); + + 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 FailSetConfDescr; + + // Set up features status + _enhanced_status = enhanced_features(); + half_duplex(false); + autoflowRTS(false); + autoflowDSR(false); + autoflowXON(false); + wide(false); // Always false, because this is only available in custom mode. + + rcode = pAsync->OnInit(this); + + if(rcode) + goto FailOnInit; + + USBTRACE("XR configured\r\n"); + + ready = true; + + //bPollEnable = true; + + //USBTRACE("Poll enabled\r\n"); + return 0; + +FailGetDevDescr: +#ifdef DEBUG_USB_HOST + NotifyFailGetDevDescr(); + goto Fail; +#endif + +FailSetDevTblEntry: +#ifdef DEBUG_USB_HOST + NotifyFailSetDevTblEntry(); + goto Fail; +#endif + +FailGetConfDescr: +#ifdef DEBUG_USB_HOST + NotifyFailGetConfDescr(); + goto Fail; +#endif + +FailSetConfDescr: +#ifdef DEBUG_USB_HOST + NotifyFailSetConfDescr(); + goto Fail; +#endif + +FailOnInit: +#ifdef DEBUG_USB_HOST + USBTRACE("OnInit:"); +#endif + +#ifdef DEBUG_USB_HOST +Fail: + NotifyFail(rcode); +#endif + Release(); + return rcode; +} diff --git a/cdc_XR21B1411.h b/cdc_XR21B1411.h new file mode 100644 index 00000000..347f0df6 --- /dev/null +++ b/cdc_XR21B1411.h @@ -0,0 +1,272 @@ +/* Copyright (C) 2015 Andrew J. Kroll + and + Circuits At Home, LTD. All rights reserved. + +This software may be distributed and modified under the terms of the GNU +General Public License version 2 (GPL2) as published by the Free Software +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(__CDC_XR21B1411_H__) +#define __CDC_XR21B1411_H__ + +#include "cdcacm.h" + +#define XR_REG_CUSTOM_DRIVER (0x020DU) // DRIVER SELECT +#define XR_REG_CUSTOM_DRIVER_ACTIVE (0x0001U) // 0: CDC 1: CUSTOM + +#define XR_REG_ACM_FLOW_CTL (0x0216U) // FLOW CONTROL REGISTER CDCACM MODE +#define XR_REG_FLOW_CTL (0x0C06U) // FLOW CONTROL REGISTER CUSTOM MODE +#define XR_REG_FLOW_CTL_HALF_DPLX (0x0008U) // 0:FULL DUPLEX 1:HALF DUPLEX +#define XR_REG_FLOW_CTL_MODE_MASK (0x0007U) // MODE BITMASK +#define XR_REG_FLOW_CTL_NONE (0x0000U) // NO FLOW CONTROL +#define XR_REG_FLOW_CTL_HW (0x0001U) // HARDWARE FLOW CONTROL +#define XR_REG_FLOW_CTL_SW (0x0002U) // SOFTWARE FLOW CONTROL +#define XR_REG_FLOW_CTL_MMMRX (0x0003U) // MULTIDROP RX UPON ADDRESS MATCH +#define XR_REG_FLOW_CTL_MMMRXTX (0x0004U) // MULTIDROP RX/TX UPON ADDRESS MATCH + +#define XR_REG_ACM_GPIO_MODE (0x0217U) // GPIO MODE REGISTER IN CDCACM MODE +#define XR_REG_GPIO_MODE (0x0C0CU) // GPIO MODE REGISTER IN CUSTOM MODE +#define XR_REG_GPIO_MODE_GPIO (0x0000U) // ALL GPIO PINS ACM PROGRAMMABLE +#define XR_REG_GPIO_MODE_FC_RTSCTS (0x0001U) // AUTO RTSCTS HW FC (GPIO 4/5) +#define XR_REG_GPIO_MODE_FC_DTRDSR (0x0002U) // AUTO DTRDSR HW FC (GPIO 2/3) +#define XR_REG_GPIO_MODE_ATE (0x0003U) // AUTO TRANSCEIVER ENABLE DURING TX (GPIO 5) +#define XR_REG_GPIO_MODE_ATE_ADDRESS (0x0004U) // AUTO TRANSCEIVER ENABLE ON ADDRESS MATCH (GPIO 5) + +#define XR_REG_ACM_GPIO_DIR (0x0218U) // GPIO DIRECTION REGISTER CDCACM MODE, 0:IN 1:OUT +#define XR_REG_GPIO_DIR (0x0C0DU) // GPIO DIRECTION REGISTER CUSTOM MODE, 0:IN 1:OUT + +#define XR_REG_ACM_GPIO_INT (0x0219U) // GPIO PIN CHANGE INTERRUPT ENABLE CDCACM MODE, 0: ENABLED 1: DISABLED +#define XR_REG_GPIO_INT (0x0C11U) // GPIO PIN CHANGE INTERRUPT ENABLE CUSTOM MODE, 0: ENABLED 1: DISABLED +#define XR_REG_GPIO_MASK (0x001FU) // GPIO REGISTERS BITMASK + +#define XR_REG_UART_ENABLE (0x0C00U) // UART I/O ENABLE REGISTER +#define XR_REG_UART_ENABLE_RX (0x0002U) // 0:DISABLED 1:ENABLED +#define XR_REG_UART_ENABLE_TX (0x0001U) // 0:DISABLED 1:ENABLED + +#define XR_REG_ERROR_STATUS (0x0C09U) // ERROR STATUS REGISTER +#define XR_REG_ERROR_STATUS_MASK (0x00F8U) // ERROR STATUS BITMASK +#define XR_REG_ERROR_STATUS_ERROR (0x0070U) // ERROR STATUS ERROR BITMASK +#define XR_REG_ERROR_STATUS_BREAK (0x0008U) // BREAK HAS BEEN DETECTED +#define XR_REG_ERROR_STATUS_OVERRUN (0x0010U) // RX OVERRUN ERROR +#define XR_REG_ERROR_STATUS_PARITY (0x0020U) // PARITY ERROR +#define XR_REG_ERROR_STATUS_FRAME (0x0040U) // FRAMING ERROR +#define XR_REG_ERROR_STATUS_BREAK (0x0080U) // BREAK IS BEING DETECTED + +#define XR_REG_TX_BREAK (0x0C0AU) // TRANSMIT BREAK. 0X0001-0XFFE TIME IN MS, 0X0000 STOP, 0X0FFF BREAK ON + +#define XR_REG_XCVR_EN_DELAY (0x0C0BU) // TURN-ARROUND DELAY IN BIT-TIMES 0X0000-0X000F + +#define XR_REG_GPIO_SET (0x0C0EU) // 1:SET GPIO PIN + +#define XR_REG_GPIO_CLR (0x0C0FU) // 1:CLEAR GPIO PIN + +#define XR_REG_GPIO_STATUS (0x0C10U) // READ GPIO PINS + +#define XR_REG_CUSTOMISED_INT (0x0C12U) // 0:STANDARD 1:CUSTOM SEE DATA SHEET + +#define XR_REG_PIN_PULLUP_ENABLE (0x0C14U) // 0:DISABLE 1:ENABLE, BITS 0-5:GPIO, 6:RX 7:TX + +#define XR_REG_PIN_PULLDOWN_ENABLE (0x0C15U) // 0:DISABLE 1:ENABLE, BITS 0-5:GPIO, 6:RX 7:TX + +#define XR_REG_LOOPBACK (0x0C16U) // 0:DISABLE 1:ENABLE, SEE DATA SHEET + +#define XR_REG_RX_FIFO_LATENCY (0x0CC2U) // FIFO LATENCY REGISTER +#define XR_REG_RX_FIFO_LATENCY_ENABLE (0x0001U) // + +#define XR_REG_WIDE_MODE (0x0D02U) +#define XR_REG_WIDE_MODE_ENABLE (0x0001U) + +#define XR_REG_XON_CHAR (0x0C07U) +#define XR_REG_XOFF_CHAR (0x0C08U) + +#define XR_REG_TX_FIFO_RESET (0x0C80U) // 1: RESET, SELF-CLEARING +#define XR_REG_TX_FIFO_COUNT (0x0C81U) // READ-ONLY +#define XR_REG_RX_FIFO_RESET (0x0CC0U) // 1: RESET, SELF-CLEARING +#define XR_REG_RX_FIFO_COUNT (0x0CC1U) // READ-ONLY + +#define XR_WRITE_REQUEST_TYPE (0x40U) + +#define XR_READ_REQUEST_TYPE (0xC0U) + +#define XR_MAX_ENDPOINTS 4 + +class XR21B1411 : public ACM { +protected: + +public: + XR21B1411(USB *pusb, CDCAsyncOper *pasync); + + /** + * Used by the USB core to check what this driver support. + * @param vid The device's VID. + * @param pid The device's PID. + * @return Returns true if the device's VID and PID matches this driver. + */ + virtual bool VIDPIDOK(uint16_t vid, uint16_t pid) { + return (((vid == 0x2890U) && (pid == 0x0201U)) || ((vid == 0x04e2U) && (pid == 0x1411U))); + }; + + uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed); + + virtual tty_features enhanced_features(void) { + tty_features rv; + rv.enhanced = true; + rv.autoflow_RTS = true; + rv.autoflow_DSR = true; + rv.autoflow_XON = true; + rv.half_duplex = true; + rv.wide = true; + return rv; + }; + + uint8_t read_register(uint16_t reg, uint16_t *val) { + return (pUsb->ctrlReq(bAddress, 0, XR_READ_REQUEST_TYPE, 1, 0, 0, reg, 2, 2, (uint8_t *)val, NULL)); + } + + uint8_t write_register(uint16_t reg, uint16_t val) { + return (pUsb->ctrlReq(bAddress, 0, XR_WRITE_REQUEST_TYPE, 0, BGRAB0(val), BGRAB1(val), reg, 0, 0, NULL, NULL)); + } + + + //////////////////////////////////////////////////////////////////////// + // The following methods set the CDC-ACM defaults. + //////////////////////////////////////////////////////////////////////// + + virtual void autoflowRTS(bool s) { + uint16_t val; + uint8_t rval; + rval = read_register(XR_REG_ACM_FLOW_CTL, &val); + if(!rval) { + if(s) { + val &= XR_REG_FLOW_CTL_HALF_DPLX; + val |= XR_REG_FLOW_CTL_HW; + } else { + val &= XR_REG_FLOW_CTL_HALF_DPLX; + } + rval = write_register(XR_REG_ACM_FLOW_CTL, val); + if(!rval) { + rval = write_register(XR_REG_ACM_GPIO_MODE, XR_REG_GPIO_MODE_GPIO); + if(!rval) { + // ACM commands apply the new settings. + LINE_CODING LCT; + rval = GetLineCoding(&LCT); + if(!rval) { + rval = SetLineCoding(&LCT); + if(!rval) { + _enhanced_status.autoflow_XON = false; + _enhanced_status.autoflow_DSR = false; + _enhanced_status.autoflow_RTS = s; + } + } + } + } + } + }; + + virtual void autoflowDSR(bool s) { + uint16_t val; + uint8_t rval; + rval = read_register(XR_REG_ACM_FLOW_CTL, &val); + if(!rval) { + if(s) { + val &= XR_REG_FLOW_CTL_HALF_DPLX; + val |= XR_REG_FLOW_CTL_HW; + } else { + val &= XR_REG_FLOW_CTL_HALF_DPLX; + } + rval = write_register(XR_REG_ACM_FLOW_CTL, val); + if(!rval) { + if(s) { + rval = write_register(XR_REG_ACM_GPIO_MODE, XR_REG_GPIO_MODE_FC_DTRDSR); + } else { + rval = write_register(XR_REG_ACM_GPIO_MODE, XR_REG_GPIO_MODE_GPIO); + } + if(!rval) { + // ACM commands apply the new settings. + LINE_CODING LCT; + rval = GetLineCoding(&LCT); + if(!rval) { + rval = SetLineCoding(&LCT); + if(!rval) { + _enhanced_status.autoflow_XON = false; + _enhanced_status.autoflow_RTS = false; + _enhanced_status.autoflow_DSR = s; + } + } + } + } + } + }; + + virtual void autoflowXON(bool s) { + // NOTE: hardware defaults to the normal XON/XOFF + uint16_t val; + uint8_t rval; + rval = read_register(XR_REG_ACM_FLOW_CTL, &val); + if(!rval) { + if(s) { + val &= XR_REG_FLOW_CTL_HALF_DPLX; + val |= XR_REG_FLOW_CTL_SW; + } else { + val &= XR_REG_FLOW_CTL_HALF_DPLX; + } + rval = write_register(XR_REG_ACM_FLOW_CTL, val); + if(!rval) { + rval = write_register(XR_REG_ACM_GPIO_MODE, XR_REG_GPIO_MODE_GPIO); + if(!rval) { + // ACM commands apply the new settings. + LINE_CODING LCT; + rval = GetLineCoding(&LCT); + if(!rval) { + rval = SetLineCoding(&LCT); + if(!rval) { + _enhanced_status.autoflow_RTS = false; + _enhanced_status.autoflow_DSR = false; + _enhanced_status.autoflow_XON = s; + } + } + } + } + } + }; + + virtual void half_duplex(bool s) { + uint16_t val; + uint8_t rval; + rval = read_register(XR_REG_ACM_FLOW_CTL, &val); + if(!rval) { + if(s) { + val |= XR_REG_FLOW_CTL_HALF_DPLX; + } else { + val &= XR_REG_FLOW_CTL_MODE_MASK; + } + rval = write_register(XR_REG_ACM_FLOW_CTL, val); + if(!rval) { + // ACM commands apply the new settings. + LINE_CODING LCT; + rval = GetLineCoding(&LCT); + if(!rval) { + rval = SetLineCoding(&LCT); + if(!rval) { + _enhanced_status.half_duplex = s; + } + } + } + } + }; + + + +}; + +#endif // __CDCPROLIFIC_H__ diff --git a/cdcacm.cpp b/cdcacm.cpp index 3d50f600..2cd2c9a8 100644 --- a/cdcacm.cpp +++ b/cdcacm.cpp @@ -1,351 +1,331 @@ -/* 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), -ready(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]; - USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast(buf); - - 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 = udd->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 = udd->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 FailSetConfDescr; - - 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: -#ifdef DEBUG_USB_HOST - NotifyFailGetDevDescr(); - goto Fail; -#endif - -FailSetDevTblEntry: -#ifdef DEBUG_USB_HOST - NotifyFailSetDevTblEntry(); - goto Fail; -#endif - -FailGetConfDescr: -#ifdef DEBUG_USB_HOST - NotifyFailGetConfDescr(); - goto Fail; -#endif - -FailSetConfDescr: -#ifdef DEBUG_USB_HOST - NotifyFailSetConfDescr(); - goto Fail; -#endif - -FailOnInit: -#ifdef DEBUG_USB_HOST - USBTRACE("OnInit:"); -#endif - -#ifdef DEBUG_USB_HOST -Fail: - NotifyFail(rcode); -#endif - 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]); - // USB_HOST_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); -} +/* 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), +ready(false) { + _enhanced_status = enhanced_features(); // Set up features + 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 = (i == epDataInIndex) ? USB_NAK_NOWAIT : 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]; + USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast(buf); + + 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 = udd->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 = udd->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 FailSetConfDescr; + + // Set up features status + _enhanced_status = enhanced_features(); + half_duplex(false); + autoflowRTS(false); + autoflowDSR(false); + autoflowXON(false); + wide(false); // Always false, because this is only available in custom mode. + rcode = pAsync->OnInit(this); + + if(rcode) + goto FailOnInit; + + USBTRACE("ACM configured\r\n"); + + ready = true; + + //bPollEnable = true; + + //USBTRACE("Poll enabled\r\n"); + return 0; + +FailGetDevDescr: +#ifdef DEBUG_USB_HOST + NotifyFailGetDevDescr(); + goto Fail; +#endif + +FailSetDevTblEntry: +#ifdef DEBUG_USB_HOST + NotifyFailSetDevTblEntry(); + goto Fail; +#endif + +FailGetConfDescr: +#ifdef DEBUG_USB_HOST + NotifyFailGetConfDescr(); + goto Fail; +#endif + +FailSetConfDescr: +#ifdef DEBUG_USB_HOST + NotifyFailSetConfDescr(); + goto Fail; +#endif + +FailOnInit: +#ifdef DEBUG_USB_HOST + USBTRACE("OnInit:"); +#endif + +#ifdef DEBUG_USB_HOST +Fail: + NotifyFail(rcode); +#endif + 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() { + ready = false; + 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; + + 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); + D_PrintHex (ep_ptr->bLength, 0x80); + Notify(PSTR("\r\nType:\t\t"), 0x80); + D_PrintHex (ep_ptr->bDescriptorType, 0x80); + Notify(PSTR("\r\nAddress:\t"), 0x80); + D_PrintHex (ep_ptr->bEndpointAddress, 0x80); + Notify(PSTR("\r\nAttributes:\t"), 0x80); + D_PrintHex (ep_ptr->bmAttributes, 0x80); + Notify(PSTR("\r\nMaxPktSize:\t"), 0x80); + D_PrintHex (ep_ptr->wMaxPacketSize, 0x80); + Notify(PSTR("\r\nPoll Intrv:\t"), 0x80); + D_PrintHex (ep_ptr->bInterval, 0x80); + Notify(PSTR("\r\n"), 0x80); +} diff --git a/cdcacm.h b/cdcacm.h index c0b6fd07..8372f56b 100644 --- a/cdcacm.h +++ b/cdcacm.h @@ -1,194 +1,252 @@ -/* 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 "Usb.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) { - }; - //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 - uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed); - uint8_t Release(); - uint8_t Poll(); - - virtual uint8_t GetAddress() { - return bAddress; - }; - - virtual bool isReady() { - return ready; - }; - - // UsbConfigXtracter implementation - void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep); -}; - -#endif // __CDCACM_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(__CDCACM_H__) +#define __CDCACM_H__ + +#include "Usb.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) { + return 0; + }; + //virtual void OnDataRcvd(ACM *pacm, uint8_t nbytes, uint8_t *dataptr) = 0; + //virtual void OnDisconnected(ACM *pacm) = 0; +}; + +/** + * This structure is used to report the extended capabilities of the connected device. + * It is also used to report the current status. + * Regular CDC-ACM reports all as false. + */ +typedef struct { + + union { + uint8_t tty; + + struct { + bool enhanced : 1; // Do we have the ability to set/clear any features? + // Status and 8th bit in data stream. + // Presence only indicates feature is available, but this isn't used for CDC-ACM. + bool wide : 1; + bool autoflow_RTS : 1; // Has autoflow on RTS/CTS + bool autoflow_DSR : 1; // Has autoflow on DTR/DSR + bool autoflow_XON : 1; // Has autoflow XON/XOFF + bool half_duplex : 1; // Has half-duplex capability. + } __attribute__((packed)); + }; +} tty_features; + +#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 + volatile bool bPollEnable; // poll enable flag + volatile bool ready; //device ready indicator + tty_features _enhanced_status; // current status + + 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 receiving and sending data + uint8_t RcvData(uint16_t *nbytesptr, uint8_t *dataptr); + uint8_t SndData(uint16_t nbytes, uint8_t *dataptr); + + // USBDeviceConfig implementation + uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed); + uint8_t Release(); + uint8_t Poll(); + + bool available(void) { + + }; + + virtual uint8_t GetAddress() { + return bAddress; + }; + + virtual bool isReady() { + return ready; + }; + + virtual tty_features enhanced_status(void) { + return _enhanced_status; + }; + + virtual tty_features enhanced_features(void) { + tty_features rv; + rv.enhanced = false; + rv.autoflow_RTS = false; + rv.autoflow_DSR = false; + rv.autoflow_XON = false; + rv.half_duplex = false; + rv.wide = false; + return rv; + }; + + virtual void autoflowRTS(bool s) { + }; + + virtual void autoflowDSR(bool s) { + }; + + virtual void autoflowXON(bool s) { + }; + + virtual void half_duplex(bool s) { + }; + + virtual void wide(bool s) { + }; + + // UsbConfigXtracter implementation + void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep); +}; + +#endif // __CDCACM_H__ diff --git a/cdcftdi.cpp b/cdcftdi.cpp index 8f07b358..80d21d16 100644 --- a/cdcftdi.cpp +++ b/cdcftdi.cpp @@ -1,339 +1,334 @@ -/* 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]; - USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast(buf); - 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), buf); - - // Restore p->epinfo - p->epinfo = oldep_ptr; - - if(rcode) - goto FailGetDevDescr; - if(udd->idVendor != FTDI_VID || udd->idProduct != FTDI_PID) - return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; - - // Save type of FTDI chip - wFTDIType = udd->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 = udd->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 = udd->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: -#ifdef DEBUG_USB_HOST - NotifyFailGetDevDescr(); - goto Fail; -#endif - -FailSetDevTblEntry: -#ifdef DEBUG_USB_HOST - NotifyFailSetDevTblEntry(); - goto Fail; -#endif - -FailGetConfDescr: -#ifdef DEBUG_USB_HOST - NotifyFailGetConfDescr(); - goto Fail; -#endif - -FailSetConfDescr: -#ifdef DEBUG_USB_HOST - NotifyFailSetConfDescr(); - goto Fail; -#endif - -FailOnInit: -#ifdef DEBUG_USB_HOST - USBTRACE("OnInit:"); - -Fail: - NotifyFail(rcode); -#endif - 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 pAsync->OnRelease(this); -} - -uint8_t FTDI::Poll() { - uint8_t rcode = 0; - - //if (!bPollEnable) - // return 0; - - //if (qNextPollTime <= millis()) - //{ - // USB_HOST_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); -} +/* 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; + epInfo[i].bmNakPower = (i==epDataInIndex) ? USB_NAK_NOWAIT: 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]; + USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast(buf); + uint8_t rcode; + UsbDevice *p = NULL; + EpInfo *oldep_ptr = NULL; + + uint8_t num_of_conf; // number of configurations + + 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), buf); + + // Restore p->epinfo + p->epinfo = oldep_ptr; + + if(rcode) + goto FailGetDevDescr; + if(udd->idVendor != FTDI_VID || udd->idProduct != FTDI_PID) + return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; + + // Save type of FTDI chip + wFTDIType = udd->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 = udd->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 = udd->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: +#ifdef DEBUG_USB_HOST + NotifyFailGetDevDescr(); + goto Fail; +#endif + +FailSetDevTblEntry: +#ifdef DEBUG_USB_HOST + NotifyFailSetDevTblEntry(); + goto Fail; +#endif + +FailGetConfDescr: +#ifdef DEBUG_USB_HOST + NotifyFailGetConfDescr(); + goto Fail; +#endif + +FailSetConfDescr: +#ifdef DEBUG_USB_HOST + NotifyFailSetConfDescr(); + goto Fail; +#endif + +FailOnInit: +#ifdef DEBUG_USB_HOST + USBTRACE("OnInit:"); + +Fail: + NotifyFail(rcode); +#endif + 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 pAsync->OnRelease(this); +} + +uint8_t FTDI::Poll() { + uint8_t rcode = 0; + + //if (!bPollEnable) + // return 0; + + //if (qNextPollTime <= millis()) + //{ + // USB_HOST_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); + D_PrintHex (ep_ptr->bLength, 0x80); + Notify(PSTR("\r\nType:\t\t"), 0x80); + D_PrintHex (ep_ptr->bDescriptorType, 0x80); + Notify(PSTR("\r\nAddress:\t"), 0x80); + D_PrintHex (ep_ptr->bEndpointAddress, 0x80); + Notify(PSTR("\r\nAttributes:\t"), 0x80); + D_PrintHex (ep_ptr->bmAttributes, 0x80); + Notify(PSTR("\r\nMaxPktSize:\t"), 0x80); + D_PrintHex (ep_ptr->wMaxPacketSize, 0x80); + Notify(PSTR("\r\nPoll Intrv:\t"), 0x80); + D_PrintHex (ep_ptr->bInterval, 0x80); + Notify(PSTR("\r\n"), 0x80); +} diff --git a/cdcftdi.h b/cdcftdi.h index d45d2389..5a133241 100644 --- a/cdcftdi.h +++ b/cdcftdi.h @@ -1,143 +1,143 @@ -/* 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 "Usb.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) { - }; - - virtual uint8_t OnRelease(FTDI *pftdi) { - }; -}; - - -// 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 - uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed); - uint8_t Release(); - uint8_t Poll(); - - virtual uint8_t GetAddress() { - return bAddress; - }; - - // UsbConfigXtracter implementation - void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep); - - virtual bool VIDPIDOK(uint16_t vid, uint16_t pid) { - return (vid == FTDI_VID && pid == FTDI_PID); - } - -}; - -#endif // __CDCFTDI_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(__CDCFTDI_H__) +#define __CDCFTDI_H__ + +#include "Usb.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) { + }; + + virtual uint8_t OnRelease(FTDI *pftdi) { + }; +}; + + +// 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 + uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed); + uint8_t Release(); + uint8_t Poll(); + + virtual uint8_t GetAddress() { + return bAddress; + }; + + // UsbConfigXtracter implementation + void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep); + + virtual bool VIDPIDOK(uint16_t vid, uint16_t pid) { + return (vid == FTDI_VID && pid == FTDI_PID); + } + +}; + +#endif // __CDCFTDI_H__ diff --git a/cdcprolific.cpp b/cdcprolific.cpp index d629ad55..6490c40e 100644 --- a/cdcprolific.cpp +++ b/cdcprolific.cpp @@ -1,210 +1,210 @@ -/* 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]; - USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast(buf); - 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(udd->idVendor != PL_VID && udd->idProduct != PL_PID) - return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; - - // Save type of PL chip - wPLType = udd->bcdDevice; - - // Allocate new address according to device class - bAddress = addrPool.AllocAddress(parent, false, port); - - if(!bAddress) - return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; - - // Extract Max Packet Size from the device descriptor - epInfo[0].maxPktSize = udd->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 = udd->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; - ready = true; - return 0; - -FailGetDevDescr: -#ifdef DEBUG_USB_HOST - NotifyFailGetDevDescr(); - goto Fail; -#endif - -FailSetDevTblEntry: -#ifdef DEBUG_USB_HOST - NotifyFailSetDevTblEntry(); - goto Fail; -#endif - -FailGetConfDescr: -#ifdef DEBUG_USB_HOST - NotifyFailGetConfDescr(); - goto Fail; -#endif - -FailSetConfDescr: -#ifdef DEBUG_USB_HOST - NotifyFailSetConfDescr(); - goto Fail; -#endif - -FailOnInit: -#ifdef DEBUG_USB_HOST - USBTRACE("OnInit:"); -#endif - -#ifdef DEBUG_USB_HOST -Fail: - NotifyFail(rcode); -#endif - Release(); - return rcode; -} - -//uint8_t PL::Poll() -//{ -// uint8_t rcode = 0; -// -// //if (!bPollEnable) -// // return 0; -// -// //if (qNextPollTime <= millis()) -// //{ -// // USB_HOST_SERIAL.println(bAddress, HEX); -// -// // qNextPollTime = millis() + 100; -// //} -// return rcode; -//} +/* 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]; + USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast(buf); + 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(udd->idVendor != PL_VID && udd->idProduct != PL_PID) + return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; + + // Save type of PL chip + wPLType = udd->bcdDevice; + + // Allocate new address according to device class + bAddress = addrPool.AllocAddress(parent, false, port); + + if(!bAddress) + return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; + + // Extract Max Packet Size from the device descriptor + epInfo[0].maxPktSize = udd->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 = udd->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; + ready = true; + return 0; + +FailGetDevDescr: +#ifdef DEBUG_USB_HOST + NotifyFailGetDevDescr(); + goto Fail; +#endif + +FailSetDevTblEntry: +#ifdef DEBUG_USB_HOST + NotifyFailSetDevTblEntry(); + goto Fail; +#endif + +FailGetConfDescr: +#ifdef DEBUG_USB_HOST + NotifyFailGetConfDescr(); + goto Fail; +#endif + +FailSetConfDescr: +#ifdef DEBUG_USB_HOST + NotifyFailSetConfDescr(); + goto Fail; +#endif + +FailOnInit: +#ifdef DEBUG_USB_HOST + USBTRACE("OnInit:"); +#endif + +#ifdef DEBUG_USB_HOST +Fail: + NotifyFail(rcode); +#endif + Release(); + return rcode; +} + +//uint8_t PL::Poll() +//{ +// uint8_t rcode = 0; +// +// //if (!bPollEnable) +// // return 0; +// +// //if (qNextPollTime <= millis()) +// //{ +// // USB_HOST_SERIAL.println(bAddress, HEX); +// +// // qNextPollTime = millis() + 100; +// //} +// return rcode; +//} diff --git a/cdcprolific.h b/cdcprolific.h index ce203fbe..32566585 100644 --- a/cdcprolific.h +++ b/cdcprolific.h @@ -1,135 +1,135 @@ -/* 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 "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< -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 UseOr; - bool ParseDescriptor(uint8_t **pp, uint16_t *pcntdn); - void PrintHidDescriptor(const USB_HID_DESCRIPTOR *pDesc); - -public: - - void SetOR(void) { - UseOr = true; - } - ConfigDescParser(UsbConfigXtracter *xtractor); - 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), -UseOr(false) { - 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) { - USB_CONFIGURATION_DESCRIPTOR* ucd = reinterpret_cast(varBuffer); - USB_INTERFACE_DESCRIPTOR* uid = reinterpret_cast(varBuffer); - 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 all ready 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 carefully. 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 = ucd->bConfigurationValue; - break; - case USB_DESCRIPTOR_INTERFACE: - if(!valParser.Parse(pp, pcntdn)) - return false; - if((MASK & CP_MASK_COMPARE_CLASS) && uid->bInterfaceClass != CLASS_ID) - break; - if((MASK & CP_MASK_COMPARE_SUBCLASS) && uid->bInterfaceSubClass != SUBCLASS_ID) - break; - if(UseOr) { - if((!((MASK & CP_MASK_COMPARE_PROTOCOL) && uid->bInterfaceProtocol))) - break; - } else { - if((MASK & CP_MASK_COMPARE_PROTOCOL) && uid->bInterfaceProtocol != PROTOCOL_ID) - break; - } - isGoodInterface = true; - ifaceNumber = uid->bInterfaceNumber; - ifaceAltSet = uid->bAlternateSetting; - protoValue = uid->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__ +/* 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(_usb_h_) || defined(__CONFDESCPARSER_H__) +#error "Never include confdescparser.h directly; include Usb.h instead" +#else + +#define __CONFDESCPARSER_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) { + }; +}; + +#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 UseOr; + bool ParseDescriptor(uint8_t **pp, uint16_t *pcntdn); + void PrintHidDescriptor(const USB_HID_DESCRIPTOR *pDesc); + +public: + + void SetOR(void) { + UseOr = true; + } + ConfigDescParser(UsbConfigXtracter *xtractor); + 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), +UseOr(false) { + 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) { + USB_CONFIGURATION_DESCRIPTOR* ucd = reinterpret_cast(varBuffer); + USB_INTERFACE_DESCRIPTOR* uid = reinterpret_cast(varBuffer); + 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 all ready 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 carefully. 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 = ucd->bConfigurationValue; + break; + case USB_DESCRIPTOR_INTERFACE: + if(!valParser.Parse(pp, pcntdn)) + return false; + if((MASK & CP_MASK_COMPARE_CLASS) && uid->bInterfaceClass != CLASS_ID) + break; + if((MASK & CP_MASK_COMPARE_SUBCLASS) && uid->bInterfaceSubClass != SUBCLASS_ID) + break; + if(UseOr) { + if((!((MASK & CP_MASK_COMPARE_PROTOCOL) && uid->bInterfaceProtocol))) + break; + } else { + if((MASK & CP_MASK_COMPARE_PROTOCOL) && uid->bInterfaceProtocol != PROTOCOL_ID) + break; + } + isGoodInterface = true; + ifaceNumber = uid->bInterfaceNumber; + ifaceAltSet = uid->bAlternateSetting; + protoValue = uid->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); + + 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__ diff --git a/examples/cdc_XR21B1411/XR_terminal/__XR_terminal.ino b/examples/cdc_XR21B1411/XR_terminal/__XR_terminal.ino new file mode 100644 index 00000000..0173a08b --- /dev/null +++ b/examples/cdc_XR21B1411/XR_terminal/__XR_terminal.ino @@ -0,0 +1,83 @@ +#include + +// Satisfy IDE, which only needs to see the include statment in the ino. +#ifdef dobogusinclude +#include +#include +#endif + +class ACMAsyncOper : public CDCAsyncOper +{ +public: + uint8_t OnInit(ACM *pacm); +}; + +uint8_t ACMAsyncOper::OnInit(ACM *pacm) +{ + uint8_t rcode; + // Set DTR = 1 RTS=1 + rcode = pacm->SetControlLineState(3); + + if (rcode) + { + ErrorMessage(PSTR("SetControlLineState"), rcode); + return rcode; + } + + LINE_CODING lc; + lc.dwDTERate = 115200; + lc.bCharFormat = 0; + lc.bParityType = 0; + lc.bDataBits = 8; + + rcode = pacm->SetLineCoding(&lc); + + if (rcode) + ErrorMessage(PSTR("SetLineCoding"), rcode); + + return rcode; +} + +USB Usb; +ACMAsyncOper AsyncOper; +XR21B1411 Acm(&Usb, &AsyncOper); + +void setup() { + Serial.begin( 115200 ); +#if !defined(__MIPSEL__) + while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection +#endif + Serial.println("\r\n\r\nStart"); + + if (Usb.Init() == -1) Serial.println("OSCOKIRQ failed to assert"); +} + +void loop() { + Usb.Task(); + if( Acm.isReady()) { + uint8_t rcode; + uint8_t buf[1]; + uint16_t rcvd = 1; + + /* read keyboard */ + if(Serial.available()) { + uint8_t data = Serial.read(); + /* send */ + rcode = Acm.SndData(1, &data); + if (rcode) + ErrorMessage(PSTR("SndData"), rcode); + } + + /* read XR serial */ + rcode = Acm.RcvData(&rcvd, buf); + if (rcode && rcode != hrNAK) + ErrorMessage(PSTR("Ret"), rcode); + + if( rcvd ) { //more than zero bytes received + for(uint16_t i=0; i < rcvd; i++ ) { + Serial.print((char)buf[i]); + } + } + } +} + diff --git a/gpl2.txt b/gpl2.txt index 45645b4b..5b6e7c66 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/hid.cpp b/hid.cpp index 174215df..0add4ff1 100644 --- a/hid.cpp +++ b/hid.cpp @@ -1,112 +1,112 @@ -/* 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 "hid.h" - -//get HID report descriptor - -/* WRONG! Endpoint is _ALWAYS_ ZERO for HID! We want the _INTERFACE_ value here! -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_HID_REPORT, USB_REQUEST_GET_DESCRIPTOR, 0x00, - HID_DESCRIPTOR_REPORT, 0x0000, 128, constBufLen, buf, (USBReadParser*)parser); - - //return ((rcode != hrSTALL) ? rcode : 0); - return rcode; -} - */ -uint8_t HID::GetReportDescr(uint16_t wIndex, USBReadParser *parser) { - const uint8_t constBufLen = 64; - uint8_t buf[constBufLen]; - - uint8_t rcode = pUsb->ctrlReq(bAddress, 0x00, bmREQ_HID_REPORT, USB_REQUEST_GET_DESCRIPTOR, 0x00, - HID_DESCRIPTOR_REPORT, wIndex, 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_HID_OUT, 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_HID_IN, 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_HID_IN, 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_HID_OUT, 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_HID_OUT, 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_HID_IN, 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); - D_PrintHex (ep_ptr->bLength, 0x80); - Notify(PSTR("\r\nType:\t\t"), 0x80); - D_PrintHex (ep_ptr->bDescriptorType, 0x80); - Notify(PSTR("\r\nAddress:\t"), 0x80); - D_PrintHex (ep_ptr->bEndpointAddress, 0x80); - Notify(PSTR("\r\nAttributes:\t"), 0x80); - D_PrintHex (ep_ptr->bmAttributes, 0x80); - Notify(PSTR("\r\nMaxPktSize:\t"), 0x80); - D_PrintHex (ep_ptr->wMaxPacketSize, 0x80); - Notify(PSTR("\r\nPoll Intrv:\t"), 0x80); - D_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); - D_PrintHex (pDesc->bLength, 0x80); - - Notify(PSTR("\r\nbDescriptorType:\t"), 0x80); - D_PrintHex (pDesc->bDescriptorType, 0x80); - - Notify(PSTR("\r\nbcdHID:\t\t\t"), 0x80); - D_PrintHex (pDesc->bcdHID, 0x80); - - Notify(PSTR("\r\nbCountryCode:\t\t"), 0x80); - D_PrintHex (pDesc->bCountryCode, 0x80); - - Notify(PSTR("\r\nbNumDescriptors:\t"), 0x80); - D_PrintHex (pDesc->bNumDescriptors, 0x80); - - Notify(PSTR("\r\nbDescrType:\t\t"), 0x80); - D_PrintHex (pDesc->bDescrType, 0x80); - - Notify(PSTR("\r\nwDescriptorLength:\t"), 0x80); - D_PrintHex (pDesc->wDescriptorLength, 0x80); -} +/* 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 "hid.h" + +//get HID report descriptor + +/* WRONG! Endpoint is _ALWAYS_ ZERO for HID! We want the _INTERFACE_ value here! +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::GetReportDescr(uint16_t wIndex, USBReadParser *parser) { + const uint8_t constBufLen = 64; + uint8_t buf[constBufLen]; + + uint8_t rcode = pUsb->ctrlReq(bAddress, 0x00, bmREQ_HIDREPORT, USB_REQUEST_GET_DESCRIPTOR, 0x00, + HID_DESCRIPTOR_REPORT, wIndex, 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); + D_PrintHex (ep_ptr->bLength, 0x80); + Notify(PSTR("\r\nType:\t\t"), 0x80); + D_PrintHex (ep_ptr->bDescriptorType, 0x80); + Notify(PSTR("\r\nAddress:\t"), 0x80); + D_PrintHex (ep_ptr->bEndpointAddress, 0x80); + Notify(PSTR("\r\nAttributes:\t"), 0x80); + D_PrintHex (ep_ptr->bmAttributes, 0x80); + Notify(PSTR("\r\nMaxPktSize:\t"), 0x80); + D_PrintHex (ep_ptr->wMaxPacketSize, 0x80); + Notify(PSTR("\r\nPoll Intrv:\t"), 0x80); + D_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); + D_PrintHex (pDesc->bLength, 0x80); + + Notify(PSTR("\r\nbDescriptorType:\t"), 0x80); + D_PrintHex (pDesc->bDescriptorType, 0x80); + + Notify(PSTR("\r\nbcdHID:\t\t\t"), 0x80); + D_PrintHex (pDesc->bcdHID, 0x80); + + Notify(PSTR("\r\nbCountryCode:\t\t"), 0x80); + D_PrintHex (pDesc->bCountryCode, 0x80); + + Notify(PSTR("\r\nbNumDescriptors:\t"), 0x80); + D_PrintHex (pDesc->bNumDescriptors, 0x80); + + Notify(PSTR("\r\nbDescrType:\t\t"), 0x80); + D_PrintHex (pDesc->bDescrType, 0x80); + + Notify(PSTR("\r\nwDescriptorLength:\t"), 0x80); + D_PrintHex (pDesc->wDescriptorLength, 0x80); +} diff --git a/hid.h b/hid.h index 651a355c..6b7d7d3f 100644 --- a/hid.h +++ b/hid.h @@ -1,184 +1,184 @@ -/* 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 "Usb.h" -#include "hidusagestr.h" - -#define MAX_REPORT_PARSERS 2 -#define HID_MAX_HID_CLASS_DESCRIPTORS 5 - -#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_HID_OUT USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE -#define bmREQ_HID_IN USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE -#define bmREQ_HID_REPORT 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 - -#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 HidItemPrefix { - uint8_t bSize : 2; - uint8_t bType : 2; - uint8_t bTag : 4; -}; - -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; -}; - -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(uint16_t wIndex, 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__ +/* 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 "Usb.h" +#include "hidusagestr.h" + +#define MAX_REPORT_PARSERS 2 +#define HID_MAX_HID_CLASS_DESCRIPTORS 5 + +#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 + +#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 HidItemPrefix { + uint8_t bSize : 2; + uint8_t bType : 2; + uint8_t bTag : 4; +}; + +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; +}; + +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(uint16_t wIndex, 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__ diff --git a/hidboot.cpp b/hidboot.cpp index abb36d45..ee063455 100644 --- a/hidboot.cpp +++ b/hidboot.cpp @@ -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 - */ -#include "hidboot.h" - -void MouseReportParser::Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf) { - MOUSEINFO *pmi = (MOUSEINFO*)buf; - // Future: - // bool event; - -#if 0 - 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; ibmLeftButton ) { - if(pmi->bmLeftButton) { - OnLeftButtonDown(pmi); - } else { - OnLeftButtonUp(pmi); - } - // Future: - // event = true; - } - - if(prevState.mouseInfo.bmRightButton != pmi->bmRightButton) { - if(pmi->bmRightButton) { - OnRightButtonDown(pmi); - } else { - OnRightButtonUp(pmi); - } - // Future: - // event = true; - } - - if(prevState.mouseInfo.bmMiddleButton != pmi->bmMiddleButton) { - if(pmi->bmMiddleButton) { - OnMiddleButtonDown(pmi); - } else { - OnMiddleButtonUp(pmi); - } - // Future: - // event = true; - } - - // - // Scroll wheel(s), are not part of the spec, but we could support it. - // Logitech wireless keyboard and mouse combo reports scroll wheel in byte 4 - // We wouldn't even need to save this information. - //if(len > 3) { - //} - // - - // Mice only report motion when they actually move! - // Why not just pass the x/y values to simplify things?? - if(pmi->dX || pmi->dY) { - OnMouseMove(pmi); - // Future: - // event = true; - } - - // - // Future: - // Provide a callback that operates on the gathered events from above. - // - // if(event) OnMouse(); - // - - // Only the first byte matters (buttons). We do NOT need to save position info. - prevState.bInfo[0] = buf[0]; -#endif - -}; - -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; - - // provide event for changed control key state - if (prevState.bInfo[0x00] != buf[0x00]) { - OnControlKeysChanged(prevState.bInfo[0x00], buf[0x00]); - } - - 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]; -}; - -const uint8_t KeyboardReportParser::numKeys[10] PROGMEM = {'!', '@', '#', '$', '%', '^', '&', '*', '(', ')'}; -const uint8_t KeyboardReportParser::symKeysUp[12] PROGMEM = {'_', '+', '{', '}', '|', '~', ':', '"', '~', '<', '>', '?'}; -const uint8_t KeyboardReportParser::symKeysLo[12] PROGMEM = {'-', '=', '[', ']', '\\', ' ', ';', '\'', '`', ',', '.', '/'}; -const uint8_t KeyboardReportParser::padKeys[5] PROGMEM = {'/', '*', '-', '+', 0x13}; - -uint8_t KeyboardReportParser::OemToAscii(uint8_t mod, uint8_t key) { - uint8_t shift = (mod & 0x22); - - // [a-z] - if (VALUE_WITHIN(key, 0x04, 0x1d)) { - // Upper case letters - if ((kbdLockingKeys.kbdLeds.bmCapsLock == 0 && shift) || - (kbdLockingKeys.kbdLeds.bmCapsLock == 1 && shift == 0)) - return (key - 4 + 'A'); - - // Lower case letters - else - return (key - 4 + 'a'); - }// Numbers - else if (VALUE_WITHIN(key, 0x1e, 0x27)) { - if (shift) - return ((uint8_t)pgm_read_byte(&getNumKeys()[key - 0x1e])); - else - return ((key == UHS_HID_BOOT_KEY_ZERO) ? '0' : key - 0x1e + '1'); - }// Keypad Numbers - else if(VALUE_WITHIN(key, 0x59, 0x61)) { - if(kbdLockingKeys.kbdLeds.bmNumLock == 1) - return (key - 0x59 + '1'); - } else if(VALUE_WITHIN(key, 0x2d, 0x38)) - return ((shift) ? (uint8_t)pgm_read_byte(&getSymKeysUp()[key - 0x2d]) : (uint8_t)pgm_read_byte(&getSymKeysLo()[key - 0x2d])); - else if(VALUE_WITHIN(key, 0x54, 0x58)) - return (uint8_t)pgm_read_byte(&getPadKeys()[key - 0x54]); - else { - switch(key) { - case UHS_HID_BOOT_KEY_SPACE: return (0x20); - case UHS_HID_BOOT_KEY_ENTER: return (0x13); - case UHS_HID_BOOT_KEY_ZERO2: return ((kbdLockingKeys.kbdLeds.bmNumLock == 1) ? '0': 0); - case UHS_HID_BOOT_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; + // Future: + // bool event; + +#if 0 + 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; ibmLeftButton ) { + if(pmi->bmLeftButton) { + OnLeftButtonDown(pmi); + } else { + OnLeftButtonUp(pmi); + } + // Future: + // event = true; + } + + if(prevState.mouseInfo.bmRightButton != pmi->bmRightButton) { + if(pmi->bmRightButton) { + OnRightButtonDown(pmi); + } else { + OnRightButtonUp(pmi); + } + // Future: + // event = true; + } + + if(prevState.mouseInfo.bmMiddleButton != pmi->bmMiddleButton) { + if(pmi->bmMiddleButton) { + OnMiddleButtonDown(pmi); + } else { + OnMiddleButtonUp(pmi); + } + // Future: + // event = true; + } + + // + // Scroll wheel(s), are not part of the spec, but we could support it. + // Logitech wireless keyboard and mouse combo reports scroll wheel in byte 4 + // We wouldn't even need to save this information. + //if(len > 3) { + //} + // + + // Mice only report motion when they actually move! + // Why not just pass the x/y values to simplify things?? + if(pmi->dX || pmi->dY) { + OnMouseMove(pmi); + // Future: + // event = true; + } + + // + // Future: + // Provide a callback that operates on the gathered events from above. + // + // if(event) OnMouse(); + // + + // Only the first byte matters (buttons). We do NOT need to save position info. + prevState.bInfo[0] = buf[0]; +#endif + +}; + +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; + + // provide event for changed control key state + if (prevState.bInfo[0x00] != buf[0x00]) { + OnControlKeysChanged(prevState.bInfo[0x00], buf[0x00]); + } + + 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]; +}; + +const uint8_t KeyboardReportParser::numKeys[10] PROGMEM = {'!', '@', '#', '$', '%', '^', '&', '*', '(', ')'}; +const uint8_t KeyboardReportParser::symKeysUp[12] PROGMEM = {'_', '+', '{', '}', '|', '~', ':', '"', '~', '<', '>', '?'}; +const uint8_t KeyboardReportParser::symKeysLo[12] PROGMEM = {'-', '=', '[', ']', '\\', ' ', ';', '\'', '`', ',', '.', '/'}; +const uint8_t KeyboardReportParser::padKeys[5] PROGMEM = {'/', '*', '-', '+', 0x13}; + +uint8_t KeyboardReportParser::OemToAscii(uint8_t mod, uint8_t key) { + uint8_t shift = (mod & 0x22); + + // [a-z] + if (VALUE_WITHIN(key, 0x04, 0x1d)) { + // 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 (VALUE_WITHIN(key, 0x1e, 0x27)) { + if (shift) + return ((uint8_t)pgm_read_byte(&getNumKeys()[key - 0x1e])); + else + return ((key == UHS_HID_BOOT_KEY_ZERO) ? '0' : key - 0x1e + '1'); + }// Keypad Numbers + else if(VALUE_WITHIN(key, 0x59, 0x61)) { + if(kbdLockingKeys.kbdLeds.bmNumLock == 1) + return (key - 0x59 + '1'); + } else if(VALUE_WITHIN(key, 0x2d, 0x38)) + return ((shift) ? (uint8_t)pgm_read_byte(&getSymKeysUp()[key - 0x2d]) : (uint8_t)pgm_read_byte(&getSymKeysLo()[key - 0x2d])); + else if(VALUE_WITHIN(key, 0x54, 0x58)) + return (uint8_t)pgm_read_byte(&getPadKeys()[key - 0x54]); + else { + switch(key) { + case UHS_HID_BOOT_KEY_SPACE: return (0x20); + case UHS_HID_BOOT_KEY_ENTER: return (0x13); + case UHS_HID_BOOT_KEY_ZERO2: return ((kbdLockingKeys.kbdLeds.bmNumLock == 1) ? '0': 0); + case UHS_HID_BOOT_KEY_PERIOD: return ((kbdLockingKeys.kbdLeds.bmNumLock == 1) ? '.': 0); + } + } + return ( 0); +} diff --git a/hidboot.h b/hidboot.h index 1acbff30..605b4c82 100644 --- a/hidboot.h +++ b/hidboot.h @@ -1,618 +1,614 @@ -/* 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 "hid.h" - -#define UHS_HID_BOOT_KEY_ZERO 0x27 -#define UHS_HID_BOOT_KEY_ENTER 0x28 -#define UHS_HID_BOOT_KEY_SPACE 0x2c -#define UHS_HID_BOOT_KEY_CAPS_LOCK 0x39 -#define UHS_HID_BOOT_KEY_SCROLL_LOCK 0x47 -#define UHS_HID_BOOT_KEY_NUM_LOCK 0x53 -#define UHS_HID_BOOT_KEY_ZERO2 0x62 -#define UHS_HID_BOOT_KEY_PERIOD 0x63 - -// Don't worry, GCC will optimize the result to a final value. -#define bitsEndpoints(p) ((((p) & HID_PROTOCOL_KEYBOARD)? 2 : 0) | (((p) & HID_PROTOCOL_MOUSE)? 1 : 0)) -#define totalEndpoints(p) ((bitsEndpoints(p) == 3) ? 3 : 2) -#define epMUL(p) ((((p) & HID_PROTOCOL_KEYBOARD)? 1 : 0) + (((p) & HID_PROTOCOL_MOUSE)? 1 : 0)) - -// Already defined in hid.h -// #define HID_MAX_HID_CLASS_DESCRIPTORS 5 - -struct MOUSEINFO { - - struct { - uint8_t bmLeftButton : 1; - uint8_t bmRightButton : 1; - uint8_t bmMiddleButton : 1; - uint8_t bmDummy : 5; - }; - int8_t dX; - int8_t dY; -}; - -class MouseReportParser : public HIDReportParser { - - union { - MOUSEINFO mouseInfo; - uint8_t bInfo[sizeof (MOUSEINFO)]; - } prevState; - -public: - 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; -}; - -class KeyboardReportParser : public HIDReportParser { - static const uint8_t numKeys[10]; - static const uint8_t symKeysUp[12]; - static const uint8_t symKeysLo[12]; - static const uint8_t padKeys[5]; - -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; - }; - - void Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf); - -protected: - - virtual uint8_t HandleLockingKeys(HID* hid, uint8_t key) { - uint8_t old_keys = kbdLockingKeys.bLeds; - - switch(key) { - case UHS_HID_BOOT_KEY_NUM_LOCK: - kbdLockingKeys.kbdLeds.bmNumLock = ~kbdLockingKeys.kbdLeds.bmNumLock; - break; - case UHS_HID_BOOT_KEY_CAPS_LOCK: - kbdLockingKeys.kbdLeds.bmCapsLock = ~kbdLockingKeys.kbdLeds.bmCapsLock; - break; - case UHS_HID_BOOT_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; - }; - - virtual void OnControlKeysChanged(uint8_t before, uint8_t after) { - }; - - virtual void OnKeyDown(uint8_t mod, uint8_t key) { - }; - - virtual void OnKeyUp(uint8_t mod, uint8_t key) { - }; - - virtual const uint8_t *getNumKeys() { - return numKeys; - }; - - virtual const uint8_t *getSymKeysUp() { - return symKeysUp; - }; - - virtual const uint8_t *getSymKeysLo() { - return symKeysLo; - }; - - virtual const uint8_t *getPadKeys() { - return padKeys; - }; -}; - -template -class HIDBoot : public HID //public USBDeviceConfig, public UsbConfigXtracter -{ - EpInfo epInfo[totalEndpoints(BOOT_PROTOCOL)]; - HIDReportParser *pRptParser[epMUL(BOOT_PROTOCOL)]; - - 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 - uint8_t bInterval; // largest interval - - void Initialize(); - - virtual HIDReportParser* GetReportParser(uint8_t id) { - return pRptParser[id]; - }; - -public: - HIDBoot(USB *p); - - virtual bool SetReportParser(uint8_t id, HIDReportParser *prs) { - pRptParser[id] = prs; - return true; - }; - - // USBDeviceConfig implementation - uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed); - uint8_t Release(); - uint8_t Poll(); - - virtual uint8_t GetAddress() { - return bAddress; - }; - - virtual bool isReady() { - return bPollEnable; - }; - - // UsbConfigXtracter implementation - // Method should be defined here if virtual. - virtual void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep); - - virtual bool DEVCLASSOK(uint8_t klass) { - return (klass == USB_CLASS_HID); - } - - virtual bool DEVSUBCLASSOK(uint8_t subklass) { - return (subklass == BOOT_PROTOCOL); - } -}; - -template -HIDBoot::HIDBoot(USB *p) : -HID(p), -qNextPollTime(0), -bPollEnable(false) { - Initialize(); - - for(int i = 0; i < epMUL(BOOT_PROTOCOL); i++) { - pRptParser[i] = NULL; - } - if(pUsb) - pUsb->RegisterDeviceClass(this); -} - -template -void HIDBoot::Initialize() { - for(int i = 0; i < totalEndpoints(BOOT_PROTOCOL); 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"); - //USBTRACE2("totalEndpoints:", (uint8_t) (totalEndpoints(BOOT_PROTOCOL))); - //USBTRACE2("epMUL:", epMUL(BOOT_PROTOCOL)); - - if(bAddress) - return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE; - - bInterval = 0; - // 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; - } - //delay(2); //per USB 2.0 sect.9.2.6.3 - - 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; - - USBTRACE2("NC:", num_of_conf); - - // GCC will optimize unused stuff away. - if((BOOT_PROTOCOL & (HID_PROTOCOL_KEYBOARD | HID_PROTOCOL_MOUSE)) == (HID_PROTOCOL_KEYBOARD | HID_PROTOCOL_MOUSE)) { - USBTRACE("HID_PROTOCOL_KEYBOARD AND MOUSE\r\n"); - ConfigDescParser< - USB_CLASS_HID, - HID_BOOT_INTF_SUBCLASS, - HID_PROTOCOL_KEYBOARD | HID_PROTOCOL_MOUSE, - CP_MASK_COMPARE_ALL > confDescrParser(this); - confDescrParser.SetOR(); // Use the OR variant. - for(uint8_t i = 0; i < num_of_conf; i++) { - pUsb->getConfDescr(bAddress, 0, i, &confDescrParser); - if(bNumEP == (uint8_t)(totalEndpoints(BOOT_PROTOCOL))) - break; - } - } else { - // GCC will optimize unused stuff away. - if(BOOT_PROTOCOL & HID_PROTOCOL_KEYBOARD) { - USBTRACE("HID_PROTOCOL_KEYBOARD\r\n"); - for(uint8_t i = 0; i < num_of_conf; i++) { - ConfigDescParser< - USB_CLASS_HID, - HID_BOOT_INTF_SUBCLASS, - HID_PROTOCOL_KEYBOARD, - CP_MASK_COMPARE_ALL> confDescrParserA(this); - - pUsb->getConfDescr(bAddress, 0, i, &confDescrParserA); - if(bNumEP == (uint8_t)(totalEndpoints(BOOT_PROTOCOL))) - break; - } - } - - // GCC will optimize unused stuff away. - if(BOOT_PROTOCOL & HID_PROTOCOL_MOUSE) { - USBTRACE("HID_PROTOCOL_MOUSE\r\n"); - for(uint8_t i = 0; i < num_of_conf; i++) { - ConfigDescParser< - USB_CLASS_HID, - HID_BOOT_INTF_SUBCLASS, - HID_PROTOCOL_MOUSE, - CP_MASK_COMPARE_ALL> confDescrParserB(this); - - pUsb->getConfDescr(bAddress, 0, i, &confDescrParserB); - if(bNumEP == ((uint8_t)(totalEndpoints(BOOT_PROTOCOL)))) - break; - - } - } - } - USBTRACE2("bNumEP:", bNumEP); - - if(bNumEP != (uint8_t)(totalEndpoints(BOOT_PROTOCOL))) { - rcode = USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; - goto Fail; - } - - // Assign epInfo to epinfo pointer - rcode = pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo); - //USBTRACE2("setEpInfoEntry returned ", rcode); - USBTRACE2("Cnf:", bConfNum); - - delay(1000); - - // Set Configuration Value - rcode = pUsb->setConf(bAddress, 0, bConfNum); - - if(rcode) - goto FailSetConfDescr; - - delay(1000); - - USBTRACE2("bIfaceNum:", bIfaceNum); - USBTRACE2("bNumIface:", bNumIface); - - // Yes, mouse wants SetProtocol and SetIdle too! - for(uint8_t i = 0; i < epMUL(BOOT_PROTOCOL); i++) { - USBTRACE2("\r\nInterface:", i); - rcode = SetProtocol(i, HID_BOOT_PROTOCOL); - if(rcode) goto FailSetProtocol; - USBTRACE2("PROTOCOL SET HID_BOOT rcode:", rcode); - rcode = SetIdle(i, 0, 0); - USBTRACE2("SET_IDLE rcode:", rcode); - // if(rcode) goto FailSetIdle; This can fail. - // Get the RPIPE and just throw it away. - SinkParser sink; - rcode = GetReportDescr(i, &sink); - USBTRACE2("RPIPE rcode:", rcode); - } - - // Get RPIPE and throw it away. - - if(BOOT_PROTOCOL & HID_PROTOCOL_KEYBOARD) { - // Wake keyboard interface by twinkling up to 5 LEDs that are in the spec. - // kana, compose, scroll, caps, num - rcode = 0x20; // Reuse rcode. - while(rcode) { - rcode >>= 1; - // Ignore any error returned, we don't care if LED is not supported - SetReport(0, 0, 2, 0, 1, &rcode); // Eventually becomes zero (All off) - delay(25); - } - } - USBTRACE("BM configured\r\n"); - - bPollEnable = true; - return 0; - -FailGetDevDescr: -#ifdef DEBUG_USB_HOST - NotifyFailGetDevDescr(); - goto Fail; -#endif - - //FailSetDevTblEntry: - //#ifdef DEBUG_USB_HOST - // NotifyFailSetDevTblEntry(); - // goto Fail; - //#endif - - //FailGetConfDescr: - //#ifdef DEBUG_USB_HOST - // NotifyFailGetConfDescr(); - // goto Fail; - //#endif - -FailSetConfDescr: -#ifdef DEBUG_USB_HOST - NotifyFailSetConfDescr(); - goto Fail; -#endif - -FailSetProtocol: -#ifdef DEBUG_USB_HOST - USBTRACE("SetProto:"); - goto Fail; -#endif - - //FailSetIdle: - //#ifdef DEBUG_USB_HOST - // USBTRACE("SetIdle:"); - //#endif - -Fail: -#ifdef DEBUG_USB_HOST - NotifyFail(rcode); -#endif - 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 considered. - //if(bNumEP > 1 && conf != bConfNum) - if(bNumEP == totalEndpoints(BOOT_PROTOCOL)) - return; - - bConfNum = conf; - bIfaceNum = iface; - - if((pep->bmAttributes & 0x03) == 3 && (pep->bEndpointAddress & 0x80) == 0x80) { - if(pep->bInterval > bInterval) bInterval = pep->bInterval; - - // 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; - 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 && ((long)(millis() - qNextPollTime) >= 0L)) { - - // To-do: optimize manually, using the for loop only if needed. - for(int i = 0; i < epMUL(BOOT_PROTOCOL); i++) { - const uint16_t const_buff_len = 16; - uint8_t buf[const_buff_len]; - - USBTRACE3("(hidboot.h) i=", i, 0x81); - USBTRACE3("(hidboot.h) epInfo[epInterruptInIndex + i].epAddr=", epInfo[epInterruptInIndex + i].epAddr, 0x81); - USBTRACE3("(hidboot.h) epInfo[epInterruptInIndex + i].maxPktSize=", epInfo[epInterruptInIndex + i].maxPktSize, 0x81); - uint16_t read = (uint16_t)epInfo[epInterruptInIndex + i].maxPktSize; - - rcode = pUsb->inTransfer(bAddress, epInfo[epInterruptInIndex + i].epAddr, &read, buf); - // SOME buggy dongles report extra keys (like sleep) using a 2 byte packet on the wrong endpoint. - // Since keyboard and mice must report at least 3 bytes, we ignore the extra data. - if(!rcode && read > 2) { - if(pRptParser[i]) - pRptParser[i]->Parse((HID*)this, 0, (uint8_t)read, buf); -#ifdef DEBUG_USB_HOST - // We really don't care about errors and anomalies unless we are debugging. - } else { - if(rcode != hrNAK) { - USBTRACE3("(hidboot.h) Poll:", rcode, 0x81); - } - if(!rcode && read) { - USBTRACE3("(hidboot.h) Strange read count: ", read, 0x80); - USBTRACE3("(hidboot.h) Interface:", i, 0x80); - } - } - - if(!rcode && read && (UsbDEBUGlvl > 0x7f)) { - for(uint8_t i = 0; i < read; i++) { - PrintHex (buf[i], 0x80); - USBTRACE1(" ", 0x80); - } - if(read) - USBTRACE1("\r\n", 0x80); -#endif - } - - } - qNextPollTime = millis() + bInterval; - } - return rcode; -} - -#endif // __HIDBOOTMOUSE_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(__HIDBOOT_H__) +#define __HIDBOOT_H__ + +#include "hid.h" + +#define UHS_HID_BOOT_KEY_ZERO 0x27 +#define UHS_HID_BOOT_KEY_ENTER 0x28 +#define UHS_HID_BOOT_KEY_SPACE 0x2c +#define UHS_HID_BOOT_KEY_CAPS_LOCK 0x39 +#define UHS_HID_BOOT_KEY_SCROLL_LOCK 0x47 +#define UHS_HID_BOOT_KEY_NUM_LOCK 0x53 +#define UHS_HID_BOOT_KEY_ZERO2 0x62 +#define UHS_HID_BOOT_KEY_PERIOD 0x63 + +// Don't worry, GCC will optimize the result to a final value. +#define bitsEndpoints(p) ((((p) & HID_PROTOCOL_KEYBOARD)? 2 : 0) | (((p) & HID_PROTOCOL_MOUSE)? 1 : 0)) +#define totalEndpoints(p) ((bitsEndpoints(p) == 3) ? 3 : 2) +#define epMUL(p) ((((p) & HID_PROTOCOL_KEYBOARD)? 1 : 0) + (((p) & HID_PROTOCOL_MOUSE)? 1 : 0)) + +// Already defined in hid.h +// #define HID_MAX_HID_CLASS_DESCRIPTORS 5 + +struct MOUSEINFO { + + struct { + uint8_t bmLeftButton : 1; + uint8_t bmRightButton : 1; + uint8_t bmMiddleButton : 1; + uint8_t bmDummy : 5; + }; + int8_t dX; + int8_t dY; +}; + +class MouseReportParser : public HIDReportParser { + + union { + MOUSEINFO mouseInfo; + uint8_t bInfo[sizeof (MOUSEINFO)]; + } prevState; + +public: + 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; +}; + +class KeyboardReportParser : public HIDReportParser { + static const uint8_t numKeys[10]; + static const uint8_t symKeysUp[12]; + static const uint8_t symKeysLo[12]; + static const uint8_t padKeys[5]; + +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; + }; + + void Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf); + +protected: + + virtual uint8_t HandleLockingKeys(HID* hid, uint8_t key) { + uint8_t old_keys = kbdLockingKeys.bLeds; + + switch(key) { + case UHS_HID_BOOT_KEY_NUM_LOCK: + kbdLockingKeys.kbdLeds.bmNumLock = ~kbdLockingKeys.kbdLeds.bmNumLock; + break; + case UHS_HID_BOOT_KEY_CAPS_LOCK: + kbdLockingKeys.kbdLeds.bmCapsLock = ~kbdLockingKeys.kbdLeds.bmCapsLock; + break; + case UHS_HID_BOOT_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; + }; + + virtual void OnControlKeysChanged(uint8_t before, uint8_t after) { + }; + + virtual void OnKeyDown(uint8_t mod, uint8_t key) { + }; + + virtual void OnKeyUp(uint8_t mod, uint8_t key) { + }; + + virtual const uint8_t *getNumKeys() { + return numKeys; + }; + + virtual const uint8_t *getSymKeysUp() { + return symKeysUp; + }; + + virtual const uint8_t *getSymKeysLo() { + return symKeysLo; + }; + + virtual const uint8_t *getPadKeys() { + return padKeys; + }; +}; + +template +class HIDBoot : public HID //public USBDeviceConfig, public UsbConfigXtracter +{ + EpInfo epInfo[totalEndpoints(BOOT_PROTOCOL)]; + HIDReportParser *pRptParser[epMUL(BOOT_PROTOCOL)]; + + 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 + uint8_t bInterval; // largest interval + + void Initialize(); + + virtual HIDReportParser* GetReportParser(uint8_t id) { + return pRptParser[id]; + }; + +public: + HIDBoot(USB *p); + + virtual bool SetReportParser(uint8_t id, HIDReportParser *prs) { + pRptParser[id] = prs; + return true; + }; + + // USBDeviceConfig implementation + uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed); + uint8_t Release(); + uint8_t Poll(); + + virtual uint8_t GetAddress() { + return bAddress; + }; + + // UsbConfigXtracter implementation + // Method should be defined here if virtual. + virtual void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep); + + virtual bool DEVCLASSOK(uint8_t klass) { + return (klass == USB_CLASS_HID); + } + + virtual bool DEVSUBCLASSOK(uint8_t subklass) { + return (subklass == BOOT_PROTOCOL); + } +}; + +template +HIDBoot::HIDBoot(USB *p) : +HID(p), +qNextPollTime(0), +bPollEnable(false) { + Initialize(); + + for(int i = 0; i < epMUL(BOOT_PROTOCOL); i++) { + pRptParser[i] = NULL; + } + if(pUsb) + pUsb->RegisterDeviceClass(this); +} + +template +void HIDBoot::Initialize() { + for(int i = 0; i < totalEndpoints(BOOT_PROTOCOL); 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"); + //USBTRACE2("totalEndpoints:", (uint8_t) (totalEndpoints(BOOT_PROTOCOL))); + //USBTRACE2("epMUL:", epMUL(BOOT_PROTOCOL)); + + if(bAddress) + return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE; + + bInterval = 0; + // 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; + } + //delay(2); //per USB 2.0 sect.9.2.6.3 + + 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; + + USBTRACE2("NC:", num_of_conf); + + // GCC will optimize unused stuff away. + if((BOOT_PROTOCOL & (HID_PROTOCOL_KEYBOARD | HID_PROTOCOL_MOUSE)) == (HID_PROTOCOL_KEYBOARD | HID_PROTOCOL_MOUSE)) { + USBTRACE("HID_PROTOCOL_KEYBOARD AND MOUSE\r\n"); + ConfigDescParser< + USB_CLASS_HID, + HID_BOOT_INTF_SUBCLASS, + HID_PROTOCOL_KEYBOARD | HID_PROTOCOL_MOUSE, + CP_MASK_COMPARE_ALL > confDescrParser(this); + confDescrParser.SetOR(); // Use the OR variant. + for(uint8_t i = 0; i < num_of_conf; i++) { + pUsb->getConfDescr(bAddress, 0, i, &confDescrParser); + if(bNumEP == (uint8_t)(totalEndpoints(BOOT_PROTOCOL))) + break; + } + } else { + // GCC will optimize unused stuff away. + if(BOOT_PROTOCOL & HID_PROTOCOL_KEYBOARD) { + USBTRACE("HID_PROTOCOL_KEYBOARD\r\n"); + for(uint8_t i = 0; i < num_of_conf; i++) { + ConfigDescParser< + USB_CLASS_HID, + HID_BOOT_INTF_SUBCLASS, + HID_PROTOCOL_KEYBOARD, + CP_MASK_COMPARE_ALL> confDescrParserA(this); + + pUsb->getConfDescr(bAddress, 0, i, &confDescrParserA); + if(bNumEP == (uint8_t)(totalEndpoints(BOOT_PROTOCOL))) + break; + } + } + + // GCC will optimize unused stuff away. + if(BOOT_PROTOCOL & HID_PROTOCOL_MOUSE) { + USBTRACE("HID_PROTOCOL_MOUSE\r\n"); + for(uint8_t i = 0; i < num_of_conf; i++) { + ConfigDescParser< + USB_CLASS_HID, + HID_BOOT_INTF_SUBCLASS, + HID_PROTOCOL_MOUSE, + CP_MASK_COMPARE_ALL> confDescrParserB(this); + + pUsb->getConfDescr(bAddress, 0, i, &confDescrParserB); + if(bNumEP == ((uint8_t)(totalEndpoints(BOOT_PROTOCOL)))) + break; + + } + } + } + USBTRACE2("bNumEP:", bNumEP); + + if(bNumEP != (uint8_t)(totalEndpoints(BOOT_PROTOCOL))) { + rcode = USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; + goto Fail; + } + + // Assign epInfo to epinfo pointer + rcode = pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo); + //USBTRACE2("setEpInfoEntry returned ", rcode); + USBTRACE2("Cnf:", bConfNum); + + delay(1000); + + // Set Configuration Value + rcode = pUsb->setConf(bAddress, 0, bConfNum); + + if(rcode) + goto FailSetConfDescr; + + delay(1000); + + USBTRACE2("bIfaceNum:", bIfaceNum); + USBTRACE2("bNumIface:", bNumIface); + + // Yes, mouse wants SetProtocol and SetIdle too! + for(uint8_t i = 0; i < epMUL(BOOT_PROTOCOL); i++) { + USBTRACE2("\r\nInterface:", i); + rcode = SetProtocol(i, HID_BOOT_PROTOCOL); + if(rcode) goto FailSetProtocol; + USBTRACE2("PROTOCOL SET HID_BOOT rcode:", rcode); + rcode = SetIdle(i, 0, 0); + USBTRACE2("SET_IDLE rcode:", rcode); + // if(rcode) goto FailSetIdle; This can fail. + // Get the RPIPE and just throw it away. + SinkParser sink; + rcode = GetReportDescr(i, &sink); + USBTRACE2("RPIPE rcode:", rcode); + } + + // Get RPIPE and throw it away. + + if(BOOT_PROTOCOL & HID_PROTOCOL_KEYBOARD) { + // Wake keyboard interface by twinkling up to 5 LEDs that are in the spec. + // kana, compose, scroll, caps, num + rcode = 0x20; // Reuse rcode. + while(rcode) { + rcode >>= 1; + // Ignore any error returned, we don't care if LED is not supported + SetReport(0, 0, 2, 0, 1, &rcode); // Eventually becomes zero (All off) + delay(25); + } + } + USBTRACE("BM configured\r\n"); + + bPollEnable = true; + return 0; + +FailGetDevDescr: +#ifdef DEBUG_USB_HOST + NotifyFailGetDevDescr(); + goto Fail; +#endif + + //FailSetDevTblEntry: + //#ifdef DEBUG_USB_HOST + // NotifyFailSetDevTblEntry(); + // goto Fail; + //#endif + + //FailGetConfDescr: + //#ifdef DEBUG_USB_HOST + // NotifyFailGetConfDescr(); + // goto Fail; + //#endif + +FailSetConfDescr: +#ifdef DEBUG_USB_HOST + NotifyFailSetConfDescr(); + goto Fail; +#endif + +FailSetProtocol: +#ifdef DEBUG_USB_HOST + USBTRACE("SetProto:"); + goto Fail; +#endif + + //FailSetIdle: + //#ifdef DEBUG_USB_HOST + // USBTRACE("SetIdle:"); + //#endif + +Fail: +#ifdef DEBUG_USB_HOST + NotifyFail(rcode); +#endif + 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 considered. + //if(bNumEP > 1 && conf != bConfNum) + if(bNumEP == totalEndpoints(BOOT_PROTOCOL)) + return; + + bConfNum = conf; + bIfaceNum = iface; + + if((pep->bmAttributes & 0x03) == 3 && (pep->bEndpointAddress & 0x80) == 0x80) { + if(pep->bInterval > bInterval) bInterval = pep->bInterval; + + // 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; + 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 && ((long)(millis() - qNextPollTime) >= 0L)) { + + // To-do: optimize manually, using the for loop only if needed. + for(int i = 0; i < epMUL(BOOT_PROTOCOL); i++) { + const uint16_t const_buff_len = 16; + uint8_t buf[const_buff_len]; + + USBTRACE3("(hidboot.h) i=", i, 0x81); + USBTRACE3("(hidboot.h) epInfo[epInterruptInIndex + i].epAddr=", epInfo[epInterruptInIndex + i].epAddr, 0x81); + USBTRACE3("(hidboot.h) epInfo[epInterruptInIndex + i].maxPktSize=", epInfo[epInterruptInIndex + i].maxPktSize, 0x81); + uint16_t read = (uint16_t)epInfo[epInterruptInIndex + i].maxPktSize; + + rcode = pUsb->inTransfer(bAddress, epInfo[epInterruptInIndex + i].epAddr, &read, buf); + // SOME buggy dongles report extra keys (like sleep) using a 2 byte packet on the wrong endpoint. + // Since keyboard and mice must report at least 3 bytes, we ignore the extra data. + if(!rcode && read > 2) { + if(pRptParser[i]) + pRptParser[i]->Parse((HID*)this, 0, (uint8_t)read, buf); +#ifdef DEBUG_USB_HOST + // We really don't care about errors and anomalies unless we are debugging. + } else { + if(rcode != hrNAK) { + USBTRACE3("(hidboot.h) Poll:", rcode, 0x81); + } + if(!rcode && read) { + USBTRACE3("(hidboot.h) Strange read count: ", read, 0x80); + USBTRACE3("(hidboot.h) Interface:", i, 0x80); + } + } + + if(!rcode && read && (UsbDEBUGlvl > 0x7f)) { + for(uint8_t i = 0; i < read; i++) { + PrintHex (buf[i], 0x80); + USBTRACE1(" ", 0x80); + } + if(read) + USBTRACE1("\r\n", 0x80); +#endif + } + + } + qNextPollTime = millis() + bInterval; + } + return rcode; +} + +#endif // __HIDBOOTMOUSE_H__ diff --git a/hidescriptorparser.cpp b/hidescriptorparser.cpp index f3040ce8..e4491b4e 100644 --- a/hidescriptorparser.cpp +++ b/hidescriptorparser.cpp @@ -1,1599 +1,1588 @@ -/* 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 "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) { - //USB_HOST_SERIAL.println(""); - //PrintHex(offset + len - cntdn); - //USB_HOST_SERIAL.print(":"); - - ParseItem(&p, &cntdn); - - //if (ParseItem(&p, &cntdn)) - // return; - } - //USBTRACE2("Total:", totalSize); -} - -void ReportDescParserBase::PrintValue(uint8_t *p, uint8_t len) { - E_Notify(PSTR("("), 0x80); - for(; len; p++, len--) - PrintHex (*p, 0x80); - E_Notify(PSTR(")"), 0x80); -} - -void ReportDescParserBase::PrintByteValue(uint8_t data) { - E_Notify(PSTR("("), 0x80); - PrintHex (data, 0x80); - E_Notify(PSTR(")"), 0x80); -} - -void ReportDescParserBase::PrintItemTitle(uint8_t prefix) { - switch(prefix & (TYPE_MASK | TAG_MASK)) { - case (TYPE_GLOBAL | TAG_GLOBAL_PUSH): - E_Notify(PSTR("\r\nPush"), 0x80); - break; - case (TYPE_GLOBAL | TAG_GLOBAL_POP): - E_Notify(PSTR("\r\nPop"), 0x80); - break; - case (TYPE_GLOBAL | TAG_GLOBAL_USAGEPAGE): - E_Notify(PSTR("\r\nUsage Page"), 0x80); - break; - case (TYPE_GLOBAL | TAG_GLOBAL_LOGICALMIN): - E_Notify(PSTR("\r\nLogical Min"), 0x80); - break; - case (TYPE_GLOBAL | TAG_GLOBAL_LOGICALMAX): - E_Notify(PSTR("\r\nLogical Max"), 0x80); - break; - case (TYPE_GLOBAL | TAG_GLOBAL_PHYSMIN): - E_Notify(PSTR("\r\nPhysical Min"), 0x80); - break; - case (TYPE_GLOBAL | TAG_GLOBAL_PHYSMAX): - E_Notify(PSTR("\r\nPhysical Max"), 0x80); - break; - case (TYPE_GLOBAL | TAG_GLOBAL_UNITEXP): - E_Notify(PSTR("\r\nUnit Exp"), 0x80); - break; - case (TYPE_GLOBAL | TAG_GLOBAL_UNIT): - E_Notify(PSTR("\r\nUnit"), 0x80); - break; - case (TYPE_GLOBAL | TAG_GLOBAL_REPORTSIZE): - E_Notify(PSTR("\r\nReport Size"), 0x80); - break; - case (TYPE_GLOBAL | TAG_GLOBAL_REPORTCOUNT): - E_Notify(PSTR("\r\nReport Count"), 0x80); - break; - case (TYPE_GLOBAL | TAG_GLOBAL_REPORTID): - E_Notify(PSTR("\r\nReport Id"), 0x80); - break; - case (TYPE_LOCAL | TAG_LOCAL_USAGE): - E_Notify(PSTR("\r\nUsage"), 0x80); - break; - case (TYPE_LOCAL | TAG_LOCAL_USAGEMIN): - E_Notify(PSTR("\r\nUsage Min"), 0x80); - break; - case (TYPE_LOCAL | TAG_LOCAL_USAGEMAX): - E_Notify(PSTR("\r\nUsage Max"), 0x80); - break; - case (TYPE_MAIN | TAG_MAIN_COLLECTION): - E_Notify(PSTR("\r\nCollection"), 0x80); - break; - case (TYPE_MAIN | TAG_MAIN_ENDCOLLECTION): - E_Notify(PSTR("\r\nEnd Collection"), 0x80); - break; - case (TYPE_MAIN | TAG_MAIN_INPUT): - E_Notify(PSTR("\r\nInput"), 0x80); - break; - case (TYPE_MAIN | TAG_MAIN_OUTPUT): - E_Notify(PSTR("\r\nOutput"), 0x80); - break; - case (TYPE_MAIN | TAG_MAIN_FEATURE): - E_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; - //reinterpret_cast<>(varBuffer); - 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) { - uint16_t* ui16 = reinterpret_cast(varBuffer); - pfUsage(*ui16); - } 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: - E_Notify(PSTR(" Physical"), 0x80); - break; - case 0x01: - E_Notify(PSTR(" Application"), 0x80); - break; - case 0x02: - E_Notify(PSTR(" Logical"), 0x80); - break; - case 0x03: - E_Notify(PSTR(" Report"), 0x80); - break; - case 0x04: - E_Notify(PSTR(" Named Array"), 0x80); - break; - case 0x05: - E_Notify(PSTR(" Usage Switch"), 0x80); - break; - case 0x06: - E_Notify(PSTR(" Usage Modifier"), 0x80); - break; - default: - E_Notify(PSTR(" Vendor Defined("), 0x80); - PrintHex (data, 0x80); - E_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; - E_Notify(PSTR("("), 0x80); - PrintBin (data, 0x80); - E_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(VALUE_BETWEEN(page, 0x00, 0x11)) - pfUsage = (usagePageFunctions[page - 1]); - - // Dead code... - // - // pfUsage = (UsagePageFunc)pgm_read_pointer(usagePageFunctions[page - 1]); - //else if (page > 0x7f && page < 0x84) - // E_Notify(pstrUsagePageMonitor); - //else if (page > 0x83 && page < 0x8c) - // E_Notify(pstrUsagePagePower); - //else if (page > 0x8b && page < 0x92) - // E_Notify((char*)pgm_read_pointer(&usagePageTitles1[page - 0x8c])); - //else if (page > 0xfeff && page <= 0xffff) - // E_Notify(pstrUsagePageVendorDefined); - // - else - switch(page) { - case 0x14: - pfUsage = &ReportDescParserBase::PrintAlphanumDisplayPageUsage; - break; - case 0x40: - pfUsage = &ReportDescParserBase::PrintMedicalInstrumentPageUsage; - break; - } -} - -void ReportDescParserBase::PrintUsagePage(uint16_t page) { - const char * const * w; - E_Notify(pstrSpace, 0x80); - - output_if_between(page, 0x00, 0x11, w, E_Notify, usagePageTitles0, 0x80) - else output_if_between(page, 0x8b, 0x92, w, E_Notify, usagePageTitles1, 0x80) - else if(VALUE_BETWEEN(page, 0x7f, 0x84)) - E_Notify(pstrUsagePageMonitor, 0x80); - else if(VALUE_BETWEEN(page, 0x83, 0x8c)) - E_Notify(pstrUsagePagePower, 0x80); - else if(page > 0xfeff /* && page <= 0xffff */) - E_Notify(pstrUsagePageVendorDefined, 0x80); - else - switch(page) { - case 0x14: - E_Notify(pstrUsagePageAlphaNumericDisplay, 0x80); - break; - case 0x40: - E_Notify(pstrUsagePageMedicalInstruments, 0x80); - break; - default: - E_Notify(pstrUsagePageUndefined, 0x80); - } -} - -void ReportDescParserBase::PrintButtonPageUsage(uint16_t usage) { - E_Notify(pstrSpace, 0x80); - E_Notify(PSTR("Btn"), 0x80); - PrintHex (usage, 0x80); - E_Notify(PSTR("\r\n"), 0x80); - //USB_HOST_SERIAL.print(usage, HEX); -} - -void ReportDescParserBase::PrintOrdinalPageUsage(uint16_t usage) { - E_Notify(pstrSpace, 0x80); - E_Notify(PSTR("Inst"), 0x80); - // Sorry, HEX for now... - PrintHex (usage, 0x80); - E_Notify(PSTR("\r\n"), 0x80); - //USB_HOST_SERIAL.print(usage, DEC); -} - -void ReportDescParserBase::PrintGenericDesktopPageUsage(uint16_t usage) { - const char * const * w; - E_Notify(pstrSpace, 0x80); - - output_if_between(usage, 0x00, 0x0a, w, E_Notify, genDesktopTitles0, 0x80) - else output_if_between(usage, 0x2f, 0x49, w, E_Notify, genDesktopTitles1, 0x80) - else output_if_between(usage, 0x7f, 0x94, w, E_Notify, genDesktopTitles2, 0x80) - else output_if_between(usage, 0x9f, 0xa9, w, E_Notify, genDesktopTitles3, 0x80) - else output_if_between(usage, 0xaf, 0xb8, w, E_Notify, genDesktopTitles4, 0x80) - else E_Notify(pstrUsagePageUndefined, 0x80); -} - -void ReportDescParserBase::PrintSimulationControlsPageUsage(uint16_t usage) { - const char * const * w; - E_Notify(pstrSpace, 0x80); - - output_if_between(usage, 0x00, 0x0d, w, E_Notify, simuTitles0, 0x80) - else output_if_between(usage, 0x1f, 0x26, w, E_Notify, simuTitles1, 0x80) - else output_if_between(usage, 0xaf, 0xd1, w, E_Notify, simuTitles2, 0x80) - else E_Notify(pstrUsagePageUndefined, 0x80); -} - -void ReportDescParserBase::PrintVRControlsPageUsage(uint16_t usage) { - const char * const * w; - E_Notify(pstrSpace, 0x80); - - output_if_between(usage, 0x00, 0x0b, w, E_Notify, vrTitles0, 0x80) - else output_if_between(usage, 0x1f, 0x22, w, E_Notify, vrTitles1, 0x80) - else E_Notify(pstrUsagePageUndefined, 0x80); -} - -void ReportDescParserBase::PrintSportsControlsPageUsage(uint16_t usage) { - const char * const * w; - E_Notify(pstrSpace, 0x80); - - output_if_between(usage, 0x00, 0x05, w, E_Notify, sportsCtrlTitles0, 0x80) - else output_if_between(usage, 0x2f, 0x3a, w, E_Notify, sportsCtrlTitles1, 0x80) - else output_if_between(usage, 0x4f, 0x64, w, E_Notify, sportsCtrlTitles2, 0x80) - else E_Notify(pstrUsagePageUndefined, 0x80); -} - -void ReportDescParserBase::PrintGameControlsPageUsage(uint16_t usage) { - const char * const * w; - E_Notify(pstrSpace, 0x80); - - output_if_between(usage, 0x00, 0x04, w, E_Notify, gameTitles0, 0x80) - else output_if_between(usage, 0x1f, 0x3a, w, E_Notify, gameTitles1, 0x80) - else E_Notify(pstrUsagePageUndefined, 0x80); -} - -void ReportDescParserBase::PrintGenericDeviceControlsPageUsage(uint16_t usage) { - const char * const * w; - E_Notify(pstrSpace, 0x80); - - output_if_between(usage, 0x1f, 0x27, w, E_Notify, genDevCtrlTitles, 0x80) - else E_Notify(pstrUsagePageUndefined, 0x80); -} - -void ReportDescParserBase::PrintLEDPageUsage(uint16_t usage) { - const char * const * w; - E_Notify(pstrSpace, 0x80); - - output_if_between(usage, 0x00, 0x4e, w, E_Notify, ledTitles, 0x80) - else E_Notify(pstrUsagePageUndefined, 0x80); -} - -void ReportDescParserBase::PrintTelephonyPageUsage(uint16_t usage) { - const char * const * w; - E_Notify(pstrSpace, 0x80); - - output_if_between(usage, 0x00, 0x08, w, E_Notify, telTitles0, 0x80) - else output_if_between(usage, 0x1f, 0x32, w, E_Notify, telTitles1, 0x80) - else output_if_between(usage, 0x4f, 0x54, w, E_Notify, telTitles2, 0x80) - else output_if_between(usage, 0x6f, 0x75, w, E_Notify, telTitles3, 0x80) - else output_if_between(usage, 0x8f, 0x9f, w, E_Notify, telTitles4, 0x80) - else output_if_between(usage, 0xaf, 0xc0, w, E_Notify, telTitles5, 0x80) - else E_Notify(pstrUsagePageUndefined, 0x80); -} - -void ReportDescParserBase::PrintConsumerPageUsage(uint16_t usage) { - const char * const * w; - E_Notify(pstrSpace, 0x80); - - output_if_between(usage, 0x00, 0x07, w, E_Notify, consTitles0, 0x80) - else output_if_between(usage, 0x1f, 0x23, w, E_Notify, consTitles1, 0x80) - else output_if_between(usage, 0x2f, 0x37, w, E_Notify, consTitles2, 0x80) - else output_if_between(usage, 0x3f, 0x49, w, E_Notify, consTitles3, 0x80) - else output_if_between(usage, 0x5f, 0x67, w, E_Notify, consTitles4, 0x80) - else output_if_between(usage, 0x7f, 0xa5, w, E_Notify, consTitles5, 0x80) - else output_if_between(usage, 0xaf, 0xcf, w, E_Notify, consTitles6, 0x80) - else output_if_between(usage, 0xdf, 0xeb, w, E_Notify, consTitles7, 0x80) - else output_if_between(usage, 0xef, 0xf6, w, E_Notify, consTitles8, 0x80) - else output_if_between(usage, 0xff, 0x10e, w, E_Notify, consTitles9, 0x80) - else output_if_between(usage, 0x14f, 0x156, w, E_Notify, consTitlesA, 0x80) - else output_if_between(usage, 0x15f, 0x16b, w, E_Notify, consTitlesB, 0x80) - else output_if_between(usage, 0x16f, 0x175, w, E_Notify, consTitlesC, 0x80) - else output_if_between(usage, 0x17f, 0x1c8, w, E_Notify, consTitlesD, 0x80) - else output_if_between(usage, 0x1ff, 0x29d, w, E_Notify, consTitlesE, 0x80) - else E_Notify(pstrUsagePageUndefined, 0x80); -} - -void ReportDescParserBase::PrintDigitizerPageUsage(uint16_t usage) { - const char * const * w; - E_Notify(pstrSpace, 0x80); - - output_if_between(usage, 0x00, 0x0e, w, E_Notify, digitTitles0, 0x80) - else output_if_between(usage, 0x1f, 0x23, w, E_Notify, digitTitles1, 0x80) - else output_if_between(usage, 0x2f, 0x47, w, E_Notify, digitTitles2, 0x80) - else E_Notify(pstrUsagePageUndefined, 0x80); -} - -void ReportDescParserBase::PrintAlphanumDisplayPageUsage(uint16_t usage) { - const char * const * w; - E_Notify(pstrSpace, 0x80); - - output_if_between(usage, 0x00, 0x03, w, E_Notify, aplphanumTitles0, 0x80) - else output_if_between(usage, 0x1f, 0x4e, w, E_Notify, aplphanumTitles1, 0x80) - else output_if_between(usage, 0x7f, 0x96, w, E_Notify, digitTitles2, 0x80) - else E_Notify(pstrUsagePageUndefined, 0x80); -} - -void ReportDescParserBase::PrintMedicalInstrumentPageUsage(uint16_t usage) { - const char * const * w; - E_Notify(pstrSpace, 0x80); - - if(usage == 1) E_Notify(pstrUsageMedicalUltrasound, 0x80); - else if(usage == 0x70) - E_Notify(pstrUsageDepthGainCompensation, 0x80); - else output_if_between(usage, 0x1f, 0x28, w, E_Notify, medInstrTitles0, 0x80) - else output_if_between(usage, 0x3f, 0x45, w, E_Notify, medInstrTitles1, 0x80) - else output_if_between(usage, 0x5f, 0x62, w, E_Notify, medInstrTitles2, 0x80) - else output_if_between(usage, 0x7f, 0x8a, w, E_Notify, medInstrTitles3, 0x80) - else output_if_between(usage, 0x9f, 0xa2, w, E_Notify, medInstrTitles4, 0x80) - else E_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) { - uint16_t* ui16 = reinterpret_cast(varBuffer); - pfUsage(*ui16); - } 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); - } - E_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); -} +/* 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 "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) { + //USB_HOST_SERIAL.println(""); + //PrintHex(offset + len - cntdn); + //USB_HOST_SERIAL.print(":"); + + ParseItem(&p, &cntdn); + + //if (ParseItem(&p, &cntdn)) + // return; + } + //USBTRACE2("Total:", totalSize); +} + +void ReportDescParserBase::PrintValue(uint8_t *p, uint8_t len) { + E_Notify(PSTR("("), 0x80); + for(; len; p++, len--) + PrintHex (*p, 0x80); + E_Notify(PSTR(")"), 0x80); +} + +void ReportDescParserBase::PrintByteValue(uint8_t data) { + E_Notify(PSTR("("), 0x80); + PrintHex (data, 0x80); + E_Notify(PSTR(")"), 0x80); +} + +void ReportDescParserBase::PrintItemTitle(uint8_t prefix) { + switch(prefix & (TYPE_MASK | TAG_MASK)) { + case (TYPE_GLOBAL | TAG_GLOBAL_PUSH): + E_Notify(PSTR("\r\nPush"), 0x80); + break; + case (TYPE_GLOBAL | TAG_GLOBAL_POP): + E_Notify(PSTR("\r\nPop"), 0x80); + break; + case (TYPE_GLOBAL | TAG_GLOBAL_USAGEPAGE): + E_Notify(PSTR("\r\nUsage Page"), 0x80); + break; + case (TYPE_GLOBAL | TAG_GLOBAL_LOGICALMIN): + E_Notify(PSTR("\r\nLogical Min"), 0x80); + break; + case (TYPE_GLOBAL | TAG_GLOBAL_LOGICALMAX): + E_Notify(PSTR("\r\nLogical Max"), 0x80); + break; + case (TYPE_GLOBAL | TAG_GLOBAL_PHYSMIN): + E_Notify(PSTR("\r\nPhysical Min"), 0x80); + break; + case (TYPE_GLOBAL | TAG_GLOBAL_PHYSMAX): + E_Notify(PSTR("\r\nPhysical Max"), 0x80); + break; + case (TYPE_GLOBAL | TAG_GLOBAL_UNITEXP): + E_Notify(PSTR("\r\nUnit Exp"), 0x80); + break; + case (TYPE_GLOBAL | TAG_GLOBAL_UNIT): + E_Notify(PSTR("\r\nUnit"), 0x80); + break; + case (TYPE_GLOBAL | TAG_GLOBAL_REPORTSIZE): + E_Notify(PSTR("\r\nReport Size"), 0x80); + break; + case (TYPE_GLOBAL | TAG_GLOBAL_REPORTCOUNT): + E_Notify(PSTR("\r\nReport Count"), 0x80); + break; + case (TYPE_GLOBAL | TAG_GLOBAL_REPORTID): + E_Notify(PSTR("\r\nReport Id"), 0x80); + break; + case (TYPE_LOCAL | TAG_LOCAL_USAGE): + E_Notify(PSTR("\r\nUsage"), 0x80); + break; + case (TYPE_LOCAL | TAG_LOCAL_USAGEMIN): + E_Notify(PSTR("\r\nUsage Min"), 0x80); + break; + case (TYPE_LOCAL | TAG_LOCAL_USAGEMAX): + E_Notify(PSTR("\r\nUsage Max"), 0x80); + break; + case (TYPE_MAIN | TAG_MAIN_COLLECTION): + E_Notify(PSTR("\r\nCollection"), 0x80); + break; + case (TYPE_MAIN | TAG_MAIN_ENDCOLLECTION): + E_Notify(PSTR("\r\nEnd Collection"), 0x80); + break; + case (TYPE_MAIN | TAG_MAIN_INPUT): + E_Notify(PSTR("\r\nInput"), 0x80); + break; + case (TYPE_MAIN | TAG_MAIN_OUTPUT): + E_Notify(PSTR("\r\nOutput"), 0x80); + break; + case (TYPE_MAIN | TAG_MAIN_FEATURE): + E_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; + //reinterpret_cast<>(varBuffer); + 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) { + uint16_t* ui16 = reinterpret_cast(varBuffer); + pfUsage(*ui16); + } 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: + E_Notify(PSTR(" Physical"), 0x80); + break; + case 0x01: + E_Notify(PSTR(" Application"), 0x80); + break; + case 0x02: + E_Notify(PSTR(" Logical"), 0x80); + break; + case 0x03: + E_Notify(PSTR(" Report"), 0x80); + break; + case 0x04: + E_Notify(PSTR(" Named Array"), 0x80); + break; + case 0x05: + E_Notify(PSTR(" Usage Switch"), 0x80); + break; + case 0x06: + E_Notify(PSTR(" Usage Modifier"), 0x80); + break; + default: + E_Notify(PSTR(" Vendor Defined("), 0x80); + PrintHex (data, 0x80); + E_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; + E_Notify(PSTR("("), 0x80); + PrintBin (data, 0x80); + E_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(VALUE_BETWEEN(page, 0x00, 0x11)) { + pfUsage = (usagePageFunctions[page - 1]); + + } else { + switch(page) { + case 0x14: + pfUsage = &ReportDescParserBase::PrintAlphanumDisplayPageUsage; + break; + case 0x40: + pfUsage = &ReportDescParserBase::PrintMedicalInstrumentPageUsage; + break; + } + } +} + +void ReportDescParserBase::PrintUsagePage(uint16_t page) { + const char * const * w; + E_Notify(pstrSpace, 0x80); + + output_if_between(page, 0x00, 0x11, w, E_Notify, usagePageTitles0, 0x80) + else output_if_between(page, 0x8b, 0x92, w, E_Notify, usagePageTitles1, 0x80) + else if(VALUE_BETWEEN(page, 0x7f, 0x84)) + E_Notify(pstrUsagePageMonitor, 0x80); + else if(VALUE_BETWEEN(page, 0x83, 0x8c)) + E_Notify(pstrUsagePagePower, 0x80); + else if(page > 0xfeff /* && page <= 0xffff */) + E_Notify(pstrUsagePageVendorDefined, 0x80); + else + switch(page) { + case 0x14: + E_Notify(pstrUsagePageAlphaNumericDisplay, 0x80); + break; + case 0x40: + E_Notify(pstrUsagePageMedicalInstruments, 0x80); + break; + default: + E_Notify(pstrUsagePageUndefined, 0x80); + } +} + +void ReportDescParserBase::PrintButtonPageUsage(uint16_t usage) { + E_Notify(pstrSpace, 0x80); + E_Notify(PSTR("Btn"), 0x80); + PrintHex (usage, 0x80); + E_Notify(PSTR("\r\n"), 0x80); + //USB_HOST_SERIAL.print(usage, HEX); +} + +void ReportDescParserBase::PrintOrdinalPageUsage(uint16_t usage) { + E_Notify(pstrSpace, 0x80); + E_Notify(PSTR("Inst"), 0x80); + // Sorry, HEX for now... + PrintHex (usage, 0x80); + E_Notify(PSTR("\r\n"), 0x80); + //USB_HOST_SERIAL.print(usage, DEC); +} + +void ReportDescParserBase::PrintGenericDesktopPageUsage(uint16_t usage) { + const char * const * w; + E_Notify(pstrSpace, 0x80); + + output_if_between(usage, 0x00, 0x0a, w, E_Notify, genDesktopTitles0, 0x80) + else output_if_between(usage, 0x2f, 0x49, w, E_Notify, genDesktopTitles1, 0x80) + else output_if_between(usage, 0x7f, 0x94, w, E_Notify, genDesktopTitles2, 0x80) + else output_if_between(usage, 0x9f, 0xa9, w, E_Notify, genDesktopTitles3, 0x80) + else output_if_between(usage, 0xaf, 0xb8, w, E_Notify, genDesktopTitles4, 0x80) + else E_Notify(pstrUsagePageUndefined, 0x80); +} + +void ReportDescParserBase::PrintSimulationControlsPageUsage(uint16_t usage) { + const char * const * w; + E_Notify(pstrSpace, 0x80); + + output_if_between(usage, 0x00, 0x0d, w, E_Notify, simuTitles0, 0x80) + else output_if_between(usage, 0x1f, 0x26, w, E_Notify, simuTitles1, 0x80) + else output_if_between(usage, 0xaf, 0xd1, w, E_Notify, simuTitles2, 0x80) + else E_Notify(pstrUsagePageUndefined, 0x80); +} + +void ReportDescParserBase::PrintVRControlsPageUsage(uint16_t usage) { + const char * const * w; + E_Notify(pstrSpace, 0x80); + + output_if_between(usage, 0x00, 0x0b, w, E_Notify, vrTitles0, 0x80) + else output_if_between(usage, 0x1f, 0x22, w, E_Notify, vrTitles1, 0x80) + else E_Notify(pstrUsagePageUndefined, 0x80); +} + +void ReportDescParserBase::PrintSportsControlsPageUsage(uint16_t usage) { + const char * const * w; + E_Notify(pstrSpace, 0x80); + + output_if_between(usage, 0x00, 0x05, w, E_Notify, sportsCtrlTitles0, 0x80) + else output_if_between(usage, 0x2f, 0x3a, w, E_Notify, sportsCtrlTitles1, 0x80) + else output_if_between(usage, 0x4f, 0x64, w, E_Notify, sportsCtrlTitles2, 0x80) + else E_Notify(pstrUsagePageUndefined, 0x80); +} + +void ReportDescParserBase::PrintGameControlsPageUsage(uint16_t usage) { + const char * const * w; + E_Notify(pstrSpace, 0x80); + + output_if_between(usage, 0x00, 0x04, w, E_Notify, gameTitles0, 0x80) + else output_if_between(usage, 0x1f, 0x3a, w, E_Notify, gameTitles1, 0x80) + else E_Notify(pstrUsagePageUndefined, 0x80); +} + +void ReportDescParserBase::PrintGenericDeviceControlsPageUsage(uint16_t usage) { + const char * const * w; + E_Notify(pstrSpace, 0x80); + + output_if_between(usage, 0x1f, 0x27, w, E_Notify, genDevCtrlTitles, 0x80) + else E_Notify(pstrUsagePageUndefined, 0x80); +} + +void ReportDescParserBase::PrintLEDPageUsage(uint16_t usage) { + const char * const * w; + E_Notify(pstrSpace, 0x80); + + output_if_between(usage, 0x00, 0x4e, w, E_Notify, ledTitles, 0x80) + else E_Notify(pstrUsagePageUndefined, 0x80); +} + +void ReportDescParserBase::PrintTelephonyPageUsage(uint16_t usage) { + const char * const * w; + E_Notify(pstrSpace, 0x80); + + output_if_between(usage, 0x00, 0x08, w, E_Notify, telTitles0, 0x80) + else output_if_between(usage, 0x1f, 0x32, w, E_Notify, telTitles1, 0x80) + else output_if_between(usage, 0x4f, 0x54, w, E_Notify, telTitles2, 0x80) + else output_if_between(usage, 0x6f, 0x75, w, E_Notify, telTitles3, 0x80) + else output_if_between(usage, 0x8f, 0x9f, w, E_Notify, telTitles4, 0x80) + else output_if_between(usage, 0xaf, 0xc0, w, E_Notify, telTitles5, 0x80) + else E_Notify(pstrUsagePageUndefined, 0x80); +} + +void ReportDescParserBase::PrintConsumerPageUsage(uint16_t usage) { + const char * const * w; + E_Notify(pstrSpace, 0x80); + + output_if_between(usage, 0x00, 0x07, w, E_Notify, consTitles0, 0x80) + else output_if_between(usage, 0x1f, 0x23, w, E_Notify, consTitles1, 0x80) + else output_if_between(usage, 0x2f, 0x37, w, E_Notify, consTitles2, 0x80) + else output_if_between(usage, 0x3f, 0x49, w, E_Notify, consTitles3, 0x80) + else output_if_between(usage, 0x5f, 0x67, w, E_Notify, consTitles4, 0x80) + else output_if_between(usage, 0x7f, 0xa5, w, E_Notify, consTitles5, 0x80) + else output_if_between(usage, 0xaf, 0xcf, w, E_Notify, consTitles6, 0x80) + else output_if_between(usage, 0xdf, 0xeb, w, E_Notify, consTitles7, 0x80) + else output_if_between(usage, 0xef, 0xf6, w, E_Notify, consTitles8, 0x80) + else output_if_between(usage, 0xff, 0x10e, w, E_Notify, consTitles9, 0x80) + else output_if_between(usage, 0x14f, 0x156, w, E_Notify, consTitlesA, 0x80) + else output_if_between(usage, 0x15f, 0x16b, w, E_Notify, consTitlesB, 0x80) + else output_if_between(usage, 0x16f, 0x175, w, E_Notify, consTitlesC, 0x80) + else output_if_between(usage, 0x17f, 0x1c8, w, E_Notify, consTitlesD, 0x80) + else output_if_between(usage, 0x1ff, 0x29d, w, E_Notify, consTitlesE, 0x80) + else E_Notify(pstrUsagePageUndefined, 0x80); +} + +void ReportDescParserBase::PrintDigitizerPageUsage(uint16_t usage) { + const char * const * w; + E_Notify(pstrSpace, 0x80); + + output_if_between(usage, 0x00, 0x0e, w, E_Notify, digitTitles0, 0x80) + else output_if_between(usage, 0x1f, 0x23, w, E_Notify, digitTitles1, 0x80) + else output_if_between(usage, 0x2f, 0x47, w, E_Notify, digitTitles2, 0x80) + else E_Notify(pstrUsagePageUndefined, 0x80); +} + +void ReportDescParserBase::PrintAlphanumDisplayPageUsage(uint16_t usage) { + const char * const * w; + E_Notify(pstrSpace, 0x80); + + output_if_between(usage, 0x00, 0x03, w, E_Notify, aplphanumTitles0, 0x80) + else output_if_between(usage, 0x1f, 0x4e, w, E_Notify, aplphanumTitles1, 0x80) + else output_if_between(usage, 0x7f, 0x96, w, E_Notify, digitTitles2, 0x80) + else E_Notify(pstrUsagePageUndefined, 0x80); +} + +void ReportDescParserBase::PrintMedicalInstrumentPageUsage(uint16_t usage) { + const char * const * w; + E_Notify(pstrSpace, 0x80); + + if(usage == 1) E_Notify(pstrUsageMedicalUltrasound, 0x80); + else if(usage == 0x70) + E_Notify(pstrUsageDepthGainCompensation, 0x80); + else output_if_between(usage, 0x1f, 0x28, w, E_Notify, medInstrTitles0, 0x80) + else output_if_between(usage, 0x3f, 0x45, w, E_Notify, medInstrTitles1, 0x80) + else output_if_between(usage, 0x5f, 0x62, w, E_Notify, medInstrTitles2, 0x80) + else output_if_between(usage, 0x7f, 0x8a, w, E_Notify, medInstrTitles3, 0x80) + else output_if_between(usage, 0x9f, 0xa2, w, E_Notify, medInstrTitles4, 0x80) + else E_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) { + uint16_t* ui16 = reinterpret_cast(varBuffer); + pfUsage(*ui16); + } 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); + } + E_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); +} diff --git a/hidescriptorparser.h b/hidescriptorparser.h index e5fd17d8..f3b496ff 100644 --- a/hidescriptorparser.h +++ b/hidescriptorparser.h @@ -1,176 +1,176 @@ -/* 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 "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 - - // Method should be defined here if virtual. - 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); - }; - - 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: - // Method should be defined here if virtual. - 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: - // Method should be defined here if virtual. - virtual void Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf); -}; - -#endif // __HIDDESCRIPTORPARSER_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(__HIDDESCRIPTORPARSER_H__) +#define __HIDDESCRIPTORPARSER_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 + + // Method should be defined here if virtual. + 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); + }; + + 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: + // Method should be defined here if virtual. + 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: + // Method should be defined here if virtual. + virtual void Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf); +}; + +#endif // __HIDDESCRIPTORPARSER_H__ diff --git a/hiduniversal.cpp b/hiduniversal.cpp index 3cca8cfb..95838728 100644 --- a/hiduniversal.cpp +++ b/hiduniversal.cpp @@ -1,426 +1,420 @@ -/* 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 "hiduniversal.h" - -HIDUniversal::HIDUniversal(USB *p) : -HID(p), -qNextPollTime(0), -pollInterval(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; - pollInterval = 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]; - USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast(buf); - 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 = udd->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; - } - - //delay(2); //per USB 2.0 sect.9.2.6.3 - - 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; - - VID = udd->idVendor; // Can be used by classes that inherits this class to check the VID and PID of the connected device - PID = udd->idProduct; - - num_of_conf = udd->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("Cnf:", 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: -#ifdef DEBUG_USB_HOST - NotifyFailGetDevDescr(); - goto Fail; -#endif - -FailSetDevTblEntry: -#ifdef DEBUG_USB_HOST - NotifyFailSetDevTblEntry(); - goto Fail; -#endif - -FailGetConfDescr: -#ifdef DEBUG_USB_HOST - NotifyFailGetConfDescr(); - goto Fail; -#endif - -FailSetConfDescr: -#ifdef DEBUG_USB_HOST - NotifyFailSetConfDescr(); - goto Fail; -#endif - - -FailSetIdle: -#ifdef DEBUG_USB_HOST - USBTRACE("SetIdle:"); -#endif - -#ifdef DEBUG_USB_HOST -Fail: - NotifyFail(rcode); -#endif - 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); - - if(pollInterval < pep->bInterval) // Set the polling interval as the largest polling interval obtained from endpoints - pollInterval = pep->bInterval; - - 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((long)(millis() - qNextPollTime) >= 0L) { - qNextPollTime = millis() + pollInterval; - - 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) - USBTRACE3("(hiduniversal.h) Poll:", rcode, 0x81); - return rcode; - } - - if(read > constBuffLen) - read = constBuffLen; - - bool identical = BuffersIdentical(read, buf, prevBuf); - - SaveBuffer(read, buf, prevBuf); - - if(identical) - return 0; -#if 0 - Notify(PSTR("\r\nBuf: "), 0x80); - - for(uint8_t i = 0; i < read; i++) { - D_PrintHex (buf[i], 0x80); - Notify(PSTR(" "), 0x80); - } - - Notify(PSTR("\r\n"), 0x80); -#endif - ParseHIDData(this, bHasReportId, (uint8_t)read, buf); - - HIDReportParser *prs = GetReportParser(((bHasReportId) ? *buf : 0)); - - if(prs) - prs->Parse(this, bHasReportId, (uint8_t)read, buf); - } - } - return rcode; -} - - -//Send a report to interrupt out endpoint. This is NOT SetReport() request! -uint8_t HIDUniversal::SndRpt(uint16_t nbytes, uint8_t *dataptr) { - return pUsb->outTransfer(bAddress, epInfo[epInterruptOutIndex].epAddr, nbytes, dataptr); -} \ 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 + */ + +#include "hiduniversal.h" + +HIDUniversal::HIDUniversal(USB *p) : +HID(p), +qNextPollTime(0), +pollInterval(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; + pollInterval = 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]; + USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast(buf); + 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 = udd->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; + } + + //delay(2); //per USB 2.0 sect.9.2.6.3 + + 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; + + VID = udd->idVendor; // Can be used by classes that inherits this class to check the VID and PID of the connected device + PID = udd->idProduct; + + num_of_conf = udd->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("Cnf:", 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: +#ifdef DEBUG_USB_HOST + NotifyFailGetDevDescr(); + goto Fail; +#endif + +FailSetDevTblEntry: +#ifdef DEBUG_USB_HOST + NotifyFailSetDevTblEntry(); + goto Fail; +#endif + +FailGetConfDescr: +#ifdef DEBUG_USB_HOST + NotifyFailGetConfDescr(); + goto Fail; +#endif + +FailSetConfDescr: +#ifdef DEBUG_USB_HOST + NotifyFailSetConfDescr(); + goto Fail; +#endif + + +FailSetIdle: +#ifdef DEBUG_USB_HOST + USBTRACE("SetIdle:"); +#endif + +#ifdef DEBUG_USB_HOST +Fail: + NotifyFail(rcode); +#endif + 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); + + if(pollInterval < pep->bInterval) // Set the polling interval as the largest polling interval obtained from endpoints + pollInterval = pep->bInterval; + + 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((long)(millis() - qNextPollTime) >= 0L) { + qNextPollTime = millis() + pollInterval; + + 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) + USBTRACE3("(hiduniversal.h) Poll:", rcode, 0x81); + return rcode; + } + + if(read > constBuffLen) + read = constBuffLen; + + bool identical = BuffersIdentical(read, buf, prevBuf); + + SaveBuffer(read, buf, prevBuf); + + if(identical) + return 0; +#if 0 + Notify(PSTR("\r\nBuf: "), 0x80); + + for(uint8_t i = 0; i < read; i++) { + D_PrintHex (buf[i], 0x80); + Notify(PSTR(" "), 0x80); + } + + Notify(PSTR("\r\n"), 0x80); +#endif + ParseHIDData(this, bHasReportId, (uint8_t)read, buf); + + 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 72be453b..eda52523 100644 --- a/hiduniversal.h +++ b/hiduniversal.h @@ -1,108 +1,105 @@ -/* 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(__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); - - struct HIDInterface { - struct { - uint8_t bmInterface : 3; - uint8_t bmAltSet : 3; - uint8_t bmProtocol : 2; - }; - uint8_t epIndex[maxEpPerInterface]; - }; - - 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 - uint8_t pollInterval; - 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: - EpInfo epInfo[totalEndpoints]; - HIDInterface hidInterfaces[maxHidInterfaces]; - - bool bHasReportId; - - uint16_t PID, VID; // PID and VID of connected device - - // HID implementation - HIDReportParser* GetReportParser(uint8_t id); - - virtual uint8_t OnInitSuccessful() { - return 0; - }; - - virtual void ParseHIDData(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf) { - return; - }; - -public: - HIDUniversal(USB *p); - - // HID implementation - bool SetReportParser(uint8_t id, HIDReportParser *prs); - - // USBDeviceConfig implementation - uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed); - uint8_t Release(); - uint8_t Poll(); - - virtual uint8_t GetAddress() { - return bAddress; - }; - - virtual bool isReady() { - return bPollEnable; - }; - - // UsbConfigXtracter implementation - void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep); - - // Send report - do not mix with SetReport()! - uint8_t SndRpt(uint16_t nbytes, uint8_t *dataptr); -}; - -#endif // __HIDUNIVERSAL_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(__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); + + struct HIDInterface { + struct { + uint8_t bmInterface : 3; + uint8_t bmAltSet : 3; + uint8_t bmProtocol : 2; + }; + uint8_t epIndex[maxEpPerInterface]; + }; + + 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 + uint8_t pollInterval; + 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: + EpInfo epInfo[totalEndpoints]; + HIDInterface hidInterfaces[maxHidInterfaces]; + + bool bHasReportId; + + uint16_t PID, VID; // PID and VID of connected device + + // HID implementation + HIDReportParser* GetReportParser(uint8_t id); + + virtual uint8_t OnInitSuccessful() { + return 0; + }; + + virtual void ParseHIDData(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf) { + return; + }; + +public: + HIDUniversal(USB *p); + + // HID implementation + bool SetReportParser(uint8_t id, HIDReportParser *prs); + + // USBDeviceConfig implementation + uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed); + uint8_t Release(); + uint8_t Poll(); + + virtual uint8_t GetAddress() { + return bAddress; + }; + + virtual bool isReady() { + return bPollEnable; + }; + + // UsbConfigXtracter implementation + void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep); +}; + +#endif // __HIDUNIVERSAL_H__ diff --git a/hidusagestr.h b/hidusagestr.h index f99f0e39..5ef48f92 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 "Usb.h" - -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__ +/* 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 "Usb.h" + +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__ diff --git a/hidusagetitlearrays.cpp b/hidusagetitlearrays.cpp index 8bdd41b5..ee233002 100644 --- a/hidusagetitlearrays.cpp +++ b/hidusagetitlearrays.cpp @@ -1,1046 +1,1048 @@ -/* 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 "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__ +/* 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 "hidusagestr.h" + +// This is here why? + +//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__ diff --git a/keywords.txt b/keywords.txt index c7bd007c..178d52d8 100644 --- a/keywords.txt +++ b/keywords.txt @@ -358,4 +358,4 @@ RED LITERAL1 YELLOW LITERAL1 GREEN LITERAL1 ORANGE LITERAL1 -BLUE LITERAL1 \ No newline at end of file +BLUE LITERAL1 diff --git a/macros.h b/macros.h index 51476830..e14a711f 100644 --- a/macros.h +++ b/macros.h @@ -18,7 +18,7 @@ e-mail : support@circuitsathome.com #if !defined(_usb_h_) || defined(MACROS_H) #error "Never include macros.h directly; include Usb.h instead" #else -#define MACROS_H +#define MACROS_H //////////////////////////////////////////////////////////////////////////////// // HANDY MACROS @@ -78,5 +78,5 @@ e-mail : support@circuitsathome.com #define USBTRACE3(s,r,l) (Notify(PSTR(s), l), D_PrintHex((r), l), Notify(PSTR("\r\n"), l)) -#endif /* MACROS_H */ +#endif /* MACROS_H */ diff --git a/masstorage.cpp b/masstorage.cpp index 351a2cb3..9299f71a 100644 --- a/masstorage.cpp +++ b/masstorage.cpp @@ -1,1266 +1,1266 @@ -/* 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 "masstorage.h" - -const uint8_t BulkOnly::epDataInIndex = 1; -const uint8_t BulkOnly::epDataOutIndex = 2; -const uint8_t BulkOnly::epInterruptInIndex = 3; - -//////////////////////////////////////////////////////////////////////////////// - -// Interface code - -//////////////////////////////////////////////////////////////////////////////// - -/** - * Get the capacity of the media - * - * @param lun Logical Unit Number - * @return media capacity - */ -uint32_t BulkOnly::GetCapacity(uint8_t lun) { - if(LUNOk[lun]) - return CurrentCapacity[lun]; - return 0LU; -} - -/** - * Get the sector (block) size used on the media - * - * @param lun Logical Unit Number - * @return media sector size - */ -uint16_t BulkOnly::GetSectorSize(uint8_t lun) { - if(LUNOk[lun]) - return CurrentSectorSize[lun]; - return 0U; -} - -/** - * Test if LUN is ready for use - * - * @param lun Logical Unit Number - * @return true if LUN is ready for use - */ -bool BulkOnly::LUNIsGood(uint8_t lun) { - return LUNOk[lun]; -} - -/** - * Test if LUN is write protected - * - * @param lun Logical Unit Number - * @return cached status of write protect switch - */ -bool BulkOnly::WriteProtected(uint8_t lun) { - return WriteOk[lun]; -} - -/** - * Wrap and execute a SCSI CDB with length of 6 - * - * @param cdb CDB to execute - * @param buf_size Size of expected transaction - * @param buf Buffer - * @param dir MASS_CMD_DIR_IN | MASS_CMD_DIR_OUT - * @return - */ -uint8_t BulkOnly::SCSITransaction6(CDB6_t *cdb, uint16_t buf_size, void *buf, uint8_t dir) { - // promote buf_size to 32bits. - CommandBlockWrapper cbw = CommandBlockWrapper(++dCBWTag, (uint32_t)buf_size, cdb, dir); - //SetCurLUN(cdb->LUN); - return (HandleSCSIError(Transaction(&cbw, buf_size, buf))); -} - -/** - * Wrap and execute a SCSI CDB with length of 10 - * - * @param cdb CDB to execute - * @param buf_size Size of expected transaction - * @param buf Buffer - * @param dir MASS_CMD_DIR_IN | MASS_CMD_DIR_OUT - * @return - */ -uint8_t BulkOnly::SCSITransaction10(CDB10_t *cdb, uint16_t buf_size, void *buf, uint8_t dir) { - // promote buf_size to 32bits. - CommandBlockWrapper cbw = CommandBlockWrapper(++dCBWTag, (uint32_t)buf_size, cdb, dir); - //SetCurLUN(cdb->LUN); - return (HandleSCSIError(Transaction(&cbw, buf_size, buf))); -} - -/** - * Lock or Unlock the tray or door on device. - * Caution: Some devices with buggy firmware will lock up. - * - * @param lun Logical Unit Number - * @param lock 1 to lock, 0 to unlock - * @return - */ -uint8_t BulkOnly::LockMedia(uint8_t lun, uint8_t lock) { - Notify(PSTR("\r\nLockMedia\r\n"), 0x80); - Notify(PSTR("---------\r\n"), 0x80); - - CDB6_t cdb = CDB6_t(SCSI_CMD_PREVENT_REMOVAL, lun, (uint8_t)0, lock); - return SCSITransaction6(&cdb, (uint16_t)0, NULL, (uint8_t)MASS_CMD_DIR_IN); -} - -/** - * Media control, for spindle motor and media tray or door. - * This includes CDROM, TAPE and anything with a media loader. - * - * @param lun Logical Unit Number - * @param ctl 0x00 Stop Motor, 0x01 Start Motor, 0x02 Eject Media, 0x03 Load Media - * @return 0 on success - */ -uint8_t BulkOnly::MediaCTL(uint8_t lun, uint8_t ctl) { - Notify(PSTR("\r\nMediaCTL\r\n"), 0x80); - Notify(PSTR("-----------------\r\n"), 0x80); - - uint8_t rcode = MASS_ERR_UNIT_NOT_READY; - if(bAddress) { - CDB6_t cdb = CDB6_t(SCSI_CMD_START_STOP_UNIT, lun, ctl & 0x03, 0); - rcode = SCSITransaction6(&cdb, (uint16_t)0, NULL, (uint8_t)MASS_CMD_DIR_OUT); - } else { - SetCurLUN(lun); - } - return rcode; -} - -/** - * Read data from media - * - * @param lun Logical Unit Number - * @param addr LBA address on media to read - * @param bsize size of a block (we should probably use the cached size) - * @param blocks how many blocks to read - * @param buf memory that is able to hold the requested data - * @return 0 on success - */ -uint8_t BulkOnly::Read(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, uint8_t *buf) { - if(!LUNOk[lun]) return MASS_ERR_NO_MEDIA; - Notify(PSTR("\r\nRead LUN:\t"), 0x80); - D_PrintHex (lun, 0x90); - Notify(PSTR("\r\nLBA:\t\t"), 0x90); - D_PrintHex (addr, 0x90); - Notify(PSTR("\r\nblocks:\t\t"), 0x90); - D_PrintHex (blocks, 0x90); - Notify(PSTR("\r\nblock size:\t"), 0x90); - D_PrintHex (bsize, 0x90); - Notify(PSTR("\r\n---------\r\n"), 0x80); - CDB10_t cdb = CDB10_t(SCSI_CMD_READ_10, lun, blocks, addr); - -again: - uint8_t er = SCSITransaction10(&cdb, ((uint16_t)bsize * blocks), buf, (uint8_t)MASS_CMD_DIR_IN); - - if(er == MASS_ERR_STALL) { - MediaCTL(lun, 1); - delay(150); - if(!TestUnitReady(lun)) goto again; - } - return er; -} - -/** - * Write data to media - * - * @param lun Logical Unit Number - * @param addr LBA address on media to write - * @param bsize size of a block (we should probably use the cached size) - * @param blocks how many blocks to write - * @param buf memory that contains the data to write - * @return 0 on success - */ -uint8_t BulkOnly::Write(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, const uint8_t * buf) { - if(!LUNOk[lun]) return MASS_ERR_NO_MEDIA; - if(!WriteOk[lun]) return MASS_ERR_WRITE_PROTECTED; - Notify(PSTR("\r\nWrite LUN:\t"), 0x80); - D_PrintHex (lun, 0x90); - Notify(PSTR("\r\nLBA:\t\t"), 0x90); - D_PrintHex (addr, 0x90); - Notify(PSTR("\r\nblocks:\t\t"), 0x90); - D_PrintHex (blocks, 0x90); - Notify(PSTR("\r\nblock size:\t"), 0x90); - D_PrintHex (bsize, 0x90); - Notify(PSTR("\r\n---------\r\n"), 0x80); - CDB10_t cdb = CDB10_t(SCSI_CMD_WRITE_10, lun, blocks, addr); - -again: - uint8_t er = SCSITransaction10(&cdb, ((uint16_t)bsize * blocks), (void*)buf, (uint8_t)MASS_CMD_DIR_OUT); - - if(er == MASS_ERR_WRITE_STALL) { - MediaCTL(lun, 1); - delay(150); - if(!TestUnitReady(lun)) goto again; - } - return er; -} - -// End of user functions, the remaining code below is driver internals. -// Only developer serviceable parts below! - -//////////////////////////////////////////////////////////////////////////////// - -// Main driver code - -//////////////////////////////////////////////////////////////////////////////// - -BulkOnly::BulkOnly(USB *p) : -pUsb(p), -bAddress(0), -bIface(0), -bNumEP(1), -qNextPollTime(0), -bPollEnable(false), -//dCBWTag(0), -bLastUsbError(0) { - ClearAllEP(); - dCBWTag = 0; - if(pUsb) - pUsb->RegisterDeviceClass(this); -} - -/** - * USB_ERROR_CONFIG_REQUIRES_ADDITIONAL_RESET == success - * We need to standardize either the rcode, or change the API to return values - * so a signal that additional actions are required can be produced. - * Some of these codes do exist already. - * - * TECHNICAL: We could do most of this code elsewhere, with the exception of checking the class instance. - * Doing so would save some program memory when using multiple drivers. - * - * @param parent USB address of parent - * @param port address of port on parent - * @param lowspeed true if device is low speed - * @return - */ -uint8_t BulkOnly::ConfigureDevice(uint8_t parent, uint8_t port, bool lowspeed) { - - const uint8_t constBufSize = sizeof (USB_DEVICE_DESCRIPTOR); - - uint8_t buf[constBufSize]; - USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast(buf); - uint8_t rcode; - UsbDevice *p = NULL; - EpInfo *oldep_ptr = NULL; - USBTRACE("MS ConfigureDevice\r\n"); - ClearAllEP(); - AddressPool &addrPool = pUsb->GetAddressPool(); - - - 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 = udd->bMaxPacketSize0; - // Steal and abuse from epInfo structure to save on memory. - epInfo[1].epAddr = udd->bNumConfigurations; - // - return USB_ERROR_CONFIG_REQUIRES_ADDITIONAL_RESET; - -FailGetDevDescr: -#ifdef DEBUG_USB_HOST - NotifyFailGetDevDescr(rcode); -#endif - rcode = USB_ERROR_FailGetDevDescr; - - Release(); - return rcode; -}; - -/** - * - * @param parent (not used) - * @param port (not used) - * @param lowspeed true if device is low speed - * @return 0 for success - */ -uint8_t BulkOnly::Init(uint8_t parent, uint8_t port, bool lowspeed) { - uint8_t rcode; - uint8_t num_of_conf = epInfo[1].epAddr; // number of configurations - epInfo[1].epAddr = 0; - USBTRACE("MS Init\r\n"); - - AddressPool &addrPool = pUsb->GetAddressPool(); - UsbDevice *p = addrPool.GetUsbDevicePtr(bAddress); - - if(!p) - return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; - - // Assign new address to the device - delay(2000); - 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; - - // 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; - } - - if(bNumEP < 3) - return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; - - // Assign epInfo to epinfo pointer - pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo); - - USBTRACE2("Conf:", bConfNum); - - // Set Configuration Value - rcode = pUsb->setConf(bAddress, 0, bConfNum); - - if(rcode) - goto FailSetConfDescr; - - //Linux does a 1sec delay after this. - delay(1000); - - rcode = GetMaxLUN(&bMaxLUN); - if(rcode) - goto FailGetMaxLUN; - - if(bMaxLUN >= MASS_MAX_SUPPORTED_LUN) bMaxLUN = MASS_MAX_SUPPORTED_LUN - 1; - ErrorMessage (PSTR("MaxLUN"), bMaxLUN); - - delay(1000); // Delay a bit for slow firmware. - - for(uint8_t lun = 0; lun <= bMaxLUN; lun++) { - InquiryResponse response; - rcode = Inquiry(lun, sizeof (InquiryResponse), (uint8_t*) & response); - if(rcode) { - ErrorMessage (PSTR("Inquiry"), rcode); - } else { -#if 0 - printf("LUN %i `", lun); - uint8_t *buf = response.VendorID; - for(int i = 0; i < 28; i++) printf("%c", buf[i]); - printf("'\r\nQualifier %1.1X ", response.PeripheralQualifier); - printf("Device type %2.2X ", response.DeviceType); - printf("RMB %1.1X ", response.Removable); - printf("SSCS %1.1X ", response.SCCS); - uint8_t sv = response.Version; - printf("SCSI version %2.2X\r\nDevice conforms to ", sv); - switch(sv) { - case 0: - printf("No specific"); - break; - case 1: - printf("ANSI X3.131-1986 (ANSI 1)"); - break; - case 2: - printf("ANSI X3.131-1994 (ANSI 2)"); - break; - case 3: - printf("ANSI INCITS 301-1997 (SPC)"); - break; - case 4: - printf("ANSI INCITS 351-2001 (SPC-2)"); - break; - case 5: - printf("ANSI INCITS 408-2005 (SPC-4)"); - break; - case 6: - printf("T10/1731-D (SPC-4)"); - break; - default: - printf("unknown"); - } - printf(" standards.\r\n"); -#endif - uint8_t tries = 0xf0; - while((rcode = TestUnitReady(lun))) { - if(rcode == 0x08) break; // break on no media, this is OK to do. - // try to lock media and spin up - if(tries < 14) { - LockMedia(lun, 1); - MediaCTL(lun, 1); // I actually have a USB stick that needs this! - } else delay(2 * (tries + 1)); - tries++; - if(!tries) break; - } - if(!rcode) { - delay(1000); - LUNOk[lun] = CheckLUN(lun); - if(!LUNOk[lun]) LUNOk[lun] = CheckLUN(lun); - } - } - } - - - CheckMedia(); - - rcode = OnInit(); - - if(rcode) - goto FailOnInit; - -#ifdef DEBUG_USB_HOST - USBTRACE("MS configured\r\n\r\n"); -#endif - - bPollEnable = true; - - //USBTRACE("Poll enabled\r\n"); - return 0; - -FailSetConfDescr: -#ifdef DEBUG_USB_HOST - NotifyFailSetConfDescr(); - goto Fail; -#endif - -FailOnInit: -#ifdef DEBUG_USB_HOST - USBTRACE("OnInit:"); - goto Fail; -#endif - -FailGetMaxLUN: -#ifdef DEBUG_USB_HOST - USBTRACE("GetMaxLUN:"); - goto Fail; -#endif - - //#ifdef DEBUG_USB_HOST - //FailInvalidSectorSize: - // USBTRACE("Sector Size is NOT VALID: "); - // goto Fail; - //#endif - -FailSetDevTblEntry: -#ifdef DEBUG_USB_HOST - NotifyFailSetDevTblEntry(); - goto Fail; -#endif - -FailGetConfDescr: -#ifdef DEBUG_USB_HOST - NotifyFailGetConfDescr(); -#endif - -#ifdef DEBUG_USB_HOST -Fail: - NotifyFail(rcode); -#endif - Release(); - return rcode; -} - -/** - * For driver use only. - * - * @param conf - * @param iface - * @param alt - * @param proto - * @param pep - */ -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 1 - 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; - epInfo[index].epAttribs = 0; - - bNumEP++; - - PrintEndpointDescriptor(pep); - - } -#else - 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); -#endif -} - -/** - * For driver use only. - * - * @return - */ -uint8_t BulkOnly::Release() { - ClearAllEP(); - pUsb->GetAddressPool().FreeAddress(bAddress); - return 0; -} - -/** - * For driver use only. - * - * @param lun Logical Unit Number - * @return true if LUN is ready for use. - */ -bool BulkOnly::CheckLUN(uint8_t lun) { - uint8_t rcode; - Capacity capacity; - for(uint8_t i = 0; i < 8; i++) capacity.data[i] = 0; - - rcode = ReadCapacity10(lun, (uint8_t*)capacity.data); - if(rcode) { - //printf(">>>>>>>>>>>>>>>>ReadCapacity returned %i\r\n", rcode); - return false; - } - ErrorMessage (PSTR(">>>>>>>>>>>>>>>>CAPACITY OK ON LUN"), lun); - for(uint8_t i = 0; i < 8 /*sizeof (Capacity)*/; i++) - D_PrintHex (capacity.data[i], 0x80); - Notify(PSTR("\r\n\r\n"), 0x80); - // Only 512/1024/2048/4096 are valid values! - uint32_t c = BMAKE32(capacity.data[4], capacity.data[5], capacity.data[6], capacity.data[7]); - if(c != 0x0200LU && c != 0x0400LU && c != 0x0800LU && c != 0x1000LU) { - return false; - } - // Store capacity information. - CurrentSectorSize[lun] = (uint16_t)(c); // & 0xFFFF); - - CurrentCapacity[lun] = BMAKE32(capacity.data[0], capacity.data[1], capacity.data[2], capacity.data[3]) + 1; - if(CurrentCapacity[lun] == /*0xffffffffLU */ 0x01LU || CurrentCapacity[lun] == 0x00LU) { - // Buggy firmware will report 0xffffffff or 0 for no media - if(CurrentCapacity[lun]) - ErrorMessage (PSTR(">>>>>>>>>>>>>>>>BUGGY FIRMWARE. CAPACITY FAIL ON LUN"), lun); - return false; - } - delay(20); - Page3F(lun); - if(!TestUnitReady(lun)) return true; - return false; -} - -/** - * For driver use only. - * - * Scan for media change on all LUNs - */ -void BulkOnly::CheckMedia() { - for(uint8_t lun = 0; lun <= bMaxLUN; lun++) { - if(TestUnitReady(lun)) { - LUNOk[lun] = false; - continue; - } - if(!LUNOk[lun]) - LUNOk[lun] = CheckLUN(lun); - } -#if 0 - printf("}}}}}}}}}}}}}}}}STATUS "); - for(uint8_t lun = 0; lun <= bMaxLUN; lun++) { - if(LUNOk[lun]) - printf("#"); - else printf("."); - } - printf("\r\n"); -#endif - qNextPollTime = millis() + 2000; -} - -/** - * For driver use only. - * - * @return - */ -uint8_t BulkOnly::Poll() { - //uint8_t rcode = 0; - - if(!bPollEnable) - return 0; - - if((long)(millis() - qNextPollTime) >= 0L) { - CheckMedia(); - } - //rcode = 0; - - return 0; -} - -//////////////////////////////////////////////////////////////////////////////// - - -// SCSI code - - -//////////////////////////////////////////////////////////////////////////////// - -/** - * For driver use only. - * - * @param plun - * @return - */ -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; -} - -/** - * For driver use only. Used during Driver Init - * - * @param lun Logical Unit Number - * @param bsize - * @param buf - * @return - */ -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); - - CDB6_t cdb = CDB6_t(SCSI_CMD_INQUIRY, lun, 0LU, (uint8_t)bsize, 0); - uint8_t rc = SCSITransaction6(&cdb, bsize, buf, (uint8_t)MASS_CMD_DIR_IN); - - return rc; -} - -/** - * For driver use only. - * - * @param lun Logical Unit Number - * @return - */ -uint8_t BulkOnly::TestUnitReady(uint8_t lun) { - //SetCurLUN(lun); - if(!bAddress) - return MASS_ERR_UNIT_NOT_READY; - - Notify(PSTR("\r\nTestUnitReady\r\n"), 0x80); - Notify(PSTR("-----------------\r\n"), 0x80); - - CDB6_t cdb = CDB6_t(SCSI_CMD_TEST_UNIT_READY, lun, (uint8_t)0, 0); - return SCSITransaction6(&cdb, 0, NULL, (uint8_t)MASS_CMD_DIR_IN); - -} - -/** - * For driver use only. - * - * @param lun Logical Unit Number - * @param pc - * @param page - * @param subpage - * @param len - * @param pbuf - * @return - */ -uint8_t BulkOnly::ModeSense6(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); - - CDB6_t cdb = CDB6_t(SCSI_CMD_TEST_UNIT_READY, lun, (uint32_t)((((pc << 6) | page) << 8) | subpage), len, 0); - return SCSITransaction6(&cdb, len, pbuf, (uint8_t)MASS_CMD_DIR_IN); -} - -/** - * For driver use only. - * - * @param lun Logical Unit Number - * @param bsize - * @param buf - * @return - */ -uint8_t BulkOnly::ReadCapacity10(uint8_t lun, uint8_t *buf) { - Notify(PSTR("\r\nReadCapacity\r\n"), 0x80); - Notify(PSTR("---------------\r\n"), 0x80); - - CDB10_t cdb = CDB10_t(SCSI_CMD_READ_CAPACITY_10, lun); - return SCSITransaction10(&cdb, 8, buf, (uint8_t)MASS_CMD_DIR_IN); -} - -/** - * For driver use only. - * - * Page 3F contains write protect status. - * - * @param lun Logical Unit Number to test. - * @return Write protect switch status. - */ -uint8_t BulkOnly::Page3F(uint8_t lun) { - uint8_t buf[192]; - for(int i = 0; i < 192; i++) { - buf[i] = 0x00; - } - WriteOk[lun] = true; - uint8_t rc = ModeSense6(lun, 0, 0x3f, 0, 192, buf); - if(!rc) { - WriteOk[lun] = ((buf[2] & 0x80) == 0); - Notify(PSTR("Mode Sense: "), 0x80); - for(int i = 0; i < 4; i++) { - D_PrintHex (buf[i], 0x80); - Notify(PSTR(" "), 0x80); - } - Notify(PSTR("\r\n"), 0x80); - } - return rc; -} - -/** - * For driver use only. - * - * @param lun Logical Unit Number - * @param size - * @param buf - * @return - */ -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); - - CDB6_t cdb = CDB6_t(SCSI_CMD_REQUEST_SENSE, lun, 0LU, (uint8_t)size, 0); - CommandBlockWrapper cbw = CommandBlockWrapper(++dCBWTag, (uint32_t)size, &cdb, (uint8_t)MASS_CMD_DIR_IN); - //SetCurLUN(lun); - return Transaction(&cbw, size, buf); -} - - -//////////////////////////////////////////////////////////////////////////////// - - -// USB code - - -//////////////////////////////////////////////////////////////////////////////// - -/** - * For driver use only. - * - * @param index - * @return - */ -uint8_t BulkOnly::ClearEpHalt(uint8_t index) { - if(index == 0) - return 0; - - uint8_t ret = 0; - - while((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)) == 0x01)) - delay(6); - - if(ret) { - ErrorMessage (PSTR("ClearEpHalt"), ret); - ErrorMessage (PSTR("EP"), ((index == epDataInIndex) ? (0x80 | epInfo[index].epAddr) : epInfo[index].epAddr)); - return ret; - } - epInfo[index].bmSndToggle = 0; - epInfo[index].bmRcvToggle = 0; - // epAttribs = 0; - return 0; -} - -/** - * For driver use only. - * - */ -void BulkOnly::Reset() { - while(pUsb->ctrlReq(bAddress, 0, bmREQ_MASSOUT, MASS_REQ_BOMSR, 0, 0, bIface, 0, 0, NULL, NULL) == 0x01) delay(6); -} - -/** - * For driver use only. - * - * @return 0 if successful - */ -uint8_t BulkOnly::ResetRecovery() { - Notify(PSTR("\r\nResetRecovery\r\n"), 0x80); - Notify(PSTR("-----------------\r\n"), 0x80); - - delay(6); - Reset(); - delay(6); - ClearEpHalt(epDataInIndex); - delay(6); - bLastUsbError = ClearEpHalt(epDataOutIndex); - delay(6); - return bLastUsbError; -} - -/** - * For driver use only. - * - * Clear all EP data and clear all LUN status - */ -void BulkOnly::ClearAllEP() { - for(uint8_t i = 0; i < MASS_MAX_ENDPOINTS; i++) { - epInfo[i].epAddr = 0; - epInfo[i].maxPktSize = (i) ? 0 : 8; - epInfo[i].epAttribs = 0; - - epInfo[i].bmNakPower = USB_NAK_DEFAULT; - } - - for(uint8_t i = 0; i < MASS_MAX_SUPPORTED_LUN; i++) { - LUNOk[i] = false; - WriteOk[i] = false; - CurrentCapacity[i] = 0lu; - CurrentSectorSize[i] = 0; - } - - bIface = 0; - bNumEP = 1; - bAddress = 0; - qNextPollTime = 0; - bPollEnable = false; - bLastUsbError = 0; - bMaxLUN = 0; - bTheLUN = 0; -} - -/** - * For driver use only. - * - * @param pcsw - * @param pcbw - * @return - */ -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; -} - -/** - * For driver use only. - * - * @param error - * @param index - * @return - */ -uint8_t BulkOnly::HandleUsbError(uint8_t error, uint8_t index) { - uint8_t count = 3; - - bLastUsbError = error; - //if (error) - //ClearEpHalt(index); - while(error && count) { - if(error != hrSUCCESS) { - ErrorMessage (PSTR("USB Error"), error); - ErrorMessage (PSTR("Index"), index); - } - switch(error) { - // case hrWRONGPID: - case hrSUCCESS: - return MASS_ERR_SUCCESS; - case hrBUSY: - // SIE is busy, just hang out and try again. - return MASS_ERR_UNIT_BUSY; - case hrTIMEOUT: - case hrJERR: return MASS_ERR_DEVICE_DISCONNECTED; - case hrSTALL: - if(index == 0) - return MASS_ERR_STALL; - ClearEpHalt(index); - if(index != epDataInIndex) - return MASS_ERR_WRITE_STALL; - return MASS_ERR_STALL; - - case hrNAK: - if(index == 0) - return MASS_ERR_UNIT_BUSY; - return MASS_ERR_UNIT_BUSY; - - case hrTOGERR: - // Handle a very super rare corner case, where toggles become de-synched. - // I have only ran into one device that has this firmware bug, and this is - // the only clean way to get back into sync with the buggy device firmware. - // --AJK - 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); -} - -#if MS_WANT_PARSER - -uint8_t BulkOnly::Transaction(CommandBlockWrapper *pcbw, uint16_t buf_size, void *buf) { - return Transaction(CommandBlockWrapper *pcbw, uint16_t buf_size, void *buf, 0); -} -#endif - -/** - * For driver use only. - * - * @param pcbw - * @param buf_size - * @param buf - * @param flags - * @return - */ -uint8_t BulkOnly::Transaction(CommandBlockWrapper *pcbw, uint16_t buf_size, void *buf -#if MS_WANT_PARSER - , uint8_t flags -#endif - ) { - -#if MS_WANT_PARSER - uint16_t bytes = (pcbw->dCBWDataTransferLength > buf_size) ? buf_size : pcbw->dCBWDataTransferLength; - printf("Transfersize %i\r\n", bytes); - delay(1000); - - bool callback = (flags & MASS_TRANS_FLG_CALLBACK) == MASS_TRANS_FLG_CALLBACK; -#else - uint16_t bytes = buf_size; -#endif - bool write = (pcbw->bmCBWFlags & MASS_CMD_DIR_IN) != MASS_CMD_DIR_IN; - uint8_t ret = 0; - uint8_t usberr; - CommandStatusWrapper csw; // up here, we allocate ahead to save cpu cycles. - SetCurLUN(pcbw->bmCBWLUN); - ErrorMessage (PSTR("CBW.dCBWTag"), pcbw->dCBWTag); - - while((usberr = pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, sizeof (CommandBlockWrapper), (uint8_t*)pcbw)) == hrBUSY) delay(1); - - ret = HandleUsbError(usberr, epDataOutIndex); - //ret = HandleUsbError(pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, sizeof (CommandBlockWrapper), (uint8_t*)pcbw), epDataOutIndex); - if(ret) { - ErrorMessage (PSTR("============================ CBW"), ret); - } else { - if(bytes) { - if(!write) { -#if MS_WANT_PARSER - if(callback) { - uint8_t rbuf[bytes]; - while((usberr = pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, &bytes, rbuf)) == hrBUSY) delay(1); - if(usberr == hrSUCCESS) ((USBReadParser*)buf)->Parse(bytes, rbuf, 0); - } else { -#endif - while((usberr = pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, &bytes, (uint8_t*)buf)) == hrBUSY) delay(1); -#if MS_WANT_PARSER - - } -#endif - ret = HandleUsbError(usberr, epDataInIndex); - } else { - while((usberr = pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, bytes, (uint8_t*)buf)) == hrBUSY) delay(1); - ret = HandleUsbError(usberr, epDataOutIndex); - } - if(ret) { - ErrorMessage (PSTR("============================ DAT"), ret); - } - } - } - - { - bytes = sizeof (CommandStatusWrapper); - int tries = 2; - while(tries--) { - while((usberr = pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, &bytes, (uint8_t*) & csw)) == hrBUSY) delay(1); - if(!usberr) break; - ClearEpHalt(epDataInIndex); - if(tries) ResetRecovery(); - } - if(!ret) { - Notify(PSTR("CBW:\t\tOK\r\n"), 0x80); - Notify(PSTR("Data Stage:\tOK\r\n"), 0x80); - } else { - // Throw away csw, IT IS NOT OF ANY USE. - ResetRecovery(); - return ret; - } - ret = HandleUsbError(usberr, epDataInIndex); - if(ret) { - ErrorMessage (PSTR("============================ CSW"), ret); - } - if(usberr == hrSUCCESS) { - 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 { - // NOTE! Sometimes this is caused by the reported residue being wrong. - // Get a different device. It isn't compliant, and should have never passed Q&A. - // I own one... 05e3:0701 Genesys Logic, Inc. USB 2.0 IDE Adapter. - // Other devices that exhibit this behavior exist in the wild too. - // Be sure to check quirks in the Linux source code before reporting a bug. --xxxajk - Notify(PSTR("Invalid CSW\r\n"), 0x80); - ResetRecovery(); - //return MASS_ERR_SUCCESS; - return MASS_ERR_INVALID_CSW; - } - } - } - return ret; -} - -/** - * For driver use only. - * - * @param lun Logical Unit Number - * @return - */ -uint8_t BulkOnly::SetCurLUN(uint8_t lun) { - if(lun > bMaxLUN) - return MASS_ERR_INVALID_LUN; - bTheLUN = lun; - return MASS_ERR_SUCCESS; -}; - -/** - * For driver use only. - * - * @param status - * @return - */ -uint8_t BulkOnly::HandleSCSIError(uint8_t status) { - uint8_t ret = 0; - - switch(status) { - case 0: return MASS_ERR_SUCCESS; - - case 2: - ErrorMessage (PSTR("Phase Error"), status); - ErrorMessage (PSTR("LUN"), bTheLUN); - ResetRecovery(); - return MASS_ERR_GENERAL_SCSI_ERROR; - - case 1: - ErrorMessage (PSTR("SCSI Error"), status); - ErrorMessage (PSTR("LUN"), bTheLUN); - RequestSenseResponce rsp; - - ret = RequestSense(bTheLUN, sizeof (RequestSenseResponce), (uint8_t*) & rsp); - - if(ret) { - return MASS_ERR_GENERAL_SCSI_ERROR; - } - ErrorMessage (PSTR("Response Code"), rsp.bResponseCode); - if(rsp.bResponseCode & 0x80) { - Notify(PSTR("Information field: "), 0x80); - for(int i = 0; i < 4; i++) { - D_PrintHex (rsp.CmdSpecificInformation[i], 0x80); - Notify(PSTR(" "), 0x80); - } - Notify(PSTR("\r\n"), 0x80); - } - ErrorMessage (PSTR("Sense Key"), rsp.bmSenseKey); - ErrorMessage (PSTR("Add Sense Code"), rsp.bAdditionalSenseCode); - ErrorMessage (PSTR("Add Sense Qual"), rsp.bAdditionalSenseQualifier); - // warning, this is not testing ASQ, only SK and ASC. - switch(rsp.bmSenseKey) { - case SCSI_S_UNIT_ATTENTION: - switch(rsp.bAdditionalSenseCode) { - case SCSI_ASC_MEDIA_CHANGED: - return MASS_ERR_MEDIA_CHANGED; - default: - return MASS_ERR_UNIT_NOT_READY; - } - 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; - } - - // case 4: return MASS_ERR_UNIT_BUSY; // Busy means retry later. - // case 0x05/0x14: we stalled out - // case 0x15/0x16: we naked out. - default: - ErrorMessage (PSTR("Gen SCSI Err"), status); - ErrorMessage (PSTR("LUN"), bTheLUN); - return status; - } // switch -} - - -//////////////////////////////////////////////////////////////////////////////// - - -// Debugging code - - -//////////////////////////////////////////////////////////////////////////////// - -/** - * - * @param ep_ptr - */ -void BulkOnly::PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR * ep_ptr) { - Notify(PSTR("Endpoint descriptor:"), 0x80); - Notify(PSTR("\r\nLength:\t\t"), 0x80); - D_PrintHex (ep_ptr->bLength, 0x80); - Notify(PSTR("\r\nType:\t\t"), 0x80); - D_PrintHex (ep_ptr->bDescriptorType, 0x80); - Notify(PSTR("\r\nAddress:\t"), 0x80); - D_PrintHex (ep_ptr->bEndpointAddress, 0x80); - Notify(PSTR("\r\nAttributes:\t"), 0x80); - D_PrintHex (ep_ptr->bmAttributes, 0x80); - Notify(PSTR("\r\nMaxPktSize:\t"), 0x80); - D_PrintHex (ep_ptr->wMaxPacketSize, 0x80); - Notify(PSTR("\r\nPoll Intrv:\t"), 0x80); - D_PrintHex (ep_ptr->bInterval, 0x80); - Notify(PSTR("\r\n"), 0x80); -} - - -//////////////////////////////////////////////////////////////////////////////// - - -// misc/to kill/to-do - - -//////////////////////////////////////////////////////////////////////////////// - -/* 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 MS_WANT_PARSER - if(!LUNOk[lun]) return MASS_ERR_NO_MEDIA; - Notify(PSTR("\r\nRead (With parser)\r\n"), 0x80); - Notify(PSTR("---------\r\n"), 0x80); - - CommandBlockWrapper cbw = CommandBlockWrapper(); - - 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; - - 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)); -#else - return MASS_ERR_NOT_IMPLEMENTED; -#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 "masstorage.h" + +const uint8_t BulkOnly::epDataInIndex = 1; +const uint8_t BulkOnly::epDataOutIndex = 2; +const uint8_t BulkOnly::epInterruptInIndex = 3; + +//////////////////////////////////////////////////////////////////////////////// + +// Interface code + +//////////////////////////////////////////////////////////////////////////////// + +/** + * Get the capacity of the media + * + * @param lun Logical Unit Number + * @return media capacity + */ +uint32_t BulkOnly::GetCapacity(uint8_t lun) { + if(LUNOk[lun]) + return CurrentCapacity[lun]; + return 0LU; +} + +/** + * Get the sector (block) size used on the media + * + * @param lun Logical Unit Number + * @return media sector size + */ +uint16_t BulkOnly::GetSectorSize(uint8_t lun) { + if(LUNOk[lun]) + return CurrentSectorSize[lun]; + return 0U; +} + +/** + * Test if LUN is ready for use + * + * @param lun Logical Unit Number + * @return true if LUN is ready for use + */ +bool BulkOnly::LUNIsGood(uint8_t lun) { + return LUNOk[lun]; +} + +/** + * Test if LUN is write protected + * + * @param lun Logical Unit Number + * @return cached status of write protect switch + */ +bool BulkOnly::WriteProtected(uint8_t lun) { + return WriteOk[lun]; +} + +/** + * Wrap and execute a SCSI CDB with length of 6 + * + * @param cdb CDB to execute + * @param buf_size Size of expected transaction + * @param buf Buffer + * @param dir MASS_CMD_DIR_IN | MASS_CMD_DIR_OUT + * @return + */ +uint8_t BulkOnly::SCSITransaction6(CDB6_t *cdb, uint16_t buf_size, void *buf, uint8_t dir) { + // promote buf_size to 32bits. + CommandBlockWrapper cbw = CommandBlockWrapper(++dCBWTag, (uint32_t)buf_size, cdb, dir); + //SetCurLUN(cdb->LUN); + return (HandleSCSIError(Transaction(&cbw, buf_size, buf))); +} + +/** + * Wrap and execute a SCSI CDB with length of 10 + * + * @param cdb CDB to execute + * @param buf_size Size of expected transaction + * @param buf Buffer + * @param dir MASS_CMD_DIR_IN | MASS_CMD_DIR_OUT + * @return + */ +uint8_t BulkOnly::SCSITransaction10(CDB10_t *cdb, uint16_t buf_size, void *buf, uint8_t dir) { + // promote buf_size to 32bits. + CommandBlockWrapper cbw = CommandBlockWrapper(++dCBWTag, (uint32_t)buf_size, cdb, dir); + //SetCurLUN(cdb->LUN); + return (HandleSCSIError(Transaction(&cbw, buf_size, buf))); +} + +/** + * Lock or Unlock the tray or door on device. + * Caution: Some devices with buggy firmware will lock up. + * + * @param lun Logical Unit Number + * @param lock 1 to lock, 0 to unlock + * @return + */ +uint8_t BulkOnly::LockMedia(uint8_t lun, uint8_t lock) { + Notify(PSTR("\r\nLockMedia\r\n"), 0x80); + Notify(PSTR("---------\r\n"), 0x80); + + CDB6_t cdb = CDB6_t(SCSI_CMD_PREVENT_REMOVAL, lun, (uint8_t)0, lock); + return SCSITransaction6(&cdb, (uint16_t)0, NULL, (uint8_t)MASS_CMD_DIR_IN); +} + +/** + * Media control, for spindle motor and media tray or door. + * This includes CDROM, TAPE and anything with a media loader. + * + * @param lun Logical Unit Number + * @param ctl 0x00 Stop Motor, 0x01 Start Motor, 0x02 Eject Media, 0x03 Load Media + * @return 0 on success + */ +uint8_t BulkOnly::MediaCTL(uint8_t lun, uint8_t ctl) { + Notify(PSTR("\r\nMediaCTL\r\n"), 0x80); + Notify(PSTR("-----------------\r\n"), 0x80); + + uint8_t rcode = MASS_ERR_UNIT_NOT_READY; + if(bAddress) { + CDB6_t cdb = CDB6_t(SCSI_CMD_START_STOP_UNIT, lun, ctl & 0x03, 0); + rcode = SCSITransaction6(&cdb, (uint16_t)0, NULL, (uint8_t)MASS_CMD_DIR_OUT); + } else { + SetCurLUN(lun); + } + return rcode; +} + +/** + * Read data from media + * + * @param lun Logical Unit Number + * @param addr LBA address on media to read + * @param bsize size of a block (we should probably use the cached size) + * @param blocks how many blocks to read + * @param buf memory that is able to hold the requested data + * @return 0 on success + */ +uint8_t BulkOnly::Read(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, uint8_t *buf) { + if(!LUNOk[lun]) return MASS_ERR_NO_MEDIA; + Notify(PSTR("\r\nRead LUN:\t"), 0x80); + D_PrintHex (lun, 0x90); + Notify(PSTR("\r\nLBA:\t\t"), 0x90); + D_PrintHex (addr, 0x90); + Notify(PSTR("\r\nblocks:\t\t"), 0x90); + D_PrintHex (blocks, 0x90); + Notify(PSTR("\r\nblock size:\t"), 0x90); + D_PrintHex (bsize, 0x90); + Notify(PSTR("\r\n---------\r\n"), 0x80); + CDB10_t cdb = CDB10_t(SCSI_CMD_READ_10, lun, blocks, addr); + +again: + uint8_t er = SCSITransaction10(&cdb, ((uint16_t)bsize * blocks), buf, (uint8_t)MASS_CMD_DIR_IN); + + if(er == MASS_ERR_STALL) { + MediaCTL(lun, 1); + delay(150); + if(!TestUnitReady(lun)) goto again; + } + return er; +} + +/** + * Write data to media + * + * @param lun Logical Unit Number + * @param addr LBA address on media to write + * @param bsize size of a block (we should probably use the cached size) + * @param blocks how many blocks to write + * @param buf memory that contains the data to write + * @return 0 on success + */ +uint8_t BulkOnly::Write(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, const uint8_t * buf) { + if(!LUNOk[lun]) return MASS_ERR_NO_MEDIA; + if(!WriteOk[lun]) return MASS_ERR_WRITE_PROTECTED; + Notify(PSTR("\r\nWrite LUN:\t"), 0x80); + D_PrintHex (lun, 0x90); + Notify(PSTR("\r\nLBA:\t\t"), 0x90); + D_PrintHex (addr, 0x90); + Notify(PSTR("\r\nblocks:\t\t"), 0x90); + D_PrintHex (blocks, 0x90); + Notify(PSTR("\r\nblock size:\t"), 0x90); + D_PrintHex (bsize, 0x90); + Notify(PSTR("\r\n---------\r\n"), 0x80); + CDB10_t cdb = CDB10_t(SCSI_CMD_WRITE_10, lun, blocks, addr); + +again: + uint8_t er = SCSITransaction10(&cdb, ((uint16_t)bsize * blocks), (void*)buf, (uint8_t)MASS_CMD_DIR_OUT); + + if(er == MASS_ERR_WRITE_STALL) { + MediaCTL(lun, 1); + delay(150); + if(!TestUnitReady(lun)) goto again; + } + return er; +} + +// End of user functions, the remaining code below is driver internals. +// Only developer serviceable parts below! + +//////////////////////////////////////////////////////////////////////////////// + +// Main driver code + +//////////////////////////////////////////////////////////////////////////////// + +BulkOnly::BulkOnly(USB *p) : +pUsb(p), +bAddress(0), +bIface(0), +bNumEP(1), +qNextPollTime(0), +bPollEnable(false), +//dCBWTag(0), +bLastUsbError(0) { + ClearAllEP(); + dCBWTag = 0; + if(pUsb) + pUsb->RegisterDeviceClass(this); +} + +/** + * USB_ERROR_CONFIG_REQUIRES_ADDITIONAL_RESET == success + * We need to standardize either the rcode, or change the API to return values + * so a signal that additional actions are required can be produced. + * Some of these codes do exist already. + * + * TECHNICAL: We could do most of this code elsewhere, with the exception of checking the class instance. + * Doing so would save some program memory when using multiple drivers. + * + * @param parent USB address of parent + * @param port address of port on parent + * @param lowspeed true if device is low speed + * @return + */ +uint8_t BulkOnly::ConfigureDevice(uint8_t parent, uint8_t port, bool lowspeed) { + + const uint8_t constBufSize = sizeof (USB_DEVICE_DESCRIPTOR); + + uint8_t buf[constBufSize]; + USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast(buf); + uint8_t rcode; + UsbDevice *p = NULL; + EpInfo *oldep_ptr = NULL; + USBTRACE("MS ConfigureDevice\r\n"); + ClearAllEP(); + AddressPool &addrPool = pUsb->GetAddressPool(); + + + 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 = udd->bMaxPacketSize0; + // Steal and abuse from epInfo structure to save on memory. + epInfo[1].epAddr = udd->bNumConfigurations; + // + return USB_ERROR_CONFIG_REQUIRES_ADDITIONAL_RESET; + +FailGetDevDescr: +#ifdef DEBUG_USB_HOST + NotifyFailGetDevDescr(rcode); +#endif + rcode = USB_ERROR_FailGetDevDescr; + + Release(); + return rcode; +}; + +/** + * + * @param parent (not used) + * @param port (not used) + * @param lowspeed true if device is low speed + * @return 0 for success + */ +uint8_t BulkOnly::Init(uint8_t parent, uint8_t port, bool lowspeed) { + uint8_t rcode; + uint8_t num_of_conf = epInfo[1].epAddr; // number of configurations + epInfo[1].epAddr = 0; + USBTRACE("MS Init\r\n"); + + AddressPool &addrPool = pUsb->GetAddressPool(); + UsbDevice *p = addrPool.GetUsbDevicePtr(bAddress); + + if(!p) + return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; + + // Assign new address to the device + delay(2000); + 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; + + // 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; + } + + if(bNumEP < 3) + return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; + + // Assign epInfo to epinfo pointer + pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo); + + USBTRACE2("Conf:", bConfNum); + + // Set Configuration Value + rcode = pUsb->setConf(bAddress, 0, bConfNum); + + if(rcode) + goto FailSetConfDescr; + + //Linux does a 1sec delay after this. + delay(1000); + + rcode = GetMaxLUN(&bMaxLUN); + if(rcode) + goto FailGetMaxLUN; + + if(bMaxLUN >= MASS_MAX_SUPPORTED_LUN) bMaxLUN = MASS_MAX_SUPPORTED_LUN - 1; + ErrorMessage (PSTR("MaxLUN"), bMaxLUN); + + delay(1000); // Delay a bit for slow firmware. + + for(uint8_t lun = 0; lun <= bMaxLUN; lun++) { + InquiryResponse response; + rcode = Inquiry(lun, sizeof (InquiryResponse), (uint8_t*) & response); + if(rcode) { + ErrorMessage (PSTR("Inquiry"), rcode); + } else { +#if 0 + printf("LUN %i `", lun); + uint8_t *buf = response.VendorID; + for(int i = 0; i < 28; i++) printf("%c", buf[i]); + printf("'\r\nQualifier %1.1X ", response.PeripheralQualifier); + printf("Device type %2.2X ", response.DeviceType); + printf("RMB %1.1X ", response.Removable); + printf("SSCS %1.1X ", response.SCCS); + uint8_t sv = response.Version; + printf("SCSI version %2.2X\r\nDevice conforms to ", sv); + switch(sv) { + case 0: + printf("No specific"); + break; + case 1: + printf("ANSI X3.131-1986 (ANSI 1)"); + break; + case 2: + printf("ANSI X3.131-1994 (ANSI 2)"); + break; + case 3: + printf("ANSI INCITS 301-1997 (SPC)"); + break; + case 4: + printf("ANSI INCITS 351-2001 (SPC-2)"); + break; + case 5: + printf("ANSI INCITS 408-2005 (SPC-4)"); + break; + case 6: + printf("T10/1731-D (SPC-4)"); + break; + default: + printf("unknown"); + } + printf(" standards.\r\n"); +#endif + uint8_t tries = 0xf0; + while((rcode = TestUnitReady(lun))) { + if(rcode == 0x08) break; // break on no media, this is OK to do. + // try to lock media and spin up + if(tries < 14) { + LockMedia(lun, 1); + MediaCTL(lun, 1); // I actually have a USB stick that needs this! + } else delay(2 * (tries + 1)); + tries++; + if(!tries) break; + } + if(!rcode) { + delay(1000); + LUNOk[lun] = CheckLUN(lun); + if(!LUNOk[lun]) LUNOk[lun] = CheckLUN(lun); + } + } + } + + + CheckMedia(); + + rcode = OnInit(); + + if(rcode) + goto FailOnInit; + +#ifdef DEBUG_USB_HOST + USBTRACE("MS configured\r\n\r\n"); +#endif + + bPollEnable = true; + + //USBTRACE("Poll enabled\r\n"); + return 0; + +FailSetConfDescr: +#ifdef DEBUG_USB_HOST + NotifyFailSetConfDescr(); + goto Fail; +#endif + +FailOnInit: +#ifdef DEBUG_USB_HOST + USBTRACE("OnInit:"); + goto Fail; +#endif + +FailGetMaxLUN: +#ifdef DEBUG_USB_HOST + USBTRACE("GetMaxLUN:"); + goto Fail; +#endif + + //#ifdef DEBUG_USB_HOST + //FailInvalidSectorSize: + // USBTRACE("Sector Size is NOT VALID: "); + // goto Fail; + //#endif + +FailSetDevTblEntry: +#ifdef DEBUG_USB_HOST + NotifyFailSetDevTblEntry(); + goto Fail; +#endif + +FailGetConfDescr: +#ifdef DEBUG_USB_HOST + NotifyFailGetConfDescr(); +#endif + +#ifdef DEBUG_USB_HOST +Fail: + NotifyFail(rcode); +#endif + Release(); + return rcode; +} + +/** + * For driver use only. + * + * @param conf + * @param iface + * @param alt + * @param proto + * @param pep + */ +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 1 + 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; + epInfo[index].epAttribs = 0; + + bNumEP++; + + PrintEndpointDescriptor(pep); + + } +#else + 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); +#endif +} + +/** + * For driver use only. + * + * @return + */ +uint8_t BulkOnly::Release() { + ClearAllEP(); + pUsb->GetAddressPool().FreeAddress(bAddress); + return 0; +} + +/** + * For driver use only. + * + * @param lun Logical Unit Number + * @return true if LUN is ready for use. + */ +bool BulkOnly::CheckLUN(uint8_t lun) { + uint8_t rcode; + Capacity capacity; + for(uint8_t i = 0; i < 8; i++) capacity.data[i] = 0; + + rcode = ReadCapacity10(lun, (uint8_t*)capacity.data); + if(rcode) { + //printf(">>>>>>>>>>>>>>>>ReadCapacity returned %i\r\n", rcode); + return false; + } + ErrorMessage (PSTR(">>>>>>>>>>>>>>>>CAPACITY OK ON LUN"), lun); + for(uint8_t i = 0; i < 8 /*sizeof (Capacity)*/; i++) + D_PrintHex (capacity.data[i], 0x80); + Notify(PSTR("\r\n\r\n"), 0x80); + // Only 512/1024/2048/4096 are valid values! + uint32_t c = BMAKE32(capacity.data[4], capacity.data[5], capacity.data[6], capacity.data[7]); + if(c != 0x0200LU && c != 0x0400LU && c != 0x0800LU && c != 0x1000LU) { + return false; + } + // Store capacity information. + CurrentSectorSize[lun] = (uint16_t)(c); // & 0xFFFF); + + CurrentCapacity[lun] = BMAKE32(capacity.data[0], capacity.data[1], capacity.data[2], capacity.data[3]) + 1; + if(CurrentCapacity[lun] == /*0xffffffffLU */ 0x01LU || CurrentCapacity[lun] == 0x00LU) { + // Buggy firmware will report 0xffffffff or 0 for no media + if(CurrentCapacity[lun]) + ErrorMessage (PSTR(">>>>>>>>>>>>>>>>BUGGY FIRMWARE. CAPACITY FAIL ON LUN"), lun); + return false; + } + delay(20); + Page3F(lun); + if(!TestUnitReady(lun)) return true; + return false; +} + +/** + * For driver use only. + * + * Scan for media change on all LUNs + */ +void BulkOnly::CheckMedia() { + for(uint8_t lun = 0; lun <= bMaxLUN; lun++) { + if(TestUnitReady(lun)) { + LUNOk[lun] = false; + continue; + } + if(!LUNOk[lun]) + LUNOk[lun] = CheckLUN(lun); + } +#if 0 + printf("}}}}}}}}}}}}}}}}STATUS "); + for(uint8_t lun = 0; lun <= bMaxLUN; lun++) { + if(LUNOk[lun]) + printf("#"); + else printf("."); + } + printf("\r\n"); +#endif + qNextPollTime = millis() + 2000; +} + +/** + * For driver use only. + * + * @return + */ +uint8_t BulkOnly::Poll() { + //uint8_t rcode = 0; + + if(!bPollEnable) + return 0; + + if((long)(millis() - qNextPollTime) >= 0L) { + CheckMedia(); + } + //rcode = 0; + + return 0; +} + +//////////////////////////////////////////////////////////////////////////////// + + +// SCSI code + + +//////////////////////////////////////////////////////////////////////////////// + +/** + * For driver use only. + * + * @param plun + * @return + */ +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; +} + +/** + * For driver use only. Used during Driver Init + * + * @param lun Logical Unit Number + * @param bsize + * @param buf + * @return + */ +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); + + CDB6_t cdb = CDB6_t(SCSI_CMD_INQUIRY, lun, 0LU, (uint8_t)bsize, 0); + uint8_t rc = SCSITransaction6(&cdb, bsize, buf, (uint8_t)MASS_CMD_DIR_IN); + + return rc; +} + +/** + * For driver use only. + * + * @param lun Logical Unit Number + * @return + */ +uint8_t BulkOnly::TestUnitReady(uint8_t lun) { + //SetCurLUN(lun); + if(!bAddress) + return MASS_ERR_UNIT_NOT_READY; + + Notify(PSTR("\r\nTestUnitReady\r\n"), 0x80); + Notify(PSTR("-----------------\r\n"), 0x80); + + CDB6_t cdb = CDB6_t(SCSI_CMD_TEST_UNIT_READY, lun, (uint8_t)0, 0); + return SCSITransaction6(&cdb, 0, NULL, (uint8_t)MASS_CMD_DIR_IN); + +} + +/** + * For driver use only. + * + * @param lun Logical Unit Number + * @param pc + * @param page + * @param subpage + * @param len + * @param pbuf + * @return + */ +uint8_t BulkOnly::ModeSense6(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); + + CDB6_t cdb = CDB6_t(SCSI_CMD_TEST_UNIT_READY, lun, (uint32_t)((((pc << 6) | page) << 8) | subpage), len, 0); + return SCSITransaction6(&cdb, len, pbuf, (uint8_t)MASS_CMD_DIR_IN); +} + +/** + * For driver use only. + * + * @param lun Logical Unit Number + * @param bsize + * @param buf + * @return + */ +uint8_t BulkOnly::ReadCapacity10(uint8_t lun, uint8_t *buf) { + Notify(PSTR("\r\nReadCapacity\r\n"), 0x80); + Notify(PSTR("---------------\r\n"), 0x80); + + CDB10_t cdb = CDB10_t(SCSI_CMD_READ_CAPACITY_10, lun); + return SCSITransaction10(&cdb, 8, buf, (uint8_t)MASS_CMD_DIR_IN); +} + +/** + * For driver use only. + * + * Page 3F contains write protect status. + * + * @param lun Logical Unit Number to test. + * @return Write protect switch status. + */ +uint8_t BulkOnly::Page3F(uint8_t lun) { + uint8_t buf[192]; + for(int i = 0; i < 192; i++) { + buf[i] = 0x00; + } + WriteOk[lun] = true; + uint8_t rc = ModeSense6(lun, 0, 0x3f, 0, 192, buf); + if(!rc) { + WriteOk[lun] = ((buf[2] & 0x80) == 0); + Notify(PSTR("Mode Sense: "), 0x80); + for(int i = 0; i < 4; i++) { + D_PrintHex (buf[i], 0x80); + Notify(PSTR(" "), 0x80); + } + Notify(PSTR("\r\n"), 0x80); + } + return rc; +} + +/** + * For driver use only. + * + * @param lun Logical Unit Number + * @param size + * @param buf + * @return + */ +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); + + CDB6_t cdb = CDB6_t(SCSI_CMD_REQUEST_SENSE, lun, 0LU, (uint8_t)size, 0); + CommandBlockWrapper cbw = CommandBlockWrapper(++dCBWTag, (uint32_t)size, &cdb, (uint8_t)MASS_CMD_DIR_IN); + //SetCurLUN(lun); + return Transaction(&cbw, size, buf); +} + + +//////////////////////////////////////////////////////////////////////////////// + + +// USB code + + +//////////////////////////////////////////////////////////////////////////////// + +/** + * For driver use only. + * + * @param index + * @return + */ +uint8_t BulkOnly::ClearEpHalt(uint8_t index) { + if(index == 0) + return 0; + + uint8_t ret = 0; + + while((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)) == 0x01)) + delay(6); + + if(ret) { + ErrorMessage (PSTR("ClearEpHalt"), ret); + ErrorMessage (PSTR("EP"), ((index == epDataInIndex) ? (0x80 | epInfo[index].epAddr) : epInfo[index].epAddr)); + return ret; + } + epInfo[index].bmSndToggle = 0; + epInfo[index].bmRcvToggle = 0; + // epAttribs = 0; + return 0; +} + +/** + * For driver use only. + * + */ +void BulkOnly::Reset() { + while(pUsb->ctrlReq(bAddress, 0, bmREQ_MASSOUT, MASS_REQ_BOMSR, 0, 0, bIface, 0, 0, NULL, NULL) == 0x01) delay(6); +} + +/** + * For driver use only. + * + * @return 0 if successful + */ +uint8_t BulkOnly::ResetRecovery() { + Notify(PSTR("\r\nResetRecovery\r\n"), 0x80); + Notify(PSTR("-----------------\r\n"), 0x80); + + delay(6); + Reset(); + delay(6); + ClearEpHalt(epDataInIndex); + delay(6); + bLastUsbError = ClearEpHalt(epDataOutIndex); + delay(6); + return bLastUsbError; +} + +/** + * For driver use only. + * + * Clear all EP data and clear all LUN status + */ +void BulkOnly::ClearAllEP() { + for(uint8_t i = 0; i < MASS_MAX_ENDPOINTS; i++) { + epInfo[i].epAddr = 0; + epInfo[i].maxPktSize = (i) ? 0 : 8; + epInfo[i].epAttribs = 0; + + epInfo[i].bmNakPower = USB_NAK_DEFAULT; + } + + for(uint8_t i = 0; i < MASS_MAX_SUPPORTED_LUN; i++) { + LUNOk[i] = false; + WriteOk[i] = false; + CurrentCapacity[i] = 0lu; + CurrentSectorSize[i] = 0; + } + + bIface = 0; + bNumEP = 1; + bAddress = 0; + qNextPollTime = 0; + bPollEnable = false; + bLastUsbError = 0; + bMaxLUN = 0; + bTheLUN = 0; +} + +/** + * For driver use only. + * + * @param pcsw + * @param pcbw + * @return + */ +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; +} + +/** + * For driver use only. + * + * @param error + * @param index + * @return + */ +uint8_t BulkOnly::HandleUsbError(uint8_t error, uint8_t index) { + uint8_t count = 3; + + bLastUsbError = error; + //if (error) + //ClearEpHalt(index); + while(error && count) { + if(error != hrSUCCESS) { + ErrorMessage (PSTR("USB Error"), error); + ErrorMessage (PSTR("Index"), index); + } + switch(error) { + // case hrWRONGPID: + case hrSUCCESS: + return MASS_ERR_SUCCESS; + case hrBUSY: + // SIE is busy, just hang out and try again. + return MASS_ERR_UNIT_BUSY; + case hrTIMEOUT: + case hrJERR: return MASS_ERR_DEVICE_DISCONNECTED; + case hrSTALL: + if(index == 0) + return MASS_ERR_STALL; + ClearEpHalt(index); + if(index != epDataInIndex) + return MASS_ERR_WRITE_STALL; + return MASS_ERR_STALL; + + case hrNAK: + if(index == 0) + return MASS_ERR_UNIT_BUSY; + return MASS_ERR_UNIT_BUSY; + + case hrTOGERR: + // Handle a very super rare corner case, where toggles become de-synched. + // I have only ran into one device that has this firmware bug, and this is + // the only clean way to get back into sync with the buggy device firmware. + // --AJK + 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); +} + +#if MS_WANT_PARSER + +uint8_t BulkOnly::Transaction(CommandBlockWrapper *pcbw, uint16_t buf_size, void *buf) { + return Transaction(CommandBlockWrapper *pcbw, uint16_t buf_size, void *buf, 0); +} +#endif + +/** + * For driver use only. + * + * @param pcbw + * @param buf_size + * @param buf + * @param flags + * @return + */ +uint8_t BulkOnly::Transaction(CommandBlockWrapper *pcbw, uint16_t buf_size, void *buf +#if MS_WANT_PARSER + , uint8_t flags +#endif + ) { + +#if MS_WANT_PARSER + uint16_t bytes = (pcbw->dCBWDataTransferLength > buf_size) ? buf_size : pcbw->dCBWDataTransferLength; + printf("Transfersize %i\r\n", bytes); + delay(1000); + + bool callback = (flags & MASS_TRANS_FLG_CALLBACK) == MASS_TRANS_FLG_CALLBACK; +#else + uint16_t bytes = buf_size; +#endif + bool write = (pcbw->bmCBWFlags & MASS_CMD_DIR_IN) != MASS_CMD_DIR_IN; + uint8_t ret = 0; + uint8_t usberr; + CommandStatusWrapper csw; // up here, we allocate ahead to save cpu cycles. + SetCurLUN(pcbw->bmCBWLUN); + ErrorMessage (PSTR("CBW.dCBWTag"), pcbw->dCBWTag); + + while((usberr = pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, sizeof (CommandBlockWrapper), (uint8_t*)pcbw)) == hrBUSY) delay(1); + + ret = HandleUsbError(usberr, epDataOutIndex); + //ret = HandleUsbError(pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, sizeof (CommandBlockWrapper), (uint8_t*)pcbw), epDataOutIndex); + if(ret) { + ErrorMessage (PSTR("============================ CBW"), ret); + } else { + if(bytes) { + if(!write) { +#if MS_WANT_PARSER + if(callback) { + uint8_t rbuf[bytes]; + while((usberr = pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, &bytes, rbuf)) == hrBUSY) delay(1); + if(usberr == hrSUCCESS) ((USBReadParser*)buf)->Parse(bytes, rbuf, 0); + } else { +#endif + while((usberr = pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, &bytes, (uint8_t*)buf)) == hrBUSY) delay(1); +#if MS_WANT_PARSER + + } +#endif + ret = HandleUsbError(usberr, epDataInIndex); + } else { + while((usberr = pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, bytes, (uint8_t*)buf)) == hrBUSY) delay(1); + ret = HandleUsbError(usberr, epDataOutIndex); + } + if(ret) { + ErrorMessage (PSTR("============================ DAT"), ret); + } + } + } + + { + bytes = sizeof (CommandStatusWrapper); + int tries = 2; + while(tries--) { + while((usberr = pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, &bytes, (uint8_t*) & csw)) == hrBUSY) delay(1); + if(!usberr) break; + ClearEpHalt(epDataInIndex); + if(tries) ResetRecovery(); + } + if(!ret) { + Notify(PSTR("CBW:\t\tOK\r\n"), 0x80); + Notify(PSTR("Data Stage:\tOK\r\n"), 0x80); + } else { + // Throw away csw, IT IS NOT OF ANY USE. + ResetRecovery(); + return ret; + } + ret = HandleUsbError(usberr, epDataInIndex); + if(ret) { + ErrorMessage (PSTR("============================ CSW"), ret); + } + if(usberr == hrSUCCESS) { + 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 { + // NOTE! Sometimes this is caused by the reported residue being wrong. + // Get a different device. It isn't compliant, and should have never passed Q&A. + // I own one... 05e3:0701 Genesys Logic, Inc. USB 2.0 IDE Adapter. + // Other devices that exhibit this behavior exist in the wild too. + // Be sure to check quirks in the Linux source code before reporting a bug. --xxxajk + Notify(PSTR("Invalid CSW\r\n"), 0x80); + ResetRecovery(); + //return MASS_ERR_SUCCESS; + return MASS_ERR_INVALID_CSW; + } + } + } + return ret; +} + +/** + * For driver use only. + * + * @param lun Logical Unit Number + * @return + */ +uint8_t BulkOnly::SetCurLUN(uint8_t lun) { + if(lun > bMaxLUN) + return MASS_ERR_INVALID_LUN; + bTheLUN = lun; + return MASS_ERR_SUCCESS; +}; + +/** + * For driver use only. + * + * @param status + * @return + */ +uint8_t BulkOnly::HandleSCSIError(uint8_t status) { + uint8_t ret = 0; + + switch(status) { + case 0: return MASS_ERR_SUCCESS; + + case 2: + ErrorMessage (PSTR("Phase Error"), status); + ErrorMessage (PSTR("LUN"), bTheLUN); + ResetRecovery(); + return MASS_ERR_GENERAL_SCSI_ERROR; + + case 1: + ErrorMessage (PSTR("SCSI Error"), status); + ErrorMessage (PSTR("LUN"), bTheLUN); + RequestSenseResponce rsp; + + ret = RequestSense(bTheLUN, sizeof (RequestSenseResponce), (uint8_t*) & rsp); + + if(ret) { + return MASS_ERR_GENERAL_SCSI_ERROR; + } + ErrorMessage (PSTR("Response Code"), rsp.bResponseCode); + if(rsp.bResponseCode & 0x80) { + Notify(PSTR("Information field: "), 0x80); + for(int i = 0; i < 4; i++) { + D_PrintHex (rsp.CmdSpecificInformation[i], 0x80); + Notify(PSTR(" "), 0x80); + } + Notify(PSTR("\r\n"), 0x80); + } + ErrorMessage (PSTR("Sense Key"), rsp.bmSenseKey); + ErrorMessage (PSTR("Add Sense Code"), rsp.bAdditionalSenseCode); + ErrorMessage (PSTR("Add Sense Qual"), rsp.bAdditionalSenseQualifier); + // warning, this is not testing ASQ, only SK and ASC. + switch(rsp.bmSenseKey) { + case SCSI_S_UNIT_ATTENTION: + switch(rsp.bAdditionalSenseCode) { + case SCSI_ASC_MEDIA_CHANGED: + return MASS_ERR_MEDIA_CHANGED; + default: + return MASS_ERR_UNIT_NOT_READY; + } + 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; + } + + // case 4: return MASS_ERR_UNIT_BUSY; // Busy means retry later. + // case 0x05/0x14: we stalled out + // case 0x15/0x16: we naked out. + default: + ErrorMessage (PSTR("Gen SCSI Err"), status); + ErrorMessage (PSTR("LUN"), bTheLUN); + return status; + } // switch +} + + +//////////////////////////////////////////////////////////////////////////////// + + +// Debugging code + + +//////////////////////////////////////////////////////////////////////////////// + +/** + * + * @param ep_ptr + */ +void BulkOnly::PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR * ep_ptr) { + Notify(PSTR("Endpoint descriptor:"), 0x80); + Notify(PSTR("\r\nLength:\t\t"), 0x80); + D_PrintHex (ep_ptr->bLength, 0x80); + Notify(PSTR("\r\nType:\t\t"), 0x80); + D_PrintHex (ep_ptr->bDescriptorType, 0x80); + Notify(PSTR("\r\nAddress:\t"), 0x80); + D_PrintHex (ep_ptr->bEndpointAddress, 0x80); + Notify(PSTR("\r\nAttributes:\t"), 0x80); + D_PrintHex (ep_ptr->bmAttributes, 0x80); + Notify(PSTR("\r\nMaxPktSize:\t"), 0x80); + D_PrintHex (ep_ptr->wMaxPacketSize, 0x80); + Notify(PSTR("\r\nPoll Intrv:\t"), 0x80); + D_PrintHex (ep_ptr->bInterval, 0x80); + Notify(PSTR("\r\n"), 0x80); +} + + +//////////////////////////////////////////////////////////////////////////////// + + +// misc/to kill/to-do + + +//////////////////////////////////////////////////////////////////////////////// + +/* 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 MS_WANT_PARSER + if(!LUNOk[lun]) return MASS_ERR_NO_MEDIA; + Notify(PSTR("\r\nRead (With parser)\r\n"), 0x80); + Notify(PSTR("---------\r\n"), 0x80); + + CommandBlockWrapper cbw = CommandBlockWrapper(); + + 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; + + 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)); +#else + return MASS_ERR_NOT_IMPLEMENTED; +#endif +} diff --git a/masstorage.h b/masstorage.h index 330826c4..d39fd66f 100644 --- a/masstorage.h +++ b/masstorage.h @@ -1,571 +1,571 @@ -/* 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(__MASSTORAGE_H__) -#define __MASSTORAGE_H__ - -// Cruft removal, makes driver smaller, faster. -#ifndef MS_WANT_PARSER -#define MS_WANT_PARSER 0 -#endif - -#include "Usb.h" - -#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 // (0 << 7) -#define MASS_CMD_DIR_IN 0x80 //(1 << 7) - -/* - * Reference documents from T10 (http://www.t10.org) - * SCSI Primary Commands - 3 (SPC-3) - * SCSI Block Commands - 2 (SBC-2) - * Multi-Media Commands - 5 (MMC-5) - */ - -/* Group 1 commands (CDB's here are should all be 6-bytes) */ -#define SCSI_CMD_TEST_UNIT_READY 0x00 -#define SCSI_CMD_REQUEST_SENSE 0x03 -#define SCSI_CMD_FORMAT_UNIT 0x04 -#define SCSI_CMD_READ_6 0x08 -#define SCSI_CMD_WRITE_6 0x0A -#define SCSI_CMD_INQUIRY 0x12 -#define SCSI_CMD_MODE_SELECT_6 0x15 -#define SCSI_CMD_MODE_SENSE_6 0x1A -#define SCSI_CMD_START_STOP_UNIT 0x1B -#define SCSI_CMD_PREVENT_REMOVAL 0x1E -/* Group 2 Commands (CDB's here are 10-bytes) */ -#define SCSI_CMD_READ_FORMAT_CAPACITIES 0x23 -#define SCSI_CMD_READ_CAPACITY_10 0x25 -#define SCSI_CMD_READ_10 0x28 -#define SCSI_CMD_WRITE_10 0x2A -#define SCSI_CMD_SEEK_10 0x2B -#define SCSI_CMD_ERASE_10 0x2C -#define SCSI_CMD_WRITE_AND_VERIFY_10 0x2E -#define SCSI_CMD_VERIFY_10 0x2F -#define SCSI_CMD_SYNCHRONIZE_CACHE 0x35 -#define SCSI_CMD_WRITE_BUFFER 0x3B -#define SCSI_CMD_READ_BUFFER 0x3C -#define SCSI_CMD_READ_SUBCHANNEL 0x42 -#define SCSI_CMD_READ_TOC 0x43 -#define SCSI_CMD_READ_HEADER 0x44 -#define SCSI_CMD_PLAY_AUDIO_10 0x45 -#define SCSI_CMD_GET_CONFIGURATION 0x46 -#define SCSI_CMD_PLAY_AUDIO_MSF 0x47 -#define SCSI_CMD_PLAY_AUDIO_TI 0x48 -#define SCSI_CMD_PLAY_TRACK_REL_10 0x49 -#define SCSI_CMD_GET_EVENT_STATUS 0x4A -#define SCSI_CMD_PAUSE_RESUME 0x4B -#define SCSI_CMD_READ_DISC_INFORMATION 0x51 -#define SCSI_CMD_READ_TRACK_INFORMATION 0x52 -#define SCSI_CMD_RESERVE_TRACK 0x53 -#define SCSI_CMD_SEND_OPC_INFORMATION 0x54 -#define SCSI_CMD_MODE_SELECT_10 0x55 -#define SCSI_CMD_REPAIR_TRACK 0x58 -#define SCSI_CMD_MODE_SENSE_10 0x5A -#define SCSI_CMD_CLOSE_TRACK_SESSION 0x5B -#define SCSI_CMD_READ_BUFFER_CAPACITY 0x5C -#define SCSI_CMD_SEND_CUE_SHEET 0x5D -/* Group 5 Commands (CDB's here are 12-bytes) */ -#define SCSI_CMD_REPORT_LUNS 0xA0 -#define SCSI_CMD_BLANK 0xA1 -#define SCSI_CMD_SECURITY_PROTOCOL_IN 0xA2 -#define SCSI_CMD_SEND_KEY 0xA3 -#define SCSI_CMD_REPORT_KEY 0xA4 -#define SCSI_CMD_PLAY_AUDIO_12 0xA5 -#define SCSI_CMD_LOAD_UNLOAD 0xA6 -#define SCSI_CMD_SET_READ_AHEAD 0xA7 -#define SCSI_CMD_READ_12 0xA8 -#define SCSI_CMD_PLAY_TRACK_REL_12 0xA9 -#define SCSI_CMD_WRITE_12 0xAA -#define SCSI_CMD_READ_MEDIA_SERIAL_12 0xAB -#define SCSI_CMD_GET_PERFORMANCE 0xAC -#define SCSI_CMD_READ_DVD_STRUCTURE 0xAD -#define SCSI_CMD_SECURITY_PROTOCOL_OUT 0xB5 -#define SCSI_CMD_SET_STREAMING 0xB6 -#define SCSI_CMD_READ_MSF 0xB9 -#define SCSI_CMD_SET_SPEED 0xBB -#define SCSI_CMD_MECHANISM_STATUS 0xBD -#define SCSI_CMD_READ_CD 0xBE -#define SCSI_CMD_SEND_DISC_STRUCTURE 0xBF -/* Vendor-unique Commands, included for completeness */ -#define SCSI_CMD_CD_PLAYBACK_STATUS 0xC4 /* SONY unique */ -#define SCSI_CMD_PLAYBACK_CONTROL 0xC9 /* SONY unique */ -#define SCSI_CMD_READ_CDDA 0xD8 /* Vendor unique */ -#define SCSI_CMD_READ_CDXA 0xDB /* Vendor unique */ -#define SCSI_CMD_READ_ALL_SUBCODES 0xDF /* Vendor unique */ - -/* SCSI error codes */ -#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_LBA_OUT_OF_RANGE 0x21 -#define SCSI_ASC_MEDIA_CHANGED 0x28 -#define SCSI_ASC_MEDIUM_NOT_PRESENT 0x3A - -/* USB error codes */ -#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_MEDIA_CHANGED 0x0A -#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_WRITE_STALL 0x14 -#define MASS_ERR_READ_NAKS 0x15 -#define MASS_ERR_WRITE_NAKS 0x16 -#define MASS_ERR_WRITE_PROTECTED 0x17 -#define MASS_ERR_NOT_IMPLEMENTED 0xFD -#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 - -#define MASS_MAX_ENDPOINTS 3 - -struct Capacity { - uint8_t data[8]; - //uint32_t dwBlockAddress; - //uint32_t dwBlockLength; -} __attribute__((packed)); - -struct BASICCDB { - uint8_t Opcode; - - unsigned unused : 5; - unsigned LUN : 3; - - uint8_t info[12]; -} __attribute__((packed)); - -typedef BASICCDB BASICCDB_t; - -struct CDB6 { - uint8_t Opcode; - - unsigned LBAMSB : 5; - unsigned LUN : 3; - - uint8_t LBAHB; - uint8_t LBALB; - uint8_t AllocationLength; - uint8_t Control; - -public: - - CDB6(uint8_t _Opcode, uint8_t _LUN, uint32_t LBA, uint8_t _AllocationLength, uint8_t _Control) : - Opcode(_Opcode), LBAMSB(BGRAB2(LBA) & 0x1f), LUN(_LUN), LBAHB(BGRAB1(LBA)), LBALB(BGRAB0(LBA)), - AllocationLength(_AllocationLength), Control(_Control) { - } - - CDB6(uint8_t _Opcode, uint8_t _LUN, uint8_t _AllocationLength, uint8_t _Control) : - Opcode(_Opcode), LBAMSB(0), LUN(_LUN), LBAHB(0), LBALB(0), - AllocationLength(_AllocationLength), Control(_Control) { - } -} __attribute__((packed)); - -typedef CDB6 CDB6_t; - -struct CDB10 { - uint8_t Opcode; - - unsigned Service_Action : 5; - unsigned LUN : 3; - - uint8_t LBA_L_M_MB; - uint8_t LBA_L_M_LB; - uint8_t LBA_L_L_MB; - uint8_t LBA_L_L_LB; - - uint8_t Misc2; - - uint8_t ALC_MB; - uint8_t ALC_LB; - - uint8_t Control; -public: - - CDB10(uint8_t _Opcode, uint8_t _LUN) : - Opcode(_Opcode), Service_Action(0), LUN(_LUN), - LBA_L_M_MB(0), LBA_L_M_LB(0), LBA_L_L_MB(0), LBA_L_L_LB(0), - Misc2(0), ALC_MB(0), ALC_LB(0), Control(0) { - } - - CDB10(uint8_t _Opcode, uint8_t _LUN, uint16_t xflen, uint32_t _LBA) : - Opcode(_Opcode), Service_Action(0), LUN(_LUN), - LBA_L_M_MB(BGRAB3(_LBA)), LBA_L_M_LB(BGRAB2(_LBA)), LBA_L_L_MB(BGRAB1(_LBA)), LBA_L_L_LB(BGRAB0(_LBA)), - Misc2(0), ALC_MB(BGRAB1(xflen)), ALC_LB(BGRAB0(xflen)), Control(0) { - } -} __attribute__((packed)); - -typedef CDB10 CDB10_t; - -struct CDB12 { - uint8_t Opcode; - - unsigned Service_Action : 5; - unsigned Misc : 3; - - uint8_t LBA_L_M_LB; - uint8_t LBA_L_L_MB; - uint8_t LBA_L_L_LB; - - uint8_t ALC_M_LB; - uint8_t ALC_L_MB; - uint8_t ALC_L_LB; - uint8_t Control; -} __attribute__((packed)); - -typedef CDB12 CDB12_t; - -struct CDB_LBA32_16 { - uint8_t Opcode; - - unsigned Service_Action : 5; - unsigned Misc : 3; - - uint8_t LBA_L_M_MB; - uint8_t LBA_L_M_LB; - uint8_t LBA_L_L_MB; - uint8_t LBA_L_L_LB; - - uint8_t A_M_M_MB; - uint8_t A_M_M_LB; - uint8_t A_M_L_MB; - uint8_t A_M_L_LB; - - uint8_t ALC_M_MB; - uint8_t ALC_M_LB; - uint8_t ALC_L_MB; - uint8_t ALC_L_LB; - - uint8_t Misc2; - uint8_t Control; -} __attribute__((packed)); - -struct CDB_LBA64_16 { - uint8_t Opcode; - uint8_t Misc; - - uint8_t LBA_M_M_MB; - uint8_t LBA_M_M_LB; - uint8_t LBA_M_L_MB; - uint8_t LBA_M_L_LB; - - uint8_t LBA_L_M_MB; - uint8_t LBA_L_M_LB; - uint8_t LBA_L_L_MB; - uint8_t LBA_L_L_LB; - - uint8_t ALC_M_MB; - uint8_t ALC_M_LB; - uint8_t ALC_L_MB; - uint8_t ALC_L_LB; - - uint8_t Misc2; - uint8_t Control; -} __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 HISUP : 1; - unsigned NormACA : 1; - unsigned TrmTsk : 1; - unsigned AERC : 1; - - uint8_t AdditionalLength; - //uint8_t Reserved3[2]; - - unsigned PROTECT : 1; - unsigned Res : 2; - unsigned ThreePC : 1; - unsigned TPGS : 2; - unsigned ACC : 1; - unsigned SCCS : 1; - - unsigned ADDR16 : 1; - unsigned R1 : 1; - unsigned R2 : 1; - unsigned MCHNGR : 1; - unsigned MULTIP : 1; - unsigned VS : 1; - unsigned ENCSERV : 1; - unsigned BQUE : 1; - - 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; -public: - - CommandBlockWrapperBase() { - } - - CommandBlockWrapperBase(uint32_t tag, uint32_t xflen, uint8_t flgs) : - dCBWSignature(MASS_CBW_SIGNATURE), dCBWTag(tag), dCBWDataTransferLength(xflen), bmCBWFlags(flgs) { - } -} __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]; - -public: - // All zeroed. - - CommandBlockWrapper() : - CommandBlockWrapperBase(0, 0, 0), bmReserved1(0), bmReserved2(0) { - for(int i = 0; i < 16; i++) CBWCB[i] = 0; - } - - // Generic Wrap, CDB zeroed. - - CommandBlockWrapper(uint32_t tag, uint32_t xflen, uint8_t flgs, uint8_t lu, uint8_t cmdlen, uint8_t cmd) : - CommandBlockWrapperBase(tag, xflen, flgs), - bmCBWLUN(lu), bmReserved1(0), bmCBWCBLength(cmdlen), bmReserved2(0) { - for(int i = 0; i < 16; i++) CBWCB[i] = 0; - // Type punning can cause optimization problems and bugs. - // Using reinterpret_cast to a dreinterpretifferent object is the proper way to do this. - //(((BASICCDB_t *) CBWCB)->LUN) = cmd; - BASICCDB_t *x = reinterpret_cast(CBWCB); - x->LUN = cmd; - } - - // Wrap for CDB of 6 - - CommandBlockWrapper(uint32_t tag, uint32_t xflen, CDB6_t *cdb, uint8_t dir) : - CommandBlockWrapperBase(tag, xflen, dir), - bmCBWLUN(cdb->LUN), bmReserved1(0), bmCBWCBLength(6), bmReserved2(0) { - memcpy(&CBWCB, cdb, 6); - } - // Wrap for CDB of 10 - - CommandBlockWrapper(uint32_t tag, uint32_t xflen, CDB10_t *cdb, uint8_t dir) : - CommandBlockWrapperBase(tag, xflen, dir), - bmCBWLUN(cdb->LUN), bmReserved1(0), bmCBWCBLength(10), bmReserved2(0) { - memcpy(&CBWCB, cdb, 10); - } -} __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)); - -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 - uint32_t CurrentCapacity[MASS_MAX_SUPPORTED_LUN]; // Total sectors - uint16_t CurrentSectorSize[MASS_MAX_SUPPORTED_LUN]; // Sector size, clipped to 16 bits - bool LUNOk[MASS_MAX_SUPPORTED_LUN]; // use this to check for media changes. - bool WriteOk[MASS_MAX_SUPPORTED_LUN]; - void PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr); - - - // Additional Initialization Method for Subclasses - - virtual uint8_t OnInit() { - return 0; - }; -public: - BulkOnly(USB *p); - - uint8_t GetLastUsbError() { - return bLastUsbError; - }; - - uint8_t GetbMaxLUN() { - return bMaxLUN; // Max LUN - } - - uint8_t GetbTheLUN() { - return bTheLUN; // Active LUN - } - - bool WriteProtected(uint8_t lun); - 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); - uint8_t LockMedia(uint8_t lun, uint8_t lock); - - bool LUNIsGood(uint8_t lun); - uint32_t GetCapacity(uint8_t lun); - uint16_t GetSectorSize(uint8_t lun); - - // USBDeviceConfig implementation - uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed); - uint8_t ConfigureDevice(uint8_t parent, uint8_t port, bool lowspeed); - - uint8_t Release(); - uint8_t Poll(); - - virtual uint8_t GetAddress() { - return bAddress; - }; - - // UsbConfigXtracter implementation - void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep); - - virtual bool DEVCLASSOK(uint8_t klass) { - return (klass == USB_CLASS_MASS_STORAGE); - } - - uint8_t SCSITransaction6(CDB6_t *cdb, uint16_t buf_size, void *buf, uint8_t dir); - uint8_t SCSITransaction10(CDB10_t *cdb, uint16_t buf_size, void *buf, uint8_t dir); - -private: - uint8_t Inquiry(uint8_t lun, uint16_t size, uint8_t *buf); - uint8_t TestUnitReady(uint8_t lun); - uint8_t RequestSense(uint8_t lun, uint16_t size, uint8_t *buf); - uint8_t ModeSense6(uint8_t lun, uint8_t pc, uint8_t page, uint8_t subpage, uint8_t len, uint8_t *buf); - uint8_t GetMaxLUN(uint8_t *max_lun); - uint8_t SetCurLUN(uint8_t lun); - void Reset(); - uint8_t ResetRecovery(); - uint8_t ReadCapacity10(uint8_t lun, uint8_t *buf); - void ClearAllEP(); - void CheckMedia(); - bool CheckLUN(uint8_t lun); - uint8_t Page3F(uint8_t lun); - 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); -#if MS_WANT_PARSER - uint8_t Transaction(CommandBlockWrapper *cbw, uint16_t bsize, void *buf, uint8_t flags); -#endif - uint8_t Transaction(CommandBlockWrapper *cbw, uint16_t bsize, void *buf); - uint8_t HandleUsbError(uint8_t error, uint8_t index); - uint8_t HandleSCSIError(uint8_t status); - -}; - -#endif // __MASSTORAGE_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(__MASSTORAGE_H__) +#define __MASSTORAGE_H__ + +// Cruft removal, makes driver smaller, faster. +#ifndef MS_WANT_PARSER +#define MS_WANT_PARSER 0 +#endif + +#include "Usb.h" + +#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 // (0 << 7) +#define MASS_CMD_DIR_IN 0x80 //(1 << 7) + +/* + * Reference documents from T10 (http://www.t10.org) + * SCSI Primary Commands - 3 (SPC-3) + * SCSI Block Commands - 2 (SBC-2) + * Multi-Media Commands - 5 (MMC-5) + */ + +/* Group 1 commands (CDB's here are should all be 6-bytes) */ +#define SCSI_CMD_TEST_UNIT_READY 0x00 +#define SCSI_CMD_REQUEST_SENSE 0x03 +#define SCSI_CMD_FORMAT_UNIT 0x04 +#define SCSI_CMD_READ_6 0x08 +#define SCSI_CMD_WRITE_6 0x0A +#define SCSI_CMD_INQUIRY 0x12 +#define SCSI_CMD_MODE_SELECT_6 0x15 +#define SCSI_CMD_MODE_SENSE_6 0x1A +#define SCSI_CMD_START_STOP_UNIT 0x1B +#define SCSI_CMD_PREVENT_REMOVAL 0x1E +/* Group 2 Commands (CDB's here are 10-bytes) */ +#define SCSI_CMD_READ_FORMAT_CAPACITIES 0x23 +#define SCSI_CMD_READ_CAPACITY_10 0x25 +#define SCSI_CMD_READ_10 0x28 +#define SCSI_CMD_WRITE_10 0x2A +#define SCSI_CMD_SEEK_10 0x2B +#define SCSI_CMD_ERASE_10 0x2C +#define SCSI_CMD_WRITE_AND_VERIFY_10 0x2E +#define SCSI_CMD_VERIFY_10 0x2F +#define SCSI_CMD_SYNCHRONIZE_CACHE 0x35 +#define SCSI_CMD_WRITE_BUFFER 0x3B +#define SCSI_CMD_READ_BUFFER 0x3C +#define SCSI_CMD_READ_SUBCHANNEL 0x42 +#define SCSI_CMD_READ_TOC 0x43 +#define SCSI_CMD_READ_HEADER 0x44 +#define SCSI_CMD_PLAY_AUDIO_10 0x45 +#define SCSI_CMD_GET_CONFIGURATION 0x46 +#define SCSI_CMD_PLAY_AUDIO_MSF 0x47 +#define SCSI_CMD_PLAY_AUDIO_TI 0x48 +#define SCSI_CMD_PLAY_TRACK_REL_10 0x49 +#define SCSI_CMD_GET_EVENT_STATUS 0x4A +#define SCSI_CMD_PAUSE_RESUME 0x4B +#define SCSI_CMD_READ_DISC_INFORMATION 0x51 +#define SCSI_CMD_READ_TRACK_INFORMATION 0x52 +#define SCSI_CMD_RESERVE_TRACK 0x53 +#define SCSI_CMD_SEND_OPC_INFORMATION 0x54 +#define SCSI_CMD_MODE_SELECT_10 0x55 +#define SCSI_CMD_REPAIR_TRACK 0x58 +#define SCSI_CMD_MODE_SENSE_10 0x5A +#define SCSI_CMD_CLOSE_TRACK_SESSION 0x5B +#define SCSI_CMD_READ_BUFFER_CAPACITY 0x5C +#define SCSI_CMD_SEND_CUE_SHEET 0x5D +/* Group 5 Commands (CDB's here are 12-bytes) */ +#define SCSI_CMD_REPORT_LUNS 0xA0 +#define SCSI_CMD_BLANK 0xA1 +#define SCSI_CMD_SECURITY_PROTOCOL_IN 0xA2 +#define SCSI_CMD_SEND_KEY 0xA3 +#define SCSI_CMD_REPORT_KEY 0xA4 +#define SCSI_CMD_PLAY_AUDIO_12 0xA5 +#define SCSI_CMD_LOAD_UNLOAD 0xA6 +#define SCSI_CMD_SET_READ_AHEAD 0xA7 +#define SCSI_CMD_READ_12 0xA8 +#define SCSI_CMD_PLAY_TRACK_REL_12 0xA9 +#define SCSI_CMD_WRITE_12 0xAA +#define SCSI_CMD_READ_MEDIA_SERIAL_12 0xAB +#define SCSI_CMD_GET_PERFORMANCE 0xAC +#define SCSI_CMD_READ_DVD_STRUCTURE 0xAD +#define SCSI_CMD_SECURITY_PROTOCOL_OUT 0xB5 +#define SCSI_CMD_SET_STREAMING 0xB6 +#define SCSI_CMD_READ_MSF 0xB9 +#define SCSI_CMD_SET_SPEED 0xBB +#define SCSI_CMD_MECHANISM_STATUS 0xBD +#define SCSI_CMD_READ_CD 0xBE +#define SCSI_CMD_SEND_DISC_STRUCTURE 0xBF +/* Vendor-unique Commands, included for completeness */ +#define SCSI_CMD_CD_PLAYBACK_STATUS 0xC4 /* SONY unique */ +#define SCSI_CMD_PLAYBACK_CONTROL 0xC9 /* SONY unique */ +#define SCSI_CMD_READ_CDDA 0xD8 /* Vendor unique */ +#define SCSI_CMD_READ_CDXA 0xDB /* Vendor unique */ +#define SCSI_CMD_READ_ALL_SUBCODES 0xDF /* Vendor unique */ + +/* SCSI error codes */ +#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_LBA_OUT_OF_RANGE 0x21 +#define SCSI_ASC_MEDIA_CHANGED 0x28 +#define SCSI_ASC_MEDIUM_NOT_PRESENT 0x3A + +/* USB error codes */ +#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_MEDIA_CHANGED 0x0A +#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_WRITE_STALL 0x14 +#define MASS_ERR_READ_NAKS 0x15 +#define MASS_ERR_WRITE_NAKS 0x16 +#define MASS_ERR_WRITE_PROTECTED 0x17 +#define MASS_ERR_NOT_IMPLEMENTED 0xFD +#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 + +#define MASS_MAX_ENDPOINTS 3 + +struct Capacity { + uint8_t data[8]; + //uint32_t dwBlockAddress; + //uint32_t dwBlockLength; +} __attribute__((packed)); + +struct BASICCDB { + uint8_t Opcode; + + unsigned unused : 5; + unsigned LUN : 3; + + uint8_t info[12]; +} __attribute__((packed)); + +typedef BASICCDB BASICCDB_t; + +struct CDB6 { + uint8_t Opcode; + + unsigned LBAMSB : 5; + unsigned LUN : 3; + + uint8_t LBAHB; + uint8_t LBALB; + uint8_t AllocationLength; + uint8_t Control; + +public: + + CDB6(uint8_t _Opcode, uint8_t _LUN, uint32_t LBA, uint8_t _AllocationLength, uint8_t _Control) : + Opcode(_Opcode), LBAMSB(BGRAB2(LBA) & 0x1f), LUN(_LUN), LBAHB(BGRAB1(LBA)), LBALB(BGRAB0(LBA)), + AllocationLength(_AllocationLength), Control(_Control) { + } + + CDB6(uint8_t _Opcode, uint8_t _LUN, uint8_t _AllocationLength, uint8_t _Control) : + Opcode(_Opcode), LBAMSB(0), LUN(_LUN), LBAHB(0), LBALB(0), + AllocationLength(_AllocationLength), Control(_Control) { + } +} __attribute__((packed)); + +typedef CDB6 CDB6_t; + +struct CDB10 { + uint8_t Opcode; + + unsigned Service_Action : 5; + unsigned LUN : 3; + + uint8_t LBA_L_M_MB; + uint8_t LBA_L_M_LB; + uint8_t LBA_L_L_MB; + uint8_t LBA_L_L_LB; + + uint8_t Misc2; + + uint8_t ALC_MB; + uint8_t ALC_LB; + + uint8_t Control; +public: + + CDB10(uint8_t _Opcode, uint8_t _LUN) : + Opcode(_Opcode), Service_Action(0), LUN(_LUN), + LBA_L_M_MB(0), LBA_L_M_LB(0), LBA_L_L_MB(0), LBA_L_L_LB(0), + Misc2(0), ALC_MB(0), ALC_LB(0), Control(0) { + } + + CDB10(uint8_t _Opcode, uint8_t _LUN, uint16_t xflen, uint32_t _LBA) : + Opcode(_Opcode), Service_Action(0), LUN(_LUN), + LBA_L_M_MB(BGRAB3(_LBA)), LBA_L_M_LB(BGRAB2(_LBA)), LBA_L_L_MB(BGRAB1(_LBA)), LBA_L_L_LB(BGRAB0(_LBA)), + Misc2(0), ALC_MB(BGRAB1(xflen)), ALC_LB(BGRAB0(xflen)), Control(0) { + } +} __attribute__((packed)); + +typedef CDB10 CDB10_t; + +struct CDB12 { + uint8_t Opcode; + + unsigned Service_Action : 5; + unsigned Misc : 3; + + uint8_t LBA_L_M_LB; + uint8_t LBA_L_L_MB; + uint8_t LBA_L_L_LB; + + uint8_t ALC_M_LB; + uint8_t ALC_L_MB; + uint8_t ALC_L_LB; + uint8_t Control; +} __attribute__((packed)); + +typedef CDB12 CDB12_t; + +struct CDB_LBA32_16 { + uint8_t Opcode; + + unsigned Service_Action : 5; + unsigned Misc : 3; + + uint8_t LBA_L_M_MB; + uint8_t LBA_L_M_LB; + uint8_t LBA_L_L_MB; + uint8_t LBA_L_L_LB; + + uint8_t A_M_M_MB; + uint8_t A_M_M_LB; + uint8_t A_M_L_MB; + uint8_t A_M_L_LB; + + uint8_t ALC_M_MB; + uint8_t ALC_M_LB; + uint8_t ALC_L_MB; + uint8_t ALC_L_LB; + + uint8_t Misc2; + uint8_t Control; +} __attribute__((packed)); + +struct CDB_LBA64_16 { + uint8_t Opcode; + uint8_t Misc; + + uint8_t LBA_M_M_MB; + uint8_t LBA_M_M_LB; + uint8_t LBA_M_L_MB; + uint8_t LBA_M_L_LB; + + uint8_t LBA_L_M_MB; + uint8_t LBA_L_M_LB; + uint8_t LBA_L_L_MB; + uint8_t LBA_L_L_LB; + + uint8_t ALC_M_MB; + uint8_t ALC_M_LB; + uint8_t ALC_L_MB; + uint8_t ALC_L_LB; + + uint8_t Misc2; + uint8_t Control; +} __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 HISUP : 1; + unsigned NormACA : 1; + unsigned TrmTsk : 1; + unsigned AERC : 1; + + uint8_t AdditionalLength; + //uint8_t Reserved3[2]; + + unsigned PROTECT : 1; + unsigned Res : 2; + unsigned ThreePC : 1; + unsigned TPGS : 2; + unsigned ACC : 1; + unsigned SCCS : 1; + + unsigned ADDR16 : 1; + unsigned R1 : 1; + unsigned R2 : 1; + unsigned MCHNGR : 1; + unsigned MULTIP : 1; + unsigned VS : 1; + unsigned ENCSERV : 1; + unsigned BQUE : 1; + + 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; +public: + + CommandBlockWrapperBase() { + } + + CommandBlockWrapperBase(uint32_t tag, uint32_t xflen, uint8_t flgs) : + dCBWSignature(MASS_CBW_SIGNATURE), dCBWTag(tag), dCBWDataTransferLength(xflen), bmCBWFlags(flgs) { + } +} __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]; + +public: + // All zeroed. + + CommandBlockWrapper() : + CommandBlockWrapperBase(0, 0, 0), bmReserved1(0), bmReserved2(0) { + for(int i = 0; i < 16; i++) CBWCB[i] = 0; + } + + // Generic Wrap, CDB zeroed. + + CommandBlockWrapper(uint32_t tag, uint32_t xflen, uint8_t flgs, uint8_t lu, uint8_t cmdlen, uint8_t cmd) : + CommandBlockWrapperBase(tag, xflen, flgs), + bmCBWLUN(lu), bmReserved1(0), bmCBWCBLength(cmdlen), bmReserved2(0) { + for(int i = 0; i < 16; i++) CBWCB[i] = 0; + // Type punning can cause optimization problems and bugs. + // Using reinterpret_cast to a dreinterpretifferent object is the proper way to do this. + //(((BASICCDB_t *) CBWCB)->LUN) = cmd; + BASICCDB_t *x = reinterpret_cast(CBWCB); + x->LUN = cmd; + } + + // Wrap for CDB of 6 + + CommandBlockWrapper(uint32_t tag, uint32_t xflen, CDB6_t *cdb, uint8_t dir) : + CommandBlockWrapperBase(tag, xflen, dir), + bmCBWLUN(cdb->LUN), bmReserved1(0), bmCBWCBLength(6), bmReserved2(0) { + memcpy(&CBWCB, cdb, 6); + } + // Wrap for CDB of 10 + + CommandBlockWrapper(uint32_t tag, uint32_t xflen, CDB10_t *cdb, uint8_t dir) : + CommandBlockWrapperBase(tag, xflen, dir), + bmCBWLUN(cdb->LUN), bmReserved1(0), bmCBWCBLength(10), bmReserved2(0) { + memcpy(&CBWCB, cdb, 10); + } +} __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)); + +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 + uint32_t CurrentCapacity[MASS_MAX_SUPPORTED_LUN]; // Total sectors + uint16_t CurrentSectorSize[MASS_MAX_SUPPORTED_LUN]; // Sector size, clipped to 16 bits + bool LUNOk[MASS_MAX_SUPPORTED_LUN]; // use this to check for media changes. + bool WriteOk[MASS_MAX_SUPPORTED_LUN]; + void PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr); + + + // Additional Initialization Method for Subclasses + + virtual uint8_t OnInit() { + return 0; + }; +public: + BulkOnly(USB *p); + + uint8_t GetLastUsbError() { + return bLastUsbError; + }; + + uint8_t GetbMaxLUN() { + return bMaxLUN; // Max LUN + } + + uint8_t GetbTheLUN() { + return bTheLUN; // Active LUN + } + + bool WriteProtected(uint8_t lun); + 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); + uint8_t LockMedia(uint8_t lun, uint8_t lock); + + bool LUNIsGood(uint8_t lun); + uint32_t GetCapacity(uint8_t lun); + uint16_t GetSectorSize(uint8_t lun); + + // USBDeviceConfig implementation + uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed); + uint8_t ConfigureDevice(uint8_t parent, uint8_t port, bool lowspeed); + + uint8_t Release(); + uint8_t Poll(); + + virtual uint8_t GetAddress() { + return bAddress; + }; + + // UsbConfigXtracter implementation + void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep); + + virtual bool DEVCLASSOK(uint8_t klass) { + return (klass == USB_CLASS_MASS_STORAGE); + } + + uint8_t SCSITransaction6(CDB6_t *cdb, uint16_t buf_size, void *buf, uint8_t dir); + uint8_t SCSITransaction10(CDB10_t *cdb, uint16_t buf_size, void *buf, uint8_t dir); + +private: + uint8_t Inquiry(uint8_t lun, uint16_t size, uint8_t *buf); + uint8_t TestUnitReady(uint8_t lun); + uint8_t RequestSense(uint8_t lun, uint16_t size, uint8_t *buf); + uint8_t ModeSense6(uint8_t lun, uint8_t pc, uint8_t page, uint8_t subpage, uint8_t len, uint8_t *buf); + uint8_t GetMaxLUN(uint8_t *max_lun); + uint8_t SetCurLUN(uint8_t lun); + void Reset(); + uint8_t ResetRecovery(); + uint8_t ReadCapacity10(uint8_t lun, uint8_t *buf); + void ClearAllEP(); + void CheckMedia(); + bool CheckLUN(uint8_t lun); + uint8_t Page3F(uint8_t lun); + 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); +#if MS_WANT_PARSER + uint8_t Transaction(CommandBlockWrapper *cbw, uint16_t bsize, void *buf, uint8_t flags); +#endif + uint8_t Transaction(CommandBlockWrapper *cbw, uint16_t bsize, void *buf); + uint8_t HandleUsbError(uint8_t error, uint8_t index); + uint8_t HandleSCSIError(uint8_t status); + +}; + +#endif // __MASSTORAGE_H__ diff --git a/max3421e.h b/max3421e.h index 7986a9b3..4e45a35e 100644 --- a/max3421e.h +++ b/max3421e.h @@ -1,233 +1,228 @@ -/* 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(_usb_h_) || defined(_max3421e_h_) -#error "Never include max3421e.h directly; include Usb.h instead" -#else - -#define _max3421e_h_ - -/* MAX3421E register/bit names and bitmasks */ - -/* Arduino pin definitions */ -/* pin numbers to port numbers */ - - -//#define MAX_INT 9 // Duemielanove - -//#define MAX_GPX 8 - -#define SE0 0 -#define SE1 1 -#define FSHOST 2 -#define LSHOST 3 - -/* MAX3421E command byte format: rrrrr0wa where 'r' is register number */ -// -// MAX3421E Registers in HOST mode. -// -#define rRCVFIFO 0x08 //1<<3 -#define rSNDFIFO 0x10 //2<<3 -#define rSUDFIFO 0x20 //4<<3 -#define rRCVBC 0x30 //6<<3 -#define rSNDBC 0x38 //7<<3 - -#define rUSBIRQ 0x68 //13<<3 -/* USBIRQ Bits */ -#define bmVBUSIRQ 0x40 //b6 -#define bmNOVBUSIRQ 0x20 //b5 -#define bmOSCOKIRQ 0x01 //b0 - -#define rUSBIEN 0x70 //14<<3 -/* USBIEN Bits */ -#define bmVBUSIE 0x40 //b6 -#define bmNOVBUSIE 0x20 //b5 -#define bmOSCOKIE 0x01 //b0 - -#define rUSBCTL 0x78 //15<<3 -/* USBCTL Bits */ -#define bmCHIPRES 0x20 //b5 -#define bmPWRDOWN 0x10 //b4 - -#define rCPUCTL 0x80 //16<<3 -/* CPUCTL Bits */ -#define bmPUSLEWID1 0x80 //b7 -#define bmPULSEWID0 0x40 //b6 -#define bmIE 0x01 //b0 - -#define rPINCTL 0x88 //17<<3 -/* PINCTL Bits */ -#define bmFDUPSPI 0x10 //b4 -#define bmINTLEVEL 0x08 //b3 -#define bmPOSINT 0x04 //b2 -#define bmGPXB 0x02 //b1 -#define bmGPXA 0x01 //b0 -// GPX pin selections -#define GPX_OPERATE 0x00 -#define GPX_VBDET 0x01 -#define GPX_BUSACT 0x02 -#define GPX_SOF 0x03 - -#define rREVISION 0x90 //18<<3 - -#define rIOPINS1 0xa0 //20<<3 - -/* IOPINS1 Bits */ -#define bmGPOUT0 0x01 -#define bmGPOUT1 0x02 -#define bmGPOUT2 0x04 -#define bmGPOUT3 0x08 -#define bmGPIN0 0x10 -#define bmGPIN1 0x20 -#define bmGPIN2 0x40 -#define bmGPIN3 0x80 - -#define rIOPINS2 0xa8 //21<<3 -/* IOPINS2 Bits */ -#define bmGPOUT4 0x01 -#define bmGPOUT5 0x02 -#define bmGPOUT6 0x04 -#define bmGPOUT7 0x08 -#define bmGPIN4 0x10 -#define bmGPIN5 0x20 -#define bmGPIN6 0x40 -#define bmGPIN7 0x80 - -#define rGPINIRQ 0xb0 //22<<3 -/* GPINIRQ Bits */ -#define bmGPINIRQ0 0x01 -#define bmGPINIRQ1 0x02 -#define bmGPINIRQ2 0x04 -#define bmGPINIRQ3 0x08 -#define bmGPINIRQ4 0x10 -#define bmGPINIRQ5 0x20 -#define bmGPINIRQ6 0x40 -#define bmGPINIRQ7 0x80 - -#define rGPINIEN 0xb8 //23<<3 -/* GPINIEN Bits */ -#define bmGPINIEN0 0x01 -#define bmGPINIEN1 0x02 -#define bmGPINIEN2 0x04 -#define bmGPINIEN3 0x08 -#define bmGPINIEN4 0x10 -#define bmGPINIEN5 0x20 -#define bmGPINIEN6 0x40 -#define bmGPINIEN7 0x80 - -#define rGPINPOL 0xc0 //24<<3 -/* GPINPOL Bits */ -#define bmGPINPOL0 0x01 -#define bmGPINPOL1 0x02 -#define bmGPINPOL2 0x04 -#define bmGPINPOL3 0x08 -#define bmGPINPOL4 0x10 -#define bmGPINPOL5 0x20 -#define bmGPINPOL6 0x40 -#define bmGPINPOL7 0x80 - -#define rHIRQ 0xc8 //25<<3 -/* HIRQ Bits */ -#define bmBUSEVENTIRQ 0x01 // indicates BUS Reset Done or BUS Resume -#define bmRWUIRQ 0x02 -#define bmRCVDAVIRQ 0x04 -#define bmSNDBAVIRQ 0x08 -#define bmSUSDNIRQ 0x10 -#define bmCONDETIRQ 0x20 -#define bmFRAMEIRQ 0x40 -#define bmHXFRDNIRQ 0x80 - -#define rHIEN 0xd0 //26<<3 - -/* HIEN Bits */ -#define bmBUSEVENTIE 0x01 -#define bmRWUIE 0x02 -#define bmRCVDAVIE 0x04 -#define bmSNDBAVIE 0x08 -#define bmSUSDNIE 0x10 -#define bmCONDETIE 0x20 -#define bmFRAMEIE 0x40 -#define bmHXFRDNIE 0x80 - -#define rMODE 0xd8 //27<<3 - -/* MODE Bits */ -#define bmHOST 0x01 -#define bmLOWSPEED 0x02 -#define bmHUBPRE 0x04 -#define bmSOFKAENAB 0x08 -#define bmSEPIRQ 0x10 -#define bmDELAYISO 0x20 -#define bmDMPULLDN 0x40 -#define bmDPPULLDN 0x80 - -#define rPERADDR 0xe0 //28<<3 - -#define rHCTL 0xe8 //29<<3 -/* HCTL Bits */ -#define bmBUSRST 0x01 -#define bmFRMRST 0x02 -#define bmSAMPLEBUS 0x04 -#define bmSIGRSM 0x08 -#define bmRCVTOG0 0x10 -#define bmRCVTOG1 0x20 -#define bmSNDTOG0 0x40 -#define bmSNDTOG1 0x80 - -#define rHXFR 0xf0 //30<<3 -/* Host transfer token values for writing the HXFR register (R30) */ -/* OR this bit field with the endpoint number in bits 3:0 */ -#define tokSETUP 0x10 // HS=0, ISO=0, OUTNIN=0, SETUP=1 -#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 tokISOIN 0x40 // HS=0, ISO=1, OUTNIN=0, SETUP=0 -#define tokISOOUT 0x60 // HS=0, ISO=1, OUTNIN=1, SETUP=0 - -#define rHRSL 0xf8 //31<<3 - -/* HRSL Bits */ -#define bmRCVTOGRD 0x10 -#define bmSNDTOGRD 0x20 -#define bmKSTATUS 0x40 -#define bmJSTATUS 0x80 -#define bmSE0 0x00 //SE0 - disconnect state -#define bmSE1 0xc0 //SE1 - illegal state - -/* Host error result codes, the 4 LSB's in the HRSL register */ -#define hrSUCCESS 0x00 -#define hrBUSY 0x01 -#define hrBADREQ 0x02 -#define hrUNDEF 0x03 -#define hrNAK 0x04 -#define hrSTALL 0x05 -#define hrTOGERR 0x06 -#define hrWRONGPID 0x07 -#define hrBADBC 0x08 -#define hrPIDERR 0x09 -#define hrPKTERR 0x0A -#define hrCRCERR 0x0B -#define hrKERR 0x0C -#define hrJERR 0x0D -#define hrTIMEOUT 0x0E -#define hrBABBLE 0x0F - -#define MODE_FS_HOST (bmDPPULLDN|bmDMPULLDN|bmHOST|bmSOFKAENAB) -#define MODE_LS_HOST (bmDPPULLDN|bmDMPULLDN|bmHOST|bmLOWSPEED|bmSOFKAENAB) - - -#endif //_max3421e_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(_usb_h_) || defined(_max3421e_h_) +#error "Never include max3421e.h directly; include Usb.h instead" +#else + +#define _max3421e_h_ + +/* MAX3421E register/bit names and bitmasks */ + +/* Arduino pin definitions */ +/* pin numbers to port numbers */ + +#define SE0 0 +#define SE1 1 +#define FSHOST 2 +#define LSHOST 3 + +/* MAX3421E command byte format: rrrrr0wa where 'r' is register number */ +// +// MAX3421E Registers in HOST mode. +// +#define rRCVFIFO 0x08 //1<<3 +#define rSNDFIFO 0x10 //2<<3 +#define rSUDFIFO 0x20 //4<<3 +#define rRCVBC 0x30 //6<<3 +#define rSNDBC 0x38 //7<<3 + +#define rUSBIRQ 0x68 //13<<3 +/* USBIRQ Bits */ +#define bmVBUSIRQ 0x40 //b6 +#define bmNOVBUSIRQ 0x20 //b5 +#define bmOSCOKIRQ 0x01 //b0 + +#define rUSBIEN 0x70 //14<<3 +/* USBIEN Bits */ +#define bmVBUSIE 0x40 //b6 +#define bmNOVBUSIE 0x20 //b5 +#define bmOSCOKIE 0x01 //b0 + +#define rUSBCTL 0x78 //15<<3 +/* USBCTL Bits */ +#define bmCHIPRES 0x20 //b5 +#define bmPWRDOWN 0x10 //b4 + +#define rCPUCTL 0x80 //16<<3 +/* CPUCTL Bits */ +#define bmPUSLEWID1 0x80 //b7 +#define bmPULSEWID0 0x40 //b6 +#define bmIE 0x01 //b0 + +#define rPINCTL 0x88 //17<<3 +/* PINCTL Bits */ +#define bmFDUPSPI 0x10 //b4 +#define bmINTLEVEL 0x08 //b3 +#define bmPOSINT 0x04 //b2 +#define bmGPXB 0x02 //b1 +#define bmGPXA 0x01 //b0 +// GPX pin selections +#define GPX_OPERATE 0x00 +#define GPX_VBDET 0x01 +#define GPX_BUSACT 0x02 +#define GPX_SOF 0x03 + +#define rREVISION 0x90 //18<<3 + +#define rIOPINS1 0xa0 //20<<3 + +/* IOPINS1 Bits */ +#define bmGPOUT0 0x01 +#define bmGPOUT1 0x02 +#define bmGPOUT2 0x04 +#define bmGPOUT3 0x08 +#define bmGPIN0 0x10 +#define bmGPIN1 0x20 +#define bmGPIN2 0x40 +#define bmGPIN3 0x80 + +#define rIOPINS2 0xa8 //21<<3 +/* IOPINS2 Bits */ +#define bmGPOUT4 0x01 +#define bmGPOUT5 0x02 +#define bmGPOUT6 0x04 +#define bmGPOUT7 0x08 +#define bmGPIN4 0x10 +#define bmGPIN5 0x20 +#define bmGPIN6 0x40 +#define bmGPIN7 0x80 + +#define rGPINIRQ 0xb0 //22<<3 +/* GPINIRQ Bits */ +#define bmGPINIRQ0 0x01 +#define bmGPINIRQ1 0x02 +#define bmGPINIRQ2 0x04 +#define bmGPINIRQ3 0x08 +#define bmGPINIRQ4 0x10 +#define bmGPINIRQ5 0x20 +#define bmGPINIRQ6 0x40 +#define bmGPINIRQ7 0x80 + +#define rGPINIEN 0xb8 //23<<3 +/* GPINIEN Bits */ +#define bmGPINIEN0 0x01 +#define bmGPINIEN1 0x02 +#define bmGPINIEN2 0x04 +#define bmGPINIEN3 0x08 +#define bmGPINIEN4 0x10 +#define bmGPINIEN5 0x20 +#define bmGPINIEN6 0x40 +#define bmGPINIEN7 0x80 + +#define rGPINPOL 0xc0 //24<<3 +/* GPINPOL Bits */ +#define bmGPINPOL0 0x01 +#define bmGPINPOL1 0x02 +#define bmGPINPOL2 0x04 +#define bmGPINPOL3 0x08 +#define bmGPINPOL4 0x10 +#define bmGPINPOL5 0x20 +#define bmGPINPOL6 0x40 +#define bmGPINPOL7 0x80 + +#define rHIRQ 0xc8 //25<<3 +/* HIRQ Bits */ +#define bmBUSEVENTIRQ 0x01 // indicates BUS Reset Done or BUS Resume +#define bmRWUIRQ 0x02 +#define bmRCVDAVIRQ 0x04 +#define bmSNDBAVIRQ 0x08 +#define bmSUSDNIRQ 0x10 +#define bmCONDETIRQ 0x20 +#define bmFRAMEIRQ 0x40 +#define bmHXFRDNIRQ 0x80 + +#define rHIEN 0xd0 //26<<3 + +/* HIEN Bits */ +#define bmBUSEVENTIE 0x01 +#define bmRWUIE 0x02 +#define bmRCVDAVIE 0x04 +#define bmSNDBAVIE 0x08 +#define bmSUSDNIE 0x10 +#define bmCONDETIE 0x20 +#define bmFRAMEIE 0x40 +#define bmHXFRDNIE 0x80 + +#define rMODE 0xd8 //27<<3 + +/* MODE Bits */ +#define bmHOST 0x01 +#define bmLOWSPEED 0x02 +#define bmHUBPRE 0x04 +#define bmSOFKAENAB 0x08 +#define bmSEPIRQ 0x10 +#define bmDELAYISO 0x20 +#define bmDMPULLDN 0x40 +#define bmDPPULLDN 0x80 + +#define rPERADDR 0xe0 //28<<3 + +#define rHCTL 0xe8 //29<<3 +/* HCTL Bits */ +#define bmBUSRST 0x01 +#define bmFRMRST 0x02 +#define bmSAMPLEBUS 0x04 +#define bmSIGRSM 0x08 +#define bmRCVTOG0 0x10 +#define bmRCVTOG1 0x20 +#define bmSNDTOG0 0x40 +#define bmSNDTOG1 0x80 + +#define rHXFR 0xf0 //30<<3 +/* Host transfer token values for writing the HXFR register (R30) */ +/* OR this bit field with the endpoint number in bits 3:0 */ +#define tokSETUP 0x10 // HS=0, ISO=0, OUTNIN=0, SETUP=1 +#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 tokISOIN 0x40 // HS=0, ISO=1, OUTNIN=0, SETUP=0 +#define tokISOOUT 0x60 // HS=0, ISO=1, OUTNIN=1, SETUP=0 + +#define rHRSL 0xf8 //31<<3 + +/* HRSL Bits */ +#define bmRCVTOGRD 0x10 +#define bmSNDTOGRD 0x20 +#define bmKSTATUS 0x40 +#define bmJSTATUS 0x80 +#define bmSE0 0x00 //SE0 - disconnect state +#define bmSE1 0xc0 //SE1 - illegal state + +/* Host error result codes, the 4 LSB's in the HRSL register */ +#define hrSUCCESS 0x00 +#define hrBUSY 0x01 +#define hrBADREQ 0x02 +#define hrUNDEF 0x03 +#define hrNAK 0x04 +#define hrSTALL 0x05 +#define hrTOGERR 0x06 +#define hrWRONGPID 0x07 +#define hrBADBC 0x08 +#define hrPIDERR 0x09 +#define hrPKTERR 0x0A +#define hrCRCERR 0x0B +#define hrKERR 0x0C +#define hrJERR 0x0D +#define hrTIMEOUT 0x0E +#define hrBABBLE 0x0F + +#define MODE_FS_HOST (bmDPPULLDN|bmDMPULLDN|bmHOST|bmSOFKAENAB) +#define MODE_LS_HOST (bmDPPULLDN|bmDMPULLDN|bmHOST|bmLOWSPEED|bmSOFKAENAB) + + +#endif //_max3421e_h_ diff --git a/max_LCD.cpp b/max_LCD.cpp index db61ea3b..f0c64666 100644 --- a/max_LCD.cpp +++ b/max_LCD.cpp @@ -1,255 +1,255 @@ -/* 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 - -// 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); -} - -#if defined(ARDUINO) && ARDUINO >=100 - -inline size_t Max_LCD::write(uint8_t value) { - LCD_sendchar(value); - return 1; // Assume success -} -#else - -inline void Max_LCD::write(uint8_t value) { - LCD_sendchar(value); -} -#endif - -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 + +// 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); +} + +#if defined(ARDUINO) && ARDUINO >=100 + +inline size_t Max_LCD::write(uint8_t value) { + LCD_sendchar(value); + return 1; // Assume success +} +#else + +inline void Max_LCD::write(uint8_t value) { + LCD_sendchar(value); +} +#endif + +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 fa366f87..950c9c5a 100644 --- a/max_LCD.h +++ b/max_LCD.h @@ -1,106 +1,106 @@ -/* 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 "Usb.h" -#include - -// 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); - void command(uint8_t); - -#if defined(ARDUINO) && ARDUINO >=100 - size_t write(uint8_t); - using Print::write; -#else - void write(uint8_t); -#endif - -private: - void sendbyte(uint8_t val); - uint8_t _displayfunction; //tokill - uint8_t _displaycontrol; - uint8_t _displaymode; - uint8_t _initialized; - uint8_t _numlines, _currline; -}; - -#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 + */ +//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 "Usb.h" +#include "Print.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); + void command(uint8_t); + +#if defined(ARDUINO) && ARDUINO >=100 + size_t write(uint8_t); + using Print::write; +#else + void write(uint8_t); +#endif + +private: + void sendbyte(uint8_t val); + uint8_t _displayfunction; //tokill + uint8_t _displaycontrol; + uint8_t _displaymode; + uint8_t _initialized; + uint8_t _numlines, _currline; +}; + +#endif diff --git a/message.cpp b/message.cpp index 960a9fb4..bdcdd183 100644 --- a/message.cpp +++ b/message.cpp @@ -1,116 +1,116 @@ -/* 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 "Usb.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 by software -int UsbDEBUGlvl = 0x80; - -void E_Notifyc(char c, int lvl) { - if(UsbDEBUGlvl < lvl) return; -#if defined(ARDUINO) && ARDUINO >=100 - USB_HOST_SERIAL.print(c); -#else - USB_HOST_SERIAL.print(c, BYTE); -#endif - //USB_HOST_SERIAL.flush(); -} - -void E_Notify(char const * msg, int lvl) { - if(UsbDEBUGlvl < lvl) return; - if(!msg) return; - char c; - - while((c = pgm_read_byte(msg++))) E_Notifyc(c, lvl); -} - -void E_NotifyStr(char const * msg, int lvl) { - if(UsbDEBUGlvl < lvl) return; - if(!msg) return; - char c; - - while((c = *msg++)) E_Notifyc(c, lvl); -} - -void E_Notify(uint8_t b, int lvl) { - if(UsbDEBUGlvl < lvl) return; -#if defined(ARDUINO) && ARDUINO >=100 - USB_HOST_SERIAL.print(b); -#else - USB_HOST_SERIAL.print(b, DEC); -#endif - //USB_HOST_SERIAL.flush(); -} - -void E_Notify(double d, int lvl) { - if(UsbDEBUGlvl < lvl) return; - USB_HOST_SERIAL.print(d); - //USB_HOST_SERIAL.flush(); -} - -#ifdef DEBUG_USB_HOST - -void NotifyFailGetDevDescr(void) { - Notify(PSTR("\r\ngetDevDescr "), 0x80); -} - -void NotifyFailSetDevTblEntry(void) { - Notify(PSTR("\r\nsetDevTblEn "), 0x80); -} - -void NotifyFailGetConfDescr(void) { - Notify(PSTR("\r\ngetConf "), 0x80); -} - -void NotifyFailSetConfDescr(void) { - Notify(PSTR("\r\nsetConf "), 0x80); -} - -void NotifyFailGetDevDescr(uint8_t reason) { - NotifyFailGetDevDescr(); - NotifyFail(reason); -} - -void NotifyFailSetDevTblEntry(uint8_t reason) { - NotifyFailSetDevTblEntry(); - NotifyFail(reason); - -} - -void NotifyFailGetConfDescr(uint8_t reason) { - NotifyFailGetConfDescr(); - NotifyFail(reason); -} - -void NotifyFailSetConfDescr(uint8_t reason) { - NotifyFailSetConfDescr(); - NotifyFail(reason); -} - -void NotifyFailUnknownDevice(uint16_t VID, uint16_t PID) { - Notify(PSTR("\r\nUnknown Device Connected - VID: "), 0x80); - D_PrintHex (VID, 0x80); - Notify(PSTR(" PID: "), 0x80); - D_PrintHex (PID, 0x80); -} - -void NotifyFail(uint8_t rcode) { - D_PrintHex (rcode, 0x80); - Notify(PSTR("\r\n"), 0x80); -} -#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 "Usb.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 by software +int UsbDEBUGlvl = 0x80; + +void E_Notifyc(char c, int lvl) { + if(UsbDEBUGlvl < lvl) return; +#if defined(ARDUINO) && ARDUINO >=100 + USB_HOST_SERIAL.print(c); +#else + USB_HOST_SERIAL.print(c, BYTE); +#endif + //USB_HOST_SERIAL.flush(); +} + +void E_Notify(char const * msg, int lvl) { + if(UsbDEBUGlvl < lvl) return; + if(!msg) return; + char c; + + while((c = pgm_read_byte(msg++))) E_Notifyc(c, lvl); +} + +void E_NotifyStr(char const * msg, int lvl) { + if(UsbDEBUGlvl < lvl) return; + if(!msg) return; + char c; + + while((c = *msg++)) E_Notifyc(c, lvl); +} + +void E_Notify(uint8_t b, int lvl) { + if(UsbDEBUGlvl < lvl) return; +#if defined(ARDUINO) && ARDUINO >=100 + USB_HOST_SERIAL.print(b); +#else + USB_HOST_SERIAL.print(b, DEC); +#endif + //USB_HOST_SERIAL.flush(); +} + +void E_Notify(double d, int lvl) { + if(UsbDEBUGlvl < lvl) return; + USB_HOST_SERIAL.print(d); + //USB_HOST_SERIAL.flush(); +} + +#ifdef DEBUG_USB_HOST + +void NotifyFailGetDevDescr(void) { + Notify(PSTR("\r\ngetDevDescr "), 0x80); +} + +void NotifyFailSetDevTblEntry(void) { + Notify(PSTR("\r\nsetDevTblEn "), 0x80); +} + +void NotifyFailGetConfDescr(void) { + Notify(PSTR("\r\ngetConf "), 0x80); +} + +void NotifyFailSetConfDescr(void) { + Notify(PSTR("\r\nsetConf "), 0x80); +} + +void NotifyFailGetDevDescr(uint8_t reason) { + NotifyFailGetDevDescr(); + NotifyFail(reason); +} + +void NotifyFailSetDevTblEntry(uint8_t reason) { + NotifyFailSetDevTblEntry(); + NotifyFail(reason); + +} + +void NotifyFailGetConfDescr(uint8_t reason) { + NotifyFailGetConfDescr(); + NotifyFail(reason); +} + +void NotifyFailSetConfDescr(uint8_t reason) { + NotifyFailSetConfDescr(); + NotifyFail(reason); +} + +void NotifyFailUnknownDevice(uint16_t VID, uint16_t PID) { + Notify(PSTR("\r\nUnknown Device Connected - VID: "), 0x80); + D_PrintHex (VID, 0x80); + Notify(PSTR(" PID: "), 0x80); + D_PrintHex (PID, 0x80); +} + +void NotifyFail(uint8_t rcode) { + D_PrintHex (rcode, 0x80); + Notify(PSTR("\r\n"), 0x80); +} +#endif diff --git a/message.h b/message.h index 41f526de..c26628e7 100644 --- a/message.h +++ b/message.h @@ -1,78 +1,78 @@ -/* 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(_usb_h_) || defined(__MESSAGE_H__) -#error "Never include message.h directly; include Usb.h instead" -#else -#define __MESSAGE_H__ - -extern int UsbDEBUGlvl; - -void E_Notify(char const * msg, int lvl); -void E_Notify(uint8_t b, int lvl); -void E_NotifyStr(char const * msg, int lvl); -void E_Notifyc(char c, int lvl); - -#ifdef DEBUG_USB_HOST -#define Notify E_Notify -#define NotifyStr E_NotifyStr -#define Notifyc E_Notifyc -void NotifyFailGetDevDescr(uint8_t reason); -void NotifyFailSetDevTblEntry(uint8_t reason); -void NotifyFailGetConfDescr(uint8_t reason); -void NotifyFailSetConfDescr(uint8_t reason); -void NotifyFailGetDevDescr(void); -void NotifyFailSetDevTblEntry(void); -void NotifyFailGetConfDescr(void); -void NotifyFailSetConfDescr(void); -void NotifyFailUnknownDevice(uint16_t VID, uint16_t PID); -void NotifyFail(uint8_t rcode); -#else -#define Notify(...) ((void)0) -#define NotifyStr(...) ((void)0) -#define Notifyc(...) ((void)0) -#define NotifyFailGetDevDescr(...) ((void)0) -#define NotifyFailSetDevTblEntry(...) ((void)0) -#define NotifyFailGetConfDescr(...) ((void)0) -#define NotifyFailGetDevDescr(...) ((void)0) -#define NotifyFailSetDevTblEntry(...) ((void)0) -#define NotifyFailGetConfDescr(...) ((void)0) -#define NotifyFailSetConfDescr(...) ((void)0) -#define NotifyFailUnknownDevice(...) ((void)0) -#define NotifyFail(...) ((void)0) -#endif - -template -void ErrorMessage(uint8_t level, char const * msg, ERROR_TYPE rcode = 0) { -#ifdef DEBUG_USB_HOST - Notify(msg, level); - Notify(PSTR(": "), level); - D_PrintHex (rcode, level); - Notify(PSTR("\r\n"), level); -#endif -} - -template -void ErrorMessage(char const * msg, ERROR_TYPE rcode = 0) { -#ifdef DEBUG_USB_HOST - Notify(msg, 0x80); - Notify(PSTR(": "), 0x80); - D_PrintHex (rcode, 0x80); - Notify(PSTR("\r\n"), 0x80); -#endif -} - -#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(_usb_h_) || defined(__MESSAGE_H__) +#error "Never include message.h directly; include Usb.h instead" +#else +#define __MESSAGE_H__ + +extern int UsbDEBUGlvl; + +void E_Notify(char const * msg, int lvl); +void E_Notify(uint8_t b, int lvl); +void E_NotifyStr(char const * msg, int lvl); +void E_Notifyc(char c, int lvl); + +#ifdef DEBUG_USB_HOST +#define Notify E_Notify +#define NotifyStr E_NotifyStr +#define Notifyc E_Notifyc +void NotifyFailGetDevDescr(uint8_t reason); +void NotifyFailSetDevTblEntry(uint8_t reason); +void NotifyFailGetConfDescr(uint8_t reason); +void NotifyFailSetConfDescr(uint8_t reason); +void NotifyFailGetDevDescr(void); +void NotifyFailSetDevTblEntry(void); +void NotifyFailGetConfDescr(void); +void NotifyFailSetConfDescr(void); +void NotifyFailUnknownDevice(uint16_t VID, uint16_t PID); +void NotifyFail(uint8_t rcode); +#else +#define Notify(...) ((void)0) +#define NotifyStr(...) ((void)0) +#define Notifyc(...) ((void)0) +#define NotifyFailGetDevDescr(...) ((void)0) +#define NotifyFailSetDevTblEntry(...) ((void)0) +#define NotifyFailGetConfDescr(...) ((void)0) +#define NotifyFailGetDevDescr(...) ((void)0) +#define NotifyFailSetDevTblEntry(...) ((void)0) +#define NotifyFailGetConfDescr(...) ((void)0) +#define NotifyFailSetConfDescr(...) ((void)0) +#define NotifyFailUnknownDevice(...) ((void)0) +#define NotifyFail(...) ((void)0) +#endif + +template +void ErrorMessage(uint8_t level, char const * msg, ERROR_TYPE rcode = 0) { +#ifdef DEBUG_USB_HOST + Notify(msg, level); + Notify(PSTR(": "), level); + D_PrintHex (rcode, level); + Notify(PSTR("\r\n"), level); +#endif +} + +template +void ErrorMessage(char const * msg, ERROR_TYPE rcode = 0) { +#ifdef DEBUG_USB_HOST + Notify(msg, 0x80); + Notify(PSTR(": "), 0x80); + D_PrintHex (rcode, 0x80); + Notify(PSTR("\r\n"), 0x80); +#endif +} + +#endif // __MESSAGE_H__ diff --git a/parsetools.cpp b/parsetools.cpp index 02a7ee27..74a86105 100644 --- a/parsetools.cpp +++ b/parsetools.cpp @@ -1,67 +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 "Usb.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; -} +/* 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 "Usb.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 0e77de31..66e9531c 100644 --- a/parsetools.h +++ b/parsetools.h @@ -1,140 +1,140 @@ -/* 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(_usb_h_) || defined(__PARSETOOLS_H__) -#error "Never include parsetools.h directly; include Usb.h instead" -#else -#define __PARSETOOLS_H__ - -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__ +/* 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(_usb_h_) || defined(__PARSETOOLS_H__) +#error "Never include parsetools.h directly; include Usb.h instead" +#else +#define __PARSETOOLS_H__ + +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/settings.h b/settings.h index e408048d..33757495 100644 --- a/settings.h +++ b/settings.h @@ -136,4 +136,4 @@ e-mail : support@circuitsathome.com #include <../../../../hardware/pic32/libraries/SPI/SPI.h> // Hack to use the SPI library #endif -#endif /* SETTINGS_H */ +#endif /* SETTINGS_H */ diff --git a/usb_ch9.h b/usb_ch9.h index 7c85fefb..18f2d3e2 100644 --- a/usb_ch9.h +++ b/usb_ch9.h @@ -1,166 +1,166 @@ -/* 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(_usb_h_) || defined(_ch9_h_) -#error "Never include usb_ch9.h directly; include Usb.h instead" -#else - -/* USB chapter 9 structures */ -#define _ch9_h_ - -/* Misc.USB constants */ -#define DEV_DESCR_LEN 18 //device descriptor length -#define CONF_DESCR_LEN 9 //configuration descriptor length -#define INTR_DESCR_LEN 9 //interface descriptor length -#define EP_DESCR_LEN 7 //endpoint descriptor length - -/* Standard Device Requests */ - -#define USB_REQUEST_GET_STATUS 0 // Standard Device Request - GET STATUS -#define USB_REQUEST_CLEAR_FEATURE 1 // Standard Device Request - CLEAR FEATURE -#define USB_REQUEST_SET_FEATURE 3 // Standard Device Request - SET FEATURE -#define USB_REQUEST_SET_ADDRESS 5 // Standard Device Request - SET ADDRESS -#define USB_REQUEST_GET_DESCRIPTOR 6 // Standard Device Request - GET DESCRIPTOR -#define USB_REQUEST_SET_DESCRIPTOR 7 // Standard Device Request - SET DESCRIPTOR -#define USB_REQUEST_GET_CONFIGURATION 8 // Standard Device Request - GET CONFIGURATION -#define USB_REQUEST_SET_CONFIGURATION 9 // Standard Device Request - SET CONFIGURATION -#define USB_REQUEST_GET_INTERFACE 10 // Standard Device Request - GET INTERFACE -#define USB_REQUEST_SET_INTERFACE 11 // Standard Device Request - SET INTERFACE -#define USB_REQUEST_SYNCH_FRAME 12 // Standard Device Request - SYNCH FRAME - -#define USB_FEATURE_ENDPOINT_HALT 0 // CLEAR/SET FEATURE - Endpoint Halt -#define USB_FEATURE_DEVICE_REMOTE_WAKEUP 1 // CLEAR/SET FEATURE - Device remote wake-up -#define USB_FEATURE_TEST_MODE 2 // CLEAR/SET FEATURE - Test mode - -/* Setup Data Constants */ - -#define USB_SETUP_HOST_TO_DEVICE 0x00 // Device Request bmRequestType transfer direction - host to device transfer -#define USB_SETUP_DEVICE_TO_HOST 0x80 // Device Request bmRequestType transfer direction - device to host transfer -#define USB_SETUP_TYPE_STANDARD 0x00 // Device Request bmRequestType type - standard -#define USB_SETUP_TYPE_CLASS 0x20 // Device Request bmRequestType type - class -#define USB_SETUP_TYPE_VENDOR 0x40 // Device Request bmRequestType type - vendor -#define USB_SETUP_RECIPIENT_DEVICE 0x00 // Device Request bmRequestType recipient - device -#define USB_SETUP_RECIPIENT_INTERFACE 0x01 // Device Request bmRequestType recipient - interface -#define USB_SETUP_RECIPIENT_ENDPOINT 0x02 // Device Request bmRequestType recipient - endpoint -#define USB_SETUP_RECIPIENT_OTHER 0x03 // Device Request bmRequestType recipient - other - -/* USB descriptors */ - -#define USB_DESCRIPTOR_DEVICE 0x01 // bDescriptorType for a Device Descriptor. -#define USB_DESCRIPTOR_CONFIGURATION 0x02 // bDescriptorType for a Configuration Descriptor. -#define USB_DESCRIPTOR_STRING 0x03 // bDescriptorType for a String Descriptor. -#define USB_DESCRIPTOR_INTERFACE 0x04 // bDescriptorType for an Interface Descriptor. -#define USB_DESCRIPTOR_ENDPOINT 0x05 // bDescriptorType for an Endpoint Descriptor. -#define USB_DESCRIPTOR_DEVICE_QUALIFIER 0x06 // bDescriptorType for a Device Qualifier. -#define USB_DESCRIPTOR_OTHER_SPEED 0x07 // bDescriptorType for a Other Speed Configuration. -#define USB_DESCRIPTOR_INTERFACE_POWER 0x08 // bDescriptorType for Interface Power. -#define USB_DESCRIPTOR_OTG 0x09 // bDescriptorType for an OTG Descriptor. - -#define HID_DESCRIPTOR_HID 0x21 - - - -/* OTG SET FEATURE Constants */ -#define OTG_FEATURE_B_HNP_ENABLE 3 // SET FEATURE OTG - Enable B device to perform HNP -#define OTG_FEATURE_A_HNP_SUPPORT 4 // SET FEATURE OTG - A device supports HNP -#define OTG_FEATURE_A_ALT_HNP_SUPPORT 5 // SET FEATURE OTG - Another port on the A device supports HNP - -/* USB Endpoint Transfer Types */ -#define USB_TRANSFER_TYPE_CONTROL 0x00 // Endpoint is a control endpoint. -#define USB_TRANSFER_TYPE_ISOCHRONOUS 0x01 // Endpoint is an isochronous endpoint. -#define USB_TRANSFER_TYPE_BULK 0x02 // Endpoint is a bulk endpoint. -#define USB_TRANSFER_TYPE_INTERRUPT 0x03 // Endpoint is an interrupt endpoint. -#define bmUSB_TRANSFER_TYPE 0x03 // bit mask to separate transfer type from ISO attributes - - -/* Standard Feature Selectors for CLEAR_FEATURE Requests */ -#define USB_FEATURE_ENDPOINT_STALL 0 // Endpoint recipient -#define USB_FEATURE_DEVICE_REMOTE_WAKEUP 1 // Device recipient -#define USB_FEATURE_TEST_MODE 2 // Device recipient - -/* descriptor data structures */ - -/* 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. -} __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. -} __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. -} __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. -} __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 -} __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; - -#endif // _ch9_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(_usb_h_) || defined(_ch9_h_) +#error "Never include usb_ch9.h directly; include Usb.h instead" +#else + +/* USB chapter 9 structures */ +#define _ch9_h_ + +/* Misc.USB constants */ +#define DEV_DESCR_LEN 18 //device descriptor length +#define CONF_DESCR_LEN 9 //configuration descriptor length +#define INTR_DESCR_LEN 9 //interface descriptor length +#define EP_DESCR_LEN 7 //endpoint descriptor length + +/* Standard Device Requests */ + +#define USB_REQUEST_GET_STATUS 0 // Standard Device Request - GET STATUS +#define USB_REQUEST_CLEAR_FEATURE 1 // Standard Device Request - CLEAR FEATURE +#define USB_REQUEST_SET_FEATURE 3 // Standard Device Request - SET FEATURE +#define USB_REQUEST_SET_ADDRESS 5 // Standard Device Request - SET ADDRESS +#define USB_REQUEST_GET_DESCRIPTOR 6 // Standard Device Request - GET DESCRIPTOR +#define USB_REQUEST_SET_DESCRIPTOR 7 // Standard Device Request - SET DESCRIPTOR +#define USB_REQUEST_GET_CONFIGURATION 8 // Standard Device Request - GET CONFIGURATION +#define USB_REQUEST_SET_CONFIGURATION 9 // Standard Device Request - SET CONFIGURATION +#define USB_REQUEST_GET_INTERFACE 10 // Standard Device Request - GET INTERFACE +#define USB_REQUEST_SET_INTERFACE 11 // Standard Device Request - SET INTERFACE +#define USB_REQUEST_SYNCH_FRAME 12 // Standard Device Request - SYNCH FRAME + +#define USB_FEATURE_ENDPOINT_HALT 0 // CLEAR/SET FEATURE - Endpoint Halt +#define USB_FEATURE_DEVICE_REMOTE_WAKEUP 1 // CLEAR/SET FEATURE - Device remote wake-up +#define USB_FEATURE_TEST_MODE 2 // CLEAR/SET FEATURE - Test mode + +/* Setup Data Constants */ + +#define USB_SETUP_HOST_TO_DEVICE 0x00 // Device Request bmRequestType transfer direction - host to device transfer +#define USB_SETUP_DEVICE_TO_HOST 0x80 // Device Request bmRequestType transfer direction - device to host transfer +#define USB_SETUP_TYPE_STANDARD 0x00 // Device Request bmRequestType type - standard +#define USB_SETUP_TYPE_CLASS 0x20 // Device Request bmRequestType type - class +#define USB_SETUP_TYPE_VENDOR 0x40 // Device Request bmRequestType type - vendor +#define USB_SETUP_RECIPIENT_DEVICE 0x00 // Device Request bmRequestType recipient - device +#define USB_SETUP_RECIPIENT_INTERFACE 0x01 // Device Request bmRequestType recipient - interface +#define USB_SETUP_RECIPIENT_ENDPOINT 0x02 // Device Request bmRequestType recipient - endpoint +#define USB_SETUP_RECIPIENT_OTHER 0x03 // Device Request bmRequestType recipient - other + +/* USB descriptors */ + +#define USB_DESCRIPTOR_DEVICE 0x01 // bDescriptorType for a Device Descriptor. +#define USB_DESCRIPTOR_CONFIGURATION 0x02 // bDescriptorType for a Configuration Descriptor. +#define USB_DESCRIPTOR_STRING 0x03 // bDescriptorType for a String Descriptor. +#define USB_DESCRIPTOR_INTERFACE 0x04 // bDescriptorType for an Interface Descriptor. +#define USB_DESCRIPTOR_ENDPOINT 0x05 // bDescriptorType for an Endpoint Descriptor. +#define USB_DESCRIPTOR_DEVICE_QUALIFIER 0x06 // bDescriptorType for a Device Qualifier. +#define USB_DESCRIPTOR_OTHER_SPEED 0x07 // bDescriptorType for a Other Speed Configuration. +#define USB_DESCRIPTOR_INTERFACE_POWER 0x08 // bDescriptorType for Interface Power. +#define USB_DESCRIPTOR_OTG 0x09 // bDescriptorType for an OTG Descriptor. + +#define HID_DESCRIPTOR_HID 0x21 + + + +/* OTG SET FEATURE Constants */ +#define OTG_FEATURE_B_HNP_ENABLE 3 // SET FEATURE OTG - Enable B device to perform HNP +#define OTG_FEATURE_A_HNP_SUPPORT 4 // SET FEATURE OTG - A device supports HNP +#define OTG_FEATURE_A_ALT_HNP_SUPPORT 5 // SET FEATURE OTG - Another port on the A device supports HNP + +/* USB Endpoint Transfer Types */ +#define USB_TRANSFER_TYPE_CONTROL 0x00 // Endpoint is a control endpoint. +#define USB_TRANSFER_TYPE_ISOCHRONOUS 0x01 // Endpoint is an isochronous endpoint. +#define USB_TRANSFER_TYPE_BULK 0x02 // Endpoint is a bulk endpoint. +#define USB_TRANSFER_TYPE_INTERRUPT 0x03 // Endpoint is an interrupt endpoint. +#define bmUSB_TRANSFER_TYPE 0x03 // bit mask to separate transfer type from ISO attributes + + +/* Standard Feature Selectors for CLEAR_FEATURE Requests */ +#define USB_FEATURE_ENDPOINT_STALL 0 // Endpoint recipient +#define USB_FEATURE_DEVICE_REMOTE_WAKEUP 1 // Device recipient +#define USB_FEATURE_TEST_MODE 2 // Device recipient + +/* descriptor data structures */ + +/* 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. +} __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. +} __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. +} __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. +} __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 +} __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; + +#endif // _ch9_h_ diff --git a/usbhost.h b/usbhost.h index 3901094f..4e6154da 100644 --- a/usbhost.h +++ b/usbhost.h @@ -1,527 +1,527 @@ -/* 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 - */ -/* MAX3421E-based USB Host Library header file */ - - -#if !defined(_usb_h_) || defined(_USBHOST_H_) -#error "Never include usbhost.h directly; include Usb.h instead" -#else -#define _USBHOST_H_ - -#if USING_SPI4TEENSY3 -#include -#include -#endif - -/* SPI initialization */ -template< typename SPI_CLK, typename SPI_MOSI, typename SPI_MISO, typename SPI_SS > class SPi { -public: -#if SPI_HAS_TRANSACTION - static void init() { - SPI.begin(); // The SPI library with transaction will take care of setting up the pins - settings is set in beginTransaction() - } -#elif USING_SPI4TEENSY3 - static void init() { - // spi4teensy3 inits everything for us, except /SS - // CLK, MOSI and MISO are hard coded for now. - // spi4teensy3::init(0,0,0); // full speed, cpol 0, cpha 0 - spi4teensy3::init(); // full speed, cpol 0, cpha 0 - SPI_SS::SetDirWrite(); - SPI_SS::Set(); - } -#elif !defined(SPDR) - static void init() { - SPI_SS::SetDirWrite(); - SPI_SS::Set(); - SPI.begin(); -#if defined(__MIPSEL__) - SPI.setClockDivider(1); -#elif defined(__ARDUINO_X86__) - SPI.setClockDivider(SPI_CLOCK_DIV2); // This will set the SPI frequency to 8MHz - it could be higher, but it is not supported in the API -#else - SPI.setClockDivider(4); // Set speed to 84MHz/4=21MHz - the MAX3421E can handle up to 26MHz -#endif - } -#elif defined(RBL_NRF51822) - static void init() { - SPI_SS::SetDirWrite(); - SPI_SS::Set(); - SPI.begin(); - // SPI.setFrequency(SPI_FREQUENCY_8M); - } -#else - static void init() { - //uint8_t tmp; - SPI_CLK::SetDirWrite(); - SPI_MOSI::SetDirWrite(); - SPI_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; // 0x01 - /**/ - //tmp = SPSR; - //tmp = SPDR; - } -#endif -}; - -/* SPI pin definitions. see avrpins.h */ -#if defined(__AVR_ATmega1280__) || (__AVR_ATmega2560__) || defined(__AVR_ATmega32U4__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__) -typedef SPi< Pb1, Pb2, Pb3, Pb0 > spi; -#elif defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__) -typedef SPi< Pb5, Pb3, Pb4, Pb2 > spi; -#elif defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) -typedef SPi< Pb7, Pb5, Pb6, Pb4 > spi; -#elif (defined(CORE_TEENSY) && (defined(__MK20DX128__) || defined(__MK20DX256__))) || defined(__ARDUINO_X86__) -typedef SPi< P13, P11, P12, P10 > spi; -#elif defined(ARDUINO_SAM_DUE) && defined(__SAM3X8E__) -typedef SPi< P76, P75, P74, P10 > spi; -#elif defined(RBL_NRF51822) -typedef SPi< P16, P18, P17, P10 > spi; -#elif defined(__MIPSEL__) -typedef SPi< P13, P11, P12, P10 > spi; -#else -#error "No SPI entry in usbhost.h" -#endif - -typedef enum { - vbus_on = 0, - vbus_off = GPX_VBDET -} VBUS_t; - -template< typename SPI_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(); - int8_t Init(int mseconds); - - void vbusPower(VBUS_t state) { - regWr(rPINCTL, (bmFDUPSPI | bmINTLEVEL | state)); - } - - uint8_t getVbusState(void) { - return vbusState; - }; - void busprobe(); - uint8_t GpxHandler(); - uint8_t IntHandler(); - uint8_t Task(); -}; - -template< typename SPI_SS, typename INTR > - uint8_t MAX3421e< SPI_SS, INTR >::vbusState = 0; - -/* constructor */ -template< typename SPI_SS, typename INTR > -MAX3421e< SPI_SS, INTR >::MAX3421e() { - // Leaving ADK hardware setup in here, for now. This really belongs with the other parts. -#ifdef BOARD_MEGA_ADK - // For Mega ADK, which has a Max3421e on-board, set MAX_RESET to output mode, and then set it to HIGH - P55::SetDirWrite(); - P55::Set(); -#endif -}; - -/* write single byte into MAX3421 register */ -template< typename SPI_SS, typename INTR > -void MAX3421e< SPI_SS, INTR >::regWr(uint8_t reg, uint8_t data) { - XMEM_ACQUIRE_SPI(); -#if SPI_HAS_TRANSACTION - SPI.beginTransaction(SPISettings(26000000, MSBFIRST, SPI_MODE0)); // The MAX3421E can handle up to 26MHz, use MSB First and SPI mode 0 -#endif - SPI_SS::Clear(); - -#if SPI_HAS_TRANSACTION - uint8_t c[2]; - c[0] = reg | 0x02; - c[1] = data; - SPI.transfer(c, 2); -#elif USING_SPI4TEENSY3 - uint8_t c[2]; - c[0] = reg | 0x02; - c[1] = data; - spi4teensy3::send(c, 2); -#elif !defined(SPDR) - SPI.transfer(reg | 0x02); - SPI.transfer(data); -#else - SPDR = (reg | 0x02); - while(!(SPSR & (1 << SPIF))); - SPDR = data; - while(!(SPSR & (1 << SPIF))); -#endif - - SPI_SS::Set(); -#if SPI_HAS_TRANSACTION - SPI.endTransaction(); -#endif - XMEM_RELEASE_SPI(); - return; -}; -/* multiple-byte write */ - -/* returns a pointer to memory position after last written */ -template< typename SPI_SS, typename INTR > -uint8_t* MAX3421e< SPI_SS, INTR >::bytesWr(uint8_t reg, uint8_t nbytes, uint8_t* data_p) { - XMEM_ACQUIRE_SPI(); -#if SPI_HAS_TRANSACTION - SPI.beginTransaction(SPISettings(26000000, MSBFIRST, SPI_MODE0)); // The MAX3421E can handle up to 26MHz, use MSB First and SPI mode 0 -#endif - SPI_SS::Clear(); - -#if SPI_HAS_TRANSACTION - SPI.transfer(reg | 0x02); - SPI.transfer(data_p, nbytes); - data_p += nbytes; -#elif USING_SPI4TEENSY3 - spi4teensy3::send(reg | 0x02); - spi4teensy3::send(data_p, nbytes); - data_p += nbytes; -#elif defined(__ARDUINO_X86__) - SPI.transfer(reg | 0x02); - SPI.transferBuffer(data_p, NULL, nbytes); - data_p += nbytes; -#elif !defined(SPDR) - SPI.transfer(reg | 0x02); - while(nbytes) { - SPI.transfer(*data_p); - nbytes--; - data_p++; // advance data pointer - } -#else - 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 - nbytes--; - data_p++; // advance data pointer - } - while(!(SPSR & (1 << SPIF))); -#endif - - SPI_SS::Set(); -#if SPI_HAS_TRANSACTION - SPI.endTransaction(); -#endif - XMEM_RELEASE_SPI(); - 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 SPI_SS, typename INTR > -void MAX3421e< SPI_SS, INTR >::gpioWr(uint8_t data) { - regWr(rIOPINS1, data); - data >>= 4; - regWr(rIOPINS2, data); - return; -} - -/* single host register read */ -template< typename SPI_SS, typename INTR > -uint8_t MAX3421e< SPI_SS, INTR >::regRd(uint8_t reg) { - XMEM_ACQUIRE_SPI(); -#if SPI_HAS_TRANSACTION - SPI.beginTransaction(SPISettings(26000000, MSBFIRST, SPI_MODE0)); // The MAX3421E can handle up to 26MHz, use MSB First and SPI mode 0 -#endif - SPI_SS::Clear(); - -#if !defined(SPDR) || SPI_HAS_TRANSACTION - SPI.transfer(reg); - uint8_t rv = SPI.transfer(0); // Send empty byte - SPI_SS::Set(); -#elif USING_SPI4TEENSY3 - spi4teensy3::send(reg); - uint8_t rv = spi4teensy3::receive(); - SPI_SS::Set(); -#else - SPDR = reg; - while(!(SPSR & (1 << SPIF))); - SPDR = 0; // Send empty byte - while(!(SPSR & (1 << SPIF))); - SPI_SS::Set(); - uint8_t rv = SPDR; -#endif - -#if SPI_HAS_TRANSACTION - SPI.endTransaction(); -#endif - XMEM_RELEASE_SPI(); - return (rv); -} -/* multiple-byte register read */ - -/* returns a pointer to a memory position after last read */ -template< typename SPI_SS, typename INTR > -uint8_t* MAX3421e< SPI_SS, INTR >::bytesRd(uint8_t reg, uint8_t nbytes, uint8_t* data_p) { - XMEM_ACQUIRE_SPI(); -#if SPI_HAS_TRANSACTION - SPI.beginTransaction(SPISettings(26000000, MSBFIRST, SPI_MODE0)); // The MAX3421E can handle up to 26MHz, use MSB First and SPI mode 0 -#endif - SPI_SS::Clear(); - -#if SPI_HAS_TRANSACTION - SPI.transfer(reg); - memset(data_p, 0, nbytes); // Make sure we send out empty bytes - SPI.transfer(data_p, nbytes); - data_p += nbytes; -#elif USING_SPI4TEENSY3 - spi4teensy3::send(reg); - spi4teensy3::receive(data_p, nbytes); - data_p += nbytes; -#elif defined(__ARDUINO_X86__) - SPI.transfer(reg); - SPI.transferBuffer(NULL, data_p, nbytes); - data_p += nbytes; -#elif !defined(SPDR) - SPI.transfer(reg); - while(nbytes) { - *data_p++ = SPI.transfer(0); - nbytes--; - } -#else - SPDR = reg; - while(!(SPSR & (1 << SPIF))); //wait - while(nbytes) { - SPDR = 0; // Send empty byte - nbytes--; - while(!(SPSR & (1 << SPIF))); -#if 0 - { - *data_p = SPDR; - printf("%2.2x ", *data_p); - } - data_p++; - } - printf("\r\n"); -#else - *data_p++ = SPDR; - } -#endif -#endif - - SPI_SS::Set(); -#if SPI_HAS_TRANSACTION - SPI.endTransaction(); -#endif - XMEM_RELEASE_SPI(); - return ( data_p); -} -/* GPIO read. See gpioWr for explanation */ - -/* GPIN pins are in high nibbles of IOPINS1, IOPINS2 */ -template< typename SPI_SS, typename INTR > -uint8_t MAX3421e< SPI_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 SPI_SS, typename INTR > -uint16_t MAX3421e< SPI_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 SPI_SS, typename INTR > -int8_t MAX3421e< SPI_SS, INTR >::Init() { - XMEM_ACQUIRE_SPI(); - // Moved here. - // you really should not init hardware in the constructor when it involves locks. - // Also avoids the vbus flicker issue confusing some devices. - /* pin and peripheral setup */ - SPI_SS::SetDirWrite(); - SPI_SS::Set(); - spi::init(); - INTR::SetDirRead(); - XMEM_RELEASE_SPI(); - /* MAX3421E - full-duplex SPI, level interrupt */ - // GPX pin on. Moved here, otherwise we flicker the vbus. - regWr(rPINCTL, (bmFDUPSPI | bmINTLEVEL)); - - 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 - - /* check if device is connected */ - regWr(rHCTL, bmSAMPLEBUS); // sample USB bus - 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); -} - -/* initialize MAX3421E. Set Host mode, pullups, and stuff. Returns 0 if success, -1 if not */ -template< typename SPI_SS, typename INTR > -int8_t MAX3421e< SPI_SS, INTR >::Init(int mseconds) { - XMEM_ACQUIRE_SPI(); - // Moved here. - // you really should not init hardware in the constructor when it involves locks. - // Also avoids the vbus flicker issue confusing some devices. - /* pin and peripheral setup */ - SPI_SS::SetDirWrite(); - SPI_SS::Set(); - spi::init(); - INTR::SetDirRead(); - XMEM_RELEASE_SPI(); - /* MAX3421E - full-duplex SPI, level interrupt, vbus off */ - regWr(rPINCTL, (bmFDUPSPI | bmINTLEVEL | GPX_VBDET)); - - if(reset() == 0) { //OSCOKIRQ hasn't asserted in time - return ( -1); - } - - // Delay a minimum of 1 second to ensure any capacitors are drained. - // 1 second is required to make sure we do not smoke a Microdrive! - if(mseconds < 1000) mseconds = 1000; - delay(mseconds); - - regWr(rMODE, bmDPPULLDN | bmDMPULLDN | bmHOST); // set pull-downs, Host - - regWr(rHIEN, bmCONDETIE | bmFRAMEIE); //connection detection - - /* check if device is connected */ - regWr(rHCTL, bmSAMPLEBUS); // sample USB bus - 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 - - // GPX pin on. This is done here so that busprobe will fail if we have a switch connected. - regWr(rPINCTL, (bmFDUPSPI | bmINTLEVEL)); - - return ( 0); -} - -/* probe bus to determine device presence and speed and switch host to this speed */ -template< typename SPI_SS, typename INTR > -void MAX3421e< SPI_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 SPI_SS, typename INTR > -uint8_t MAX3421e< SPI_SS, INTR >::Task(void) { - uint8_t rcode = 0; - uint8_t pinvalue; - //USB_HOST_SERIAL.print("Vbus state: "); - //USB_HOST_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 SPI_SS, typename INTR > -uint8_t MAX3421e< SPI_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 SPI_SS, typename INTR > -//uint8_t MAX3421e< SPI_SS, INTR >::GpxHandler() -//{ -// uint8_t GPINIRQ = regRd( rGPINIRQ ); //read GPIN IRQ register -//// if( GPINIRQ & bmGPINIRQ7 ) { //vbus overload -//// vbusPwr( OFF ); //attempt powercycle -//// delay( 1000 ); -//// vbusPwr( ON ); -//// regWr( rGPINIRQ, bmGPINIRQ7 ); -//// } -// return( GPINIRQ ); -//} - -#endif //_USBHOST_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 + */ +/* MAX3421E-based USB Host Library header file */ + + +#if !defined(_usb_h_) || defined(_USBHOST_H_) +#error "Never include usbhost.h directly; include Usb.h instead" +#else +#define _USBHOST_H_ + +#if USING_SPI4TEENSY3 +#include +#include +#endif + +/* SPI initialization */ +template< typename SPI_CLK, typename SPI_MOSI, typename SPI_MISO, typename SPI_SS > class SPi { +public: +#if SPI_HAS_TRANSACTION + static void init() { + SPI.begin(); // The SPI library with transaction will take care of setting up the pins - settings is set in beginTransaction() + } +#elif USING_SPI4TEENSY3 + static void init() { + // spi4teensy3 inits everything for us, except /SS + // CLK, MOSI and MISO are hard coded for now. + // spi4teensy3::init(0,0,0); // full speed, cpol 0, cpha 0 + spi4teensy3::init(); // full speed, cpol 0, cpha 0 + SPI_SS::SetDirWrite(); + SPI_SS::Set(); + } +#elif !defined(SPDR) + static void init() { + SPI_SS::SetDirWrite(); + SPI_SS::Set(); + SPI.begin(); +#if defined(__MIPSEL__) + SPI.setClockDivider(1); +#elif defined(__ARDUINO_X86__) + SPI.setClockDivider(SPI_CLOCK_DIV2); // This will set the SPI frequency to 8MHz - it could be higher, but it is not supported in the API +#else + SPI.setClockDivider(4); // Set speed to 84MHz/4=21MHz - the MAX3421E can handle up to 26MHz +#endif + } +#elif defined(RBL_NRF51822) + static void init() { + SPI_SS::SetDirWrite(); + SPI_SS::Set(); + SPI.begin(); + // SPI.setFrequency(SPI_FREQUENCY_8M); + } +#else + static void init() { + //uint8_t tmp; + SPI_CLK::SetDirWrite(); + SPI_MOSI::SetDirWrite(); + SPI_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; // 0x01 + /**/ + //tmp = SPSR; + //tmp = SPDR; + } +#endif +}; + +/* SPI pin definitions. see avrpins.h */ +#if defined(__AVR_ATmega1280__) || (__AVR_ATmega2560__) || defined(__AVR_ATmega32U4__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__) +typedef SPi< Pb1, Pb2, Pb3, Pb0 > spi; +#elif defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__) +typedef SPi< Pb5, Pb3, Pb4, Pb2 > spi; +#elif defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) +typedef SPi< Pb7, Pb5, Pb6, Pb4 > spi; +#elif (defined(CORE_TEENSY) && (defined(__MK20DX128__) || defined(__MK20DX256__))) || defined(__ARDUINO_X86__) +typedef SPi< P13, P11, P12, P10 > spi; +#elif defined(ARDUINO_SAM_DUE) && defined(__SAM3X8E__) +typedef SPi< P76, P75, P74, P10 > spi; +#elif defined(RBL_NRF51822) +typedef SPi< P16, P18, P17, P10 > spi; +#elif defined(__MIPSEL__) +typedef SPi< P13, P11, P12, P10 > spi; +#else +#error "No SPI entry in usbhost.h" +#endif + +typedef enum { + vbus_on = 0, + vbus_off = GPX_VBDET +} VBUS_t; + +template< typename SPI_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(); + int8_t Init(int mseconds); + + void vbusPower(VBUS_t state) { + regWr(rPINCTL, (bmFDUPSPI | bmINTLEVEL | state)); + } + + uint8_t getVbusState(void) { + return vbusState; + }; + void busprobe(); + uint8_t GpxHandler(); + uint8_t IntHandler(); + uint8_t Task(); +}; + +template< typename SPI_SS, typename INTR > + uint8_t MAX3421e< SPI_SS, INTR >::vbusState = 0; + +/* constructor */ +template< typename SPI_SS, typename INTR > +MAX3421e< SPI_SS, INTR >::MAX3421e() { + // Leaving ADK hardware setup in here, for now. This really belongs with the other parts. +#ifdef BOARD_MEGA_ADK + // For Mega ADK, which has a Max3421e on-board, set MAX_RESET to output mode, and then set it to HIGH + P55::SetDirWrite(); + P55::Set(); +#endif +}; + +/* write single byte into MAX3421 register */ +template< typename SPI_SS, typename INTR > +void MAX3421e< SPI_SS, INTR >::regWr(uint8_t reg, uint8_t data) { + XMEM_ACQUIRE_SPI(); +#if SPI_HAS_TRANSACTION + SPI.beginTransaction(SPISettings(26000000, MSBFIRST, SPI_MODE0)); // The MAX3421E can handle up to 26MHz, use MSB First and SPI mode 0 +#endif + SPI_SS::Clear(); + +#if SPI_HAS_TRANSACTION + uint8_t c[2]; + c[0] = reg | 0x02; + c[1] = data; + SPI.transfer(c, 2); +#elif USING_SPI4TEENSY3 + uint8_t c[2]; + c[0] = reg | 0x02; + c[1] = data; + spi4teensy3::send(c, 2); +#elif !defined(SPDR) + SPI.transfer(reg | 0x02); + SPI.transfer(data); +#else + SPDR = (reg | 0x02); + while(!(SPSR & (1 << SPIF))); + SPDR = data; + while(!(SPSR & (1 << SPIF))); +#endif + + SPI_SS::Set(); +#if SPI_HAS_TRANSACTION + SPI.endTransaction(); +#endif + XMEM_RELEASE_SPI(); + return; +}; +/* multiple-byte write */ + +/* returns a pointer to memory position after last written */ +template< typename SPI_SS, typename INTR > +uint8_t* MAX3421e< SPI_SS, INTR >::bytesWr(uint8_t reg, uint8_t nbytes, uint8_t* data_p) { + XMEM_ACQUIRE_SPI(); +#if SPI_HAS_TRANSACTION + SPI.beginTransaction(SPISettings(26000000, MSBFIRST, SPI_MODE0)); // The MAX3421E can handle up to 26MHz, use MSB First and SPI mode 0 +#endif + SPI_SS::Clear(); + +#if SPI_HAS_TRANSACTION + SPI.transfer(reg | 0x02); + SPI.transfer(data_p, nbytes); + data_p += nbytes; +#elif USING_SPI4TEENSY3 + spi4teensy3::send(reg | 0x02); + spi4teensy3::send(data_p, nbytes); + data_p += nbytes; +#elif defined(__ARDUINO_X86__) + SPI.transfer(reg | 0x02); + SPI.transferBuffer(data_p, NULL, nbytes); + data_p += nbytes; +#elif !defined(SPDR) + SPI.transfer(reg | 0x02); + while(nbytes) { + SPI.transfer(*data_p); + nbytes--; + data_p++; // advance data pointer + } +#else + 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 + nbytes--; + data_p++; // advance data pointer + } + while(!(SPSR & (1 << SPIF))); +#endif + + SPI_SS::Set(); +#if SPI_HAS_TRANSACTION + SPI.endTransaction(); +#endif + XMEM_RELEASE_SPI(); + 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 SPI_SS, typename INTR > +void MAX3421e< SPI_SS, INTR >::gpioWr(uint8_t data) { + regWr(rIOPINS1, data); + data >>= 4; + regWr(rIOPINS2, data); + return; +} + +/* single host register read */ +template< typename SPI_SS, typename INTR > +uint8_t MAX3421e< SPI_SS, INTR >::regRd(uint8_t reg) { + XMEM_ACQUIRE_SPI(); +#if SPI_HAS_TRANSACTION + SPI.beginTransaction(SPISettings(26000000, MSBFIRST, SPI_MODE0)); // The MAX3421E can handle up to 26MHz, use MSB First and SPI mode 0 +#endif + SPI_SS::Clear(); + +#if !defined(SPDR) || SPI_HAS_TRANSACTION + SPI.transfer(reg); + uint8_t rv = SPI.transfer(0); // Send empty byte + SPI_SS::Set(); +#elif USING_SPI4TEENSY3 + spi4teensy3::send(reg); + uint8_t rv = spi4teensy3::receive(); + SPI_SS::Set(); +#else + SPDR = reg; + while(!(SPSR & (1 << SPIF))); + SPDR = 0; // Send empty byte + while(!(SPSR & (1 << SPIF))); + SPI_SS::Set(); + uint8_t rv = SPDR; +#endif + +#if SPI_HAS_TRANSACTION + SPI.endTransaction(); +#endif + XMEM_RELEASE_SPI(); + return (rv); +} +/* multiple-byte register read */ + +/* returns a pointer to a memory position after last read */ +template< typename SPI_SS, typename INTR > +uint8_t* MAX3421e< SPI_SS, INTR >::bytesRd(uint8_t reg, uint8_t nbytes, uint8_t* data_p) { + XMEM_ACQUIRE_SPI(); +#if SPI_HAS_TRANSACTION + SPI.beginTransaction(SPISettings(26000000, MSBFIRST, SPI_MODE0)); // The MAX3421E can handle up to 26MHz, use MSB First and SPI mode 0 +#endif + SPI_SS::Clear(); + +#if SPI_HAS_TRANSACTION + SPI.transfer(reg); + memset(data_p, 0, nbytes); // Make sure we send out empty bytes + SPI.transfer(data_p, nbytes); + data_p += nbytes; +#elif USING_SPI4TEENSY3 + spi4teensy3::send(reg); + spi4teensy3::receive(data_p, nbytes); + data_p += nbytes; +#elif defined(__ARDUINO_X86__) + SPI.transfer(reg); + SPI.transferBuffer(NULL, data_p, nbytes); + data_p += nbytes; +#elif !defined(SPDR) + SPI.transfer(reg); + while(nbytes) { + *data_p++ = SPI.transfer(0); + nbytes--; + } +#else + SPDR = reg; + while(!(SPSR & (1 << SPIF))); //wait + while(nbytes) { + SPDR = 0; // Send empty byte + nbytes--; + while(!(SPSR & (1 << SPIF))); +#if 0 + { + *data_p = SPDR; + printf("%2.2x ", *data_p); + } + data_p++; + } + printf("\r\n"); +#else + *data_p++ = SPDR; + } +#endif +#endif + + SPI_SS::Set(); +#if SPI_HAS_TRANSACTION + SPI.endTransaction(); +#endif + XMEM_RELEASE_SPI(); + return ( data_p); +} +/* GPIO read. See gpioWr for explanation */ + +/* GPIN pins are in high nibbles of IOPINS1, IOPINS2 */ +template< typename SPI_SS, typename INTR > +uint8_t MAX3421e< SPI_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 SPI_SS, typename INTR > +uint16_t MAX3421e< SPI_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 SPI_SS, typename INTR > +int8_t MAX3421e< SPI_SS, INTR >::Init() { + XMEM_ACQUIRE_SPI(); + // Moved here. + // you really should not init hardware in the constructor when it involves locks. + // Also avoids the vbus flicker issue confusing some devices. + /* pin and peripheral setup */ + SPI_SS::SetDirWrite(); + SPI_SS::Set(); + spi::init(); + INTR::SetDirRead(); + XMEM_RELEASE_SPI(); + /* MAX3421E - full-duplex SPI, level interrupt */ + // GPX pin on. Moved here, otherwise we flicker the vbus. + regWr(rPINCTL, (bmFDUPSPI | bmINTLEVEL)); + + 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 + + /* check if device is connected */ + regWr(rHCTL, bmSAMPLEBUS); // sample USB bus + 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); +} + +/* initialize MAX3421E. Set Host mode, pullups, and stuff. Returns 0 if success, -1 if not */ +template< typename SPI_SS, typename INTR > +int8_t MAX3421e< SPI_SS, INTR >::Init(int mseconds) { + XMEM_ACQUIRE_SPI(); + // Moved here. + // you really should not init hardware in the constructor when it involves locks. + // Also avoids the vbus flicker issue confusing some devices. + /* pin and peripheral setup */ + SPI_SS::SetDirWrite(); + SPI_SS::Set(); + spi::init(); + INTR::SetDirRead(); + XMEM_RELEASE_SPI(); + /* MAX3421E - full-duplex SPI, level interrupt, vbus off */ + regWr(rPINCTL, (bmFDUPSPI | bmINTLEVEL | GPX_VBDET)); + + if(reset() == 0) { //OSCOKIRQ hasn't asserted in time + return ( -1); + } + + // Delay a minimum of 1 second to ensure any capacitors are drained. + // 1 second is required to make sure we do not smoke a Microdrive! + if(mseconds < 1000) mseconds = 1000; + delay(mseconds); + + regWr(rMODE, bmDPPULLDN | bmDMPULLDN | bmHOST); // set pull-downs, Host + + regWr(rHIEN, bmCONDETIE | bmFRAMEIE); //connection detection + + /* check if device is connected */ + regWr(rHCTL, bmSAMPLEBUS); // sample USB bus + 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 + + // GPX pin on. This is done here so that busprobe will fail if we have a switch connected. + regWr(rPINCTL, (bmFDUPSPI | bmINTLEVEL)); + + return ( 0); +} + +/* probe bus to determine device presence and speed and switch host to this speed */ +template< typename SPI_SS, typename INTR > +void MAX3421e< SPI_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 SPI_SS, typename INTR > +uint8_t MAX3421e< SPI_SS, INTR >::Task(void) { + uint8_t rcode = 0; + uint8_t pinvalue; + //USB_HOST_SERIAL.print("Vbus state: "); + //USB_HOST_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 SPI_SS, typename INTR > +uint8_t MAX3421e< SPI_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 SPI_SS, typename INTR > +//uint8_t MAX3421e< SPI_SS, INTR >::GpxHandler() +//{ +// uint8_t GPINIRQ = regRd( rGPINIRQ ); //read GPIN IRQ register +//// if( GPINIRQ & bmGPINIRQ7 ) { //vbus overload +//// vbusPwr( OFF ); //attempt powercycle +//// delay( 1000 ); +//// vbusPwr( ON ); +//// regWr( rGPINIRQ, bmGPINIRQ7 ); +//// } +// return( GPINIRQ ); +//} + +#endif //_USBHOST_H_ diff --git a/usbhub.cpp b/usbhub.cpp index a3ab21eb..7fed48e7 100644 --- a/usbhub.cpp +++ b/usbhub.cpp @@ -1,425 +1,425 @@ -/* 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 "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; - - epInfo[1].epAddr = 1; - epInfo[1].maxPktSize = 8; //kludge - epInfo[1].epAttribs = 0; - epInfo[1].bmNakPower = USB_NAK_NOWAIT; - - if(pUsb) - pUsb->RegisterDeviceClass(this); -} - -uint8_t USBHub::Init(uint8_t parent, uint8_t port, bool lowspeed) { - uint8_t buf[32]; - USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast(buf); - HubDescriptor* hd = reinterpret_cast(buf); - USB_CONFIGURATION_DESCRIPTOR * ucd = reinterpret_cast(buf); - uint8_t rcode; - UsbDevice *p = NULL; - EpInfo *oldep_ptr = NULL; - uint8_t len = 0; - uint16_t cd_len = 0; - - //USBTRACE("\r\nHub Init Start "); - //D_PrintHex (bInitState, 0x80); - - AddressPool &addrPool = pUsb->GetAddressPool(); - - //switch (bInitState) { - // case 0: - 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) - 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); - - p->lowspeed = false; - - if(!rcode) - len = (buf[0] > 32) ? 32 : buf[0]; - - if(rcode) { - // Restore p->epinfo - p->epinfo = oldep_ptr; - return rcode; - } - - // Extract device class from device descriptor - // If device class is not a hub return - if(udd->bDeviceClass != 0x09) - return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; - - // Allocate new address according to device class - bAddress = addrPool.AllocAddress(parent, (udd->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 = udd->bMaxPacketSize0; - - // Assign new address to the device - rcode = pUsb->setAddr(0, 0, bAddress); - - 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; - - if(len) - rcode = pUsb->getDevDescr(bAddress, 0, len, (uint8_t*)buf); - - if(rcode) - goto FailGetDevDescr; - - // Assign epInfo to epinfo pointer - rcode = pUsb->setEpInfoEntry(bAddress, 2, epInfo); - - if(rcode) - goto FailSetDevTblEntry; - - // bInitState = 1; - - // case 1: - // Get hub descriptor - rcode = GetHubDescriptor(0, 8, buf); - - if(rcode) - goto FailGetHubDescr; - - // Save number of ports for future use - bNbrPorts = hd->bNbrPorts; - - // bInitState = 2; - - // case 2: - // Read configuration Descriptor in Order To Obtain Proper Configuration Value - rcode = pUsb->getConfDescr(bAddress, 0, 8, 0, buf); - - if(!rcode) { - cd_len = ucd->wTotalLength; - rcode = pUsb->getConfDescr(bAddress, 0, cd_len, 0, buf); - } - if(rcode) - goto FailGetConfDescr; - - // 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]; - - rcode = pUsb->getConfDescr(bAddress, 0, buf[0], 0, buf2); - - if(rcode) - goto FailGetConfDescr; - } - - // 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; - //USBTRACE("...OK\r\n"); - return 0; - - // Oleg, No debugging?? -- xxxajk -FailGetDevDescr: - goto Fail; - -FailSetDevTblEntry: - goto Fail; - -FailGetHubDescr: - goto Fail; - -FailGetConfDescr: - goto Fail; - -FailSetConfDescr: - goto Fail; - -Fail: - USBTRACE("...FAIL\r\n"); - return rcode; -} - -uint8_t USBHub::Release() { - pUsb->GetAddressPool().FreeAddress(bAddress); - - if(bAddress == 0x41) - pUsb->SetHubPreMask(); - - bAddress = 0; - bNbrPorts = 0; - qNextPollTime = 0; - bPollEnable = false; - return 0; -} - -uint8_t USBHub::Poll() { - uint8_t rcode = 0; - - if(!bPollEnable) - return 0; - - if(((long)(millis() - qNextPollTime) >= 0L)) { - rcode = CheckHubStatus(); - qNextPollTime = millis() + 100; - } - return rcode; -} - -uint8_t USBHub::CheckHubStatus() { - uint8_t rcode; - uint8_t buf[8]; - uint16_t read = 1; - - rcode = pUsb->inTransfer(bAddress, 1, &read, buf); - - if(rcode) - return rcode; - - //if (buf[0] & 0x01) // Hub Status Change - //{ - // pUsb->PrintHubStatus(addr); - // rcode = GetHubStatus(1, 0, 1, 4, buf); - // if (rcode) - // { - // USB_HOST_SERIAL.print("GetHubStatus Error"); - // USB_HOST_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); - - if(rcode) - continue; - - rcode = PortStatusChange(port, evt); - - if(rcode == HUB_ERROR_PORT_HAS_BEEN_RESET) - return 0; - - if(rcode) - return rcode; - } - } // for - - for(uint8_t port = 1; port <= bNbrPorts; port++) { - HubEvent evt; - evt.bmEvent = 0; - - rcode = GetPortStatus(port, 4, evt.evtBuff); - - if(rcode) - 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; - - rcode = PortStatusChange(port, evt); - - if(rcode == HUB_ERROR_PORT_HAS_BEEN_RESET) - return 0; - - if(rcode) - return rcode; - } // for - return 0; -} - -void USBHub::ResetHubPort(uint8_t port) { - HubEvent evt; - evt.bmEvent = 0; - uint8_t rcode; - - ClearPortFeature(HUB_FEATURE_C_PORT_ENABLE, port, 0); - ClearPortFeature(HUB_FEATURE_C_PORT_CONNECTION, port, 0); - SetPortFeature(HUB_FEATURE_PORT_RESET, port, 0); - - - for(int i = 0; i < 3; i++) { - rcode = GetPortStatus(port, 4, evt.evtBuff); - if(rcode) break; // Some kind of error, bail. - if(evt.bmEvent == bmHUB_PORT_EVENT_RESET_COMPLETE || evt.bmEvent == bmHUB_PORT_EVENT_LS_RESET_COMPLETE) { - break; - } - delay(100); // simulate polling. - } - ClearPortFeature(HUB_FEATURE_C_PORT_RESET, port, 0); - ClearPortFeature(HUB_FEATURE_C_PORT_CONNECTION, port, 0); - delay(20); -} - -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; - - // 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.devAddress = 0; - 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); - - delay(20); - - a.devAddress = bAddress; - - pUsb->Configuring(a.bmAddress, port, (evt.bmStatus & bmHUB_PORT_STATUS_PORT_LOW_SPEED)); - bResetInitiated = false; - break; - - } // switch (evt.bmEvent) - return 0; -} - -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); - - if(rcode) { - USB_HOST_SERIAL.println("ERROR!"); - return; - } - USB_HOST_SERIAL.print("\r\nPort "); - USB_HOST_SERIAL.println(port, DEC); - - USB_HOST_SERIAL.println("Status"); - USB_HOST_SERIAL.print("CONNECTION:\t"); - USB_HOST_SERIAL.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_CONNECTION) > 0, DEC); - USB_HOST_SERIAL.print("ENABLE:\t\t"); - USB_HOST_SERIAL.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_ENABLE) > 0, DEC); - USB_HOST_SERIAL.print("SUSPEND:\t"); - USB_HOST_SERIAL.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_SUSPEND) > 0, DEC); - USB_HOST_SERIAL.print("OVER_CURRENT:\t"); - USB_HOST_SERIAL.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_OVER_CURRENT) > 0, DEC); - USB_HOST_SERIAL.print("RESET:\t\t"); - USB_HOST_SERIAL.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_RESET) > 0, DEC); - USB_HOST_SERIAL.print("POWER:\t\t"); - USB_HOST_SERIAL.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_POWER) > 0, DEC); - USB_HOST_SERIAL.print("LOW_SPEED:\t"); - USB_HOST_SERIAL.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_LOW_SPEED) > 0, DEC); - USB_HOST_SERIAL.print("HIGH_SPEED:\t"); - USB_HOST_SERIAL.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_HIGH_SPEED) > 0, DEC); - USB_HOST_SERIAL.print("TEST:\t\t"); - USB_HOST_SERIAL.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_TEST) > 0, DEC); - USB_HOST_SERIAL.print("INDICATOR:\t"); - USB_HOST_SERIAL.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_INDICATOR) > 0, DEC); - - if(!print_changes) - return; - - USB_HOST_SERIAL.println("\r\nChange"); - USB_HOST_SERIAL.print("CONNECTION:\t"); - USB_HOST_SERIAL.println((evt.bmChange & bmHUB_PORT_STATUS_C_PORT_CONNECTION) > 0, DEC); - USB_HOST_SERIAL.print("ENABLE:\t\t"); - USB_HOST_SERIAL.println((evt.bmChange & bmHUB_PORT_STATUS_C_PORT_ENABLE) > 0, DEC); - USB_HOST_SERIAL.print("SUSPEND:\t"); - USB_HOST_SERIAL.println((evt.bmChange & bmHUB_PORT_STATUS_C_PORT_SUSPEND) > 0, DEC); - USB_HOST_SERIAL.print("OVER_CURRENT:\t"); - USB_HOST_SERIAL.println((evt.bmChange & bmHUB_PORT_STATUS_C_PORT_OVER_CURRENT) > 0, DEC); - USB_HOST_SERIAL.print("RESET:\t\t"); - USB_HOST_SERIAL.println((evt.bmChange & bmHUB_PORT_STATUS_C_PORT_RESET) > 0, DEC); -} +/* 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 "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; + + epInfo[1].epAddr = 1; + epInfo[1].maxPktSize = 8; //kludge + epInfo[1].epAttribs = 0; + epInfo[1].bmNakPower = USB_NAK_NOWAIT; + + if(pUsb) + pUsb->RegisterDeviceClass(this); +} + +uint8_t USBHub::Init(uint8_t parent, uint8_t port, bool lowspeed) { + uint8_t buf[32]; + USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast(buf); + HubDescriptor* hd = reinterpret_cast(buf); + USB_CONFIGURATION_DESCRIPTOR * ucd = reinterpret_cast(buf); + uint8_t rcode; + UsbDevice *p = NULL; + EpInfo *oldep_ptr = NULL; + uint8_t len = 0; + uint16_t cd_len = 0; + + //USBTRACE("\r\nHub Init Start "); + //D_PrintHex (bInitState, 0x80); + + AddressPool &addrPool = pUsb->GetAddressPool(); + + //switch (bInitState) { + // case 0: + 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) + 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); + + p->lowspeed = false; + + if(!rcode) + len = (buf[0] > 32) ? 32 : buf[0]; + + if(rcode) { + // Restore p->epinfo + p->epinfo = oldep_ptr; + return rcode; + } + + // Extract device class from device descriptor + // If device class is not a hub return + if(udd->bDeviceClass != 0x09) + return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; + + // Allocate new address according to device class + bAddress = addrPool.AllocAddress(parent, (udd->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 = udd->bMaxPacketSize0; + + // Assign new address to the device + rcode = pUsb->setAddr(0, 0, bAddress); + + 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; + + if(len) + rcode = pUsb->getDevDescr(bAddress, 0, len, (uint8_t*)buf); + + if(rcode) + goto FailGetDevDescr; + + // Assign epInfo to epinfo pointer + rcode = pUsb->setEpInfoEntry(bAddress, 2, epInfo); + + if(rcode) + goto FailSetDevTblEntry; + + // bInitState = 1; + + // case 1: + // Get hub descriptor + rcode = GetHubDescriptor(0, 8, buf); + + if(rcode) + goto FailGetHubDescr; + + // Save number of ports for future use + bNbrPorts = hd->bNbrPorts; + + // bInitState = 2; + + // case 2: + // Read configuration Descriptor in Order To Obtain Proper Configuration Value + rcode = pUsb->getConfDescr(bAddress, 0, 8, 0, buf); + + if(!rcode) { + cd_len = ucd->wTotalLength; + rcode = pUsb->getConfDescr(bAddress, 0, cd_len, 0, buf); + } + if(rcode) + goto FailGetConfDescr; + + // 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]; + + rcode = pUsb->getConfDescr(bAddress, 0, buf[0], 0, buf2); + + if(rcode) + goto FailGetConfDescr; + } + + // 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; + //USBTRACE("...OK\r\n"); + return 0; + + // Oleg, No debugging?? -- xxxajk +FailGetDevDescr: + goto Fail; + +FailSetDevTblEntry: + goto Fail; + +FailGetHubDescr: + goto Fail; + +FailGetConfDescr: + goto Fail; + +FailSetConfDescr: + goto Fail; + +Fail: + USBTRACE("...FAIL\r\n"); + return rcode; +} + +uint8_t USBHub::Release() { + pUsb->GetAddressPool().FreeAddress(bAddress); + + if(bAddress == 0x41) + pUsb->SetHubPreMask(); + + bAddress = 0; + bNbrPorts = 0; + qNextPollTime = 0; + bPollEnable = false; + return 0; +} + +uint8_t USBHub::Poll() { + uint8_t rcode = 0; + + if(!bPollEnable) + return 0; + + if(((long)(millis() - qNextPollTime) >= 0L)) { + rcode = CheckHubStatus(); + qNextPollTime = millis() + 100; + } + return rcode; +} + +uint8_t USBHub::CheckHubStatus() { + uint8_t rcode; + uint8_t buf[8]; + uint16_t read = 1; + + rcode = pUsb->inTransfer(bAddress, 1, &read, buf); + + if(rcode) + return rcode; + + //if (buf[0] & 0x01) // Hub Status Change + //{ + // pUsb->PrintHubStatus(addr); + // rcode = GetHubStatus(1, 0, 1, 4, buf); + // if (rcode) + // { + // USB_HOST_SERIAL.print("GetHubStatus Error"); + // USB_HOST_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); + + if(rcode) + continue; + + rcode = PortStatusChange(port, evt); + + if(rcode == HUB_ERROR_PORT_HAS_BEEN_RESET) + return 0; + + if(rcode) + return rcode; + } + } // for + + for(uint8_t port = 1; port <= bNbrPorts; port++) { + HubEvent evt; + evt.bmEvent = 0; + + rcode = GetPortStatus(port, 4, evt.evtBuff); + + if(rcode) + 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; + + rcode = PortStatusChange(port, evt); + + if(rcode == HUB_ERROR_PORT_HAS_BEEN_RESET) + return 0; + + if(rcode) + return rcode; + } // for + return 0; +} + +void USBHub::ResetHubPort(uint8_t port) { + HubEvent evt; + evt.bmEvent = 0; + uint8_t rcode; + + ClearPortFeature(HUB_FEATURE_C_PORT_ENABLE, port, 0); + ClearPortFeature(HUB_FEATURE_C_PORT_CONNECTION, port, 0); + SetPortFeature(HUB_FEATURE_PORT_RESET, port, 0); + + + for(int i = 0; i < 3; i++) { + rcode = GetPortStatus(port, 4, evt.evtBuff); + if(rcode) break; // Some kind of error, bail. + if(evt.bmEvent == bmHUB_PORT_EVENT_RESET_COMPLETE || evt.bmEvent == bmHUB_PORT_EVENT_LS_RESET_COMPLETE) { + break; + } + delay(100); // simulate polling. + } + ClearPortFeature(HUB_FEATURE_C_PORT_RESET, port, 0); + ClearPortFeature(HUB_FEATURE_C_PORT_CONNECTION, port, 0); + delay(20); +} + +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; + + // 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.devAddress = 0; + 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); + + delay(20); + + a.devAddress = bAddress; + + pUsb->Configuring(a.bmAddress, port, (evt.bmStatus & bmHUB_PORT_STATUS_PORT_LOW_SPEED)); + bResetInitiated = false; + break; + + } // switch (evt.bmEvent) + return 0; +} + +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); + + if(rcode) { + USB_HOST_SERIAL.println("ERROR!"); + return; + } + USB_HOST_SERIAL.print("\r\nPort "); + USB_HOST_SERIAL.println(port, DEC); + + USB_HOST_SERIAL.println("Status"); + USB_HOST_SERIAL.print("CONNECTION:\t"); + USB_HOST_SERIAL.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_CONNECTION) > 0, DEC); + USB_HOST_SERIAL.print("ENABLE:\t\t"); + USB_HOST_SERIAL.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_ENABLE) > 0, DEC); + USB_HOST_SERIAL.print("SUSPEND:\t"); + USB_HOST_SERIAL.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_SUSPEND) > 0, DEC); + USB_HOST_SERIAL.print("OVER_CURRENT:\t"); + USB_HOST_SERIAL.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_OVER_CURRENT) > 0, DEC); + USB_HOST_SERIAL.print("RESET:\t\t"); + USB_HOST_SERIAL.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_RESET) > 0, DEC); + USB_HOST_SERIAL.print("POWER:\t\t"); + USB_HOST_SERIAL.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_POWER) > 0, DEC); + USB_HOST_SERIAL.print("LOW_SPEED:\t"); + USB_HOST_SERIAL.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_LOW_SPEED) > 0, DEC); + USB_HOST_SERIAL.print("HIGH_SPEED:\t"); + USB_HOST_SERIAL.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_HIGH_SPEED) > 0, DEC); + USB_HOST_SERIAL.print("TEST:\t\t"); + USB_HOST_SERIAL.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_TEST) > 0, DEC); + USB_HOST_SERIAL.print("INDICATOR:\t"); + USB_HOST_SERIAL.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_INDICATOR) > 0, DEC); + + if(!print_changes) + return; + + USB_HOST_SERIAL.println("\r\nChange"); + USB_HOST_SERIAL.print("CONNECTION:\t"); + USB_HOST_SERIAL.println((evt.bmChange & bmHUB_PORT_STATUS_C_PORT_CONNECTION) > 0, DEC); + USB_HOST_SERIAL.print("ENABLE:\t\t"); + USB_HOST_SERIAL.println((evt.bmChange & bmHUB_PORT_STATUS_C_PORT_ENABLE) > 0, DEC); + USB_HOST_SERIAL.print("SUSPEND:\t"); + USB_HOST_SERIAL.println((evt.bmChange & bmHUB_PORT_STATUS_C_PORT_SUSPEND) > 0, DEC); + USB_HOST_SERIAL.print("OVER_CURRENT:\t"); + USB_HOST_SERIAL.println((evt.bmChange & bmHUB_PORT_STATUS_C_PORT_OVER_CURRENT) > 0, DEC); + USB_HOST_SERIAL.print("RESET:\t\t"); + USB_HOST_SERIAL.println((evt.bmChange & bmHUB_PORT_STATUS_C_PORT_RESET) > 0, DEC); +} diff --git a/usbhub.h b/usbhub.h index e86e89fe..1ac94944 100644 --- a/usbhub.h +++ b/usbhub.h @@ -1,252 +1,252 @@ -/* 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(__USBHUB_H__) -#define __USBHUB_H__ - -#include "Usb.h" - -#define USB_DESCRIPTOR_HUB 0x09 // Hub descriptor type - -// Hub Requests -#define bmREQ_CLEAR_HUB_FEATURE USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_DEVICE -#define bmREQ_CLEAR_PORT_FEATURE USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_OTHER -#define bmREQ_CLEAR_TT_BUFFER USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_OTHER -#define bmREQ_GET_HUB_DESCRIPTOR USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_DEVICE -#define bmREQ_GET_HUB_STATUS USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_DEVICE -#define bmREQ_GET_PORT_STATUS USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_OTHER -#define bmREQ_RESET_TT USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_OTHER -#define bmREQ_SET_HUB_DESCRIPTOR USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_DEVICE -#define bmREQ_SET_HUB_FEATURE USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_DEVICE -#define bmREQ_SET_PORT_FEATURE USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_OTHER -#define bmREQ_GET_TT_STATE USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_OTHER -#define bmREQ_STOP_TT USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_OTHER - -// Hub Class Requests -#define HUB_REQUEST_CLEAR_TT_BUFFER 8 -#define HUB_REQUEST_RESET_TT 9 -#define HUB_REQUEST_GET_TT_STATE 10 -#define HUB_REQUEST_STOP_TT 11 - -// Hub Features -#define HUB_FEATURE_C_HUB_LOCAL_POWER 0 -#define HUB_FEATURE_C_HUB_OVER_CURRENT 1 -#define HUB_FEATURE_PORT_CONNECTION 0 -#define HUB_FEATURE_PORT_ENABLE 1 -#define HUB_FEATURE_PORT_SUSPEND 2 -#define HUB_FEATURE_PORT_OVER_CURRENT 3 -#define HUB_FEATURE_PORT_RESET 4 -#define HUB_FEATURE_PORT_POWER 8 -#define HUB_FEATURE_PORT_LOW_SPEED 9 -#define HUB_FEATURE_C_PORT_CONNECTION 16 -#define HUB_FEATURE_C_PORT_ENABLE 17 -#define HUB_FEATURE_C_PORT_SUSPEND 18 -#define HUB_FEATURE_C_PORT_OVER_CURRENT 19 -#define HUB_FEATURE_C_PORT_RESET 20 -#define HUB_FEATURE_PORT_TEST 21 -#define HUB_FEATURE_PORT_INDICATOR 22 - -// Hub Port Test Modes -#define HUB_PORT_TEST_MODE_J 1 -#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 - -// Hub Port Indicator Color -#define HUB_PORT_INDICATOR_AUTO 0 -#define HUB_PORT_INDICATOR_AMBER 1 -#define HUB_PORT_INDICATOR_GREEN 2 -#define HUB_PORT_INDICATOR_OFF 3 - -// 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 -#define bmHUB_PORT_STATUS_PORT_OVER_CURRENT 0x0008 -#define bmHUB_PORT_STATUS_PORT_RESET 0x0010 -#define bmHUB_PORT_STATUS_PORT_POWER 0x0100 -#define bmHUB_PORT_STATUS_PORT_LOW_SPEED 0x0200 -#define bmHUB_PORT_STATUS_PORT_HIGH_SPEED 0x0400 -#define bmHUB_PORT_STATUS_PORT_TEST 0x0800 -#define bmHUB_PORT_STATUS_PORT_INDICATOR 0x1000 - -// Hub Port Status Change Bitmasks (used one byte instead of two) -#define bmHUB_PORT_STATUS_C_PORT_CONNECTION 0x0001 -#define bmHUB_PORT_STATUS_C_PORT_ENABLE 0x0002 -#define bmHUB_PORT_STATUS_C_PORT_SUSPEND 0x0004 -#define bmHUB_PORT_STATUS_C_PORT_OVER_CURRENT 0x0008 -#define bmHUB_PORT_STATUS_C_PORT_RESET 0x0010 - -// Hub Status Bitmasks (used one byte instead of two) -#define bmHUB_STATUS_LOCAL_POWER_SOURCE 0x01 -#define bmHUB_STATUS_OVER_CURRENT 0x12 - -// Hub Status Change Bitmasks (used one byte instead of two) -#define bmHUB_STATUS_C_LOCAL_POWER_SOURCE 0x01 -#define bmHUB_STATUS_C_OVER_CURRENT 0x12 - - -// Hub Port Configuring Substates -#define USB_STATE_HUB_PORT_CONFIGURING 0xb0 -#define USB_STATE_HUB_PORT_POWERED_OFF 0xb1 -#define USB_STATE_HUB_PORT_WAIT_FOR_POWER_GOOD 0xb2 -#define USB_STATE_HUB_PORT_DISCONNECTED 0xb3 -#define USB_STATE_HUB_PORT_DISABLED 0xb4 -#define USB_STATE_HUB_PORT_RESETTING 0xb5 -#define USB_STATE_HUB_PORT_ENABLED 0xb6 - -// Additional Error Codes -#define HUB_ERROR_PORT_HAS_BEEN_RESET 0xb1 - -// 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 -#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 -#define bmHUB_PORT_STATE_DISABLED (0x0000 | bmHUB_PORT_STATUS_PORT_POWER | bmHUB_PORT_STATUS_PORT_CONNECTION) - -// Hub Port Events -#define bmHUB_PORT_EVENT_CONNECT (((0UL | bmHUB_PORT_STATUS_C_PORT_CONNECTION) << 16) | bmHUB_PORT_STATUS_PORT_POWER | bmHUB_PORT_STATUS_PORT_CONNECTION) -#define bmHUB_PORT_EVENT_DISCONNECT (((0UL | bmHUB_PORT_STATUS_C_PORT_CONNECTION) << 16) | bmHUB_PORT_STATUS_PORT_POWER) -#define bmHUB_PORT_EVENT_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) - -#define bmHUB_PORT_EVENT_LS_CONNECT (((0UL | bmHUB_PORT_STATUS_C_PORT_CONNECTION) << 16) | bmHUB_PORT_STATUS_PORT_POWER | bmHUB_PORT_STATUS_PORT_CONNECTION | bmHUB_PORT_STATUS_PORT_LOW_SPEED) -#define bmHUB_PORT_EVENT_LS_RESET_COMPLETE (((0UL | bmHUB_PORT_STATUS_C_PORT_RESET) << 16) | bmHUB_PORT_STATUS_PORT_POWER | bmHUB_PORT_STATUS_PORT_ENABLE | bmHUB_PORT_STATUS_PORT_CONNECTION | bmHUB_PORT_STATUS_PORT_LOW_SPEED) -#define bmHUB_PORT_EVENT_LS_PORT_ENABLED (((0UL | bmHUB_PORT_STATUS_C_PORT_CONNECTION | bmHUB_PORT_STATUS_C_PORT_ENABLE) << 16) | bmHUB_PORT_STATUS_PORT_POWER | bmHUB_PORT_STATUS_PORT_ENABLE | bmHUB_PORT_STATUS_PORT_CONNECTION | bmHUB_PORT_STATUS_PORT_LOW_SPEED) - -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; - } __attribute__((packed)); - - uint8_t bPwrOn2PwrGood; - uint8_t bHubContrCurrent; -} __attribute__((packed)); - -struct HubEvent { - - union { - - 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)); - -class USBHub : USBDeviceConfig { - static bool bResetInitiated; // True when reset is triggered - - 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); - - 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(); - - uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed); - uint8_t Release(); - uint8_t Poll(); - void ResetHubPort(uint8_t port); - - virtual uint8_t GetAddress() { - return bAddress; - }; - - virtual bool DEVCLASSOK(uint8_t klass) { - return (klass == 0x09); - } - -}; - -// 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)); -} -// 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)); -} -// 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)); -} -// 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)); -} -// 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)); -} -// 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)); -} -// 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)); -} -// 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)); -} - -void PrintHubPortStatus(USB *usbptr, uint8_t addr, uint8_t port, bool print_changes = false); - -#endif // __USBHUB_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(__USBHUB_H__) +#define __USBHUB_H__ + +#include "Usb.h" + +#define USB_DESCRIPTOR_HUB 0x09 // Hub descriptor type + +// Hub Requests +#define bmREQ_CLEAR_HUB_FEATURE USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_DEVICE +#define bmREQ_CLEAR_PORT_FEATURE USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_OTHER +#define bmREQ_CLEAR_TT_BUFFER USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_OTHER +#define bmREQ_GET_HUB_DESCRIPTOR USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_DEVICE +#define bmREQ_GET_HUB_STATUS USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_DEVICE +#define bmREQ_GET_PORT_STATUS USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_OTHER +#define bmREQ_RESET_TT USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_OTHER +#define bmREQ_SET_HUB_DESCRIPTOR USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_DEVICE +#define bmREQ_SET_HUB_FEATURE USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_DEVICE +#define bmREQ_SET_PORT_FEATURE USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_OTHER +#define bmREQ_GET_TT_STATE USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_OTHER +#define bmREQ_STOP_TT USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_OTHER + +// Hub Class Requests +#define HUB_REQUEST_CLEAR_TT_BUFFER 8 +#define HUB_REQUEST_RESET_TT 9 +#define HUB_REQUEST_GET_TT_STATE 10 +#define HUB_REQUEST_STOP_TT 11 + +// Hub Features +#define HUB_FEATURE_C_HUB_LOCAL_POWER 0 +#define HUB_FEATURE_C_HUB_OVER_CURRENT 1 +#define HUB_FEATURE_PORT_CONNECTION 0 +#define HUB_FEATURE_PORT_ENABLE 1 +#define HUB_FEATURE_PORT_SUSPEND 2 +#define HUB_FEATURE_PORT_OVER_CURRENT 3 +#define HUB_FEATURE_PORT_RESET 4 +#define HUB_FEATURE_PORT_POWER 8 +#define HUB_FEATURE_PORT_LOW_SPEED 9 +#define HUB_FEATURE_C_PORT_CONNECTION 16 +#define HUB_FEATURE_C_PORT_ENABLE 17 +#define HUB_FEATURE_C_PORT_SUSPEND 18 +#define HUB_FEATURE_C_PORT_OVER_CURRENT 19 +#define HUB_FEATURE_C_PORT_RESET 20 +#define HUB_FEATURE_PORT_TEST 21 +#define HUB_FEATURE_PORT_INDICATOR 22 + +// Hub Port Test Modes +#define HUB_PORT_TEST_MODE_J 1 +#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 + +// Hub Port Indicator Color +#define HUB_PORT_INDICATOR_AUTO 0 +#define HUB_PORT_INDICATOR_AMBER 1 +#define HUB_PORT_INDICATOR_GREEN 2 +#define HUB_PORT_INDICATOR_OFF 3 + +// 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 +#define bmHUB_PORT_STATUS_PORT_OVER_CURRENT 0x0008 +#define bmHUB_PORT_STATUS_PORT_RESET 0x0010 +#define bmHUB_PORT_STATUS_PORT_POWER 0x0100 +#define bmHUB_PORT_STATUS_PORT_LOW_SPEED 0x0200 +#define bmHUB_PORT_STATUS_PORT_HIGH_SPEED 0x0400 +#define bmHUB_PORT_STATUS_PORT_TEST 0x0800 +#define bmHUB_PORT_STATUS_PORT_INDICATOR 0x1000 + +// Hub Port Status Change Bitmasks (used one byte instead of two) +#define bmHUB_PORT_STATUS_C_PORT_CONNECTION 0x0001 +#define bmHUB_PORT_STATUS_C_PORT_ENABLE 0x0002 +#define bmHUB_PORT_STATUS_C_PORT_SUSPEND 0x0004 +#define bmHUB_PORT_STATUS_C_PORT_OVER_CURRENT 0x0008 +#define bmHUB_PORT_STATUS_C_PORT_RESET 0x0010 + +// Hub Status Bitmasks (used one byte instead of two) +#define bmHUB_STATUS_LOCAL_POWER_SOURCE 0x01 +#define bmHUB_STATUS_OVER_CURRENT 0x12 + +// Hub Status Change Bitmasks (used one byte instead of two) +#define bmHUB_STATUS_C_LOCAL_POWER_SOURCE 0x01 +#define bmHUB_STATUS_C_OVER_CURRENT 0x12 + + +// Hub Port Configuring Substates +#define USB_STATE_HUB_PORT_CONFIGURING 0xb0 +#define USB_STATE_HUB_PORT_POWERED_OFF 0xb1 +#define USB_STATE_HUB_PORT_WAIT_FOR_POWER_GOOD 0xb2 +#define USB_STATE_HUB_PORT_DISCONNECTED 0xb3 +#define USB_STATE_HUB_PORT_DISABLED 0xb4 +#define USB_STATE_HUB_PORT_RESETTING 0xb5 +#define USB_STATE_HUB_PORT_ENABLED 0xb6 + +// Additional Error Codes +#define HUB_ERROR_PORT_HAS_BEEN_RESET 0xb1 + +// 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 +#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 +#define bmHUB_PORT_STATE_DISABLED (0x0000 | bmHUB_PORT_STATUS_PORT_POWER | bmHUB_PORT_STATUS_PORT_CONNECTION) + +// Hub Port Events +#define bmHUB_PORT_EVENT_CONNECT (((0UL | bmHUB_PORT_STATUS_C_PORT_CONNECTION) << 16) | bmHUB_PORT_STATUS_PORT_POWER | bmHUB_PORT_STATUS_PORT_CONNECTION) +#define bmHUB_PORT_EVENT_DISCONNECT (((0UL | bmHUB_PORT_STATUS_C_PORT_CONNECTION) << 16) | bmHUB_PORT_STATUS_PORT_POWER) +#define bmHUB_PORT_EVENT_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) + +#define bmHUB_PORT_EVENT_LS_CONNECT (((0UL | bmHUB_PORT_STATUS_C_PORT_CONNECTION) << 16) | bmHUB_PORT_STATUS_PORT_POWER | bmHUB_PORT_STATUS_PORT_CONNECTION | bmHUB_PORT_STATUS_PORT_LOW_SPEED) +#define bmHUB_PORT_EVENT_LS_RESET_COMPLETE (((0UL | bmHUB_PORT_STATUS_C_PORT_RESET) << 16) | bmHUB_PORT_STATUS_PORT_POWER | bmHUB_PORT_STATUS_PORT_ENABLE | bmHUB_PORT_STATUS_PORT_CONNECTION | bmHUB_PORT_STATUS_PORT_LOW_SPEED) +#define bmHUB_PORT_EVENT_LS_PORT_ENABLED (((0UL | bmHUB_PORT_STATUS_C_PORT_CONNECTION | bmHUB_PORT_STATUS_C_PORT_ENABLE) << 16) | bmHUB_PORT_STATUS_PORT_POWER | bmHUB_PORT_STATUS_PORT_ENABLE | bmHUB_PORT_STATUS_PORT_CONNECTION | bmHUB_PORT_STATUS_PORT_LOW_SPEED) + +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; + } __attribute__((packed)); + + uint8_t bPwrOn2PwrGood; + uint8_t bHubContrCurrent; +} __attribute__((packed)); + +struct HubEvent { + + union { + + 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)); + +class USBHub : USBDeviceConfig { + static bool bResetInitiated; // True when reset is triggered + + 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); + + 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(); + + uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed); + uint8_t Release(); + uint8_t Poll(); + void ResetHubPort(uint8_t port); + + virtual uint8_t GetAddress() { + return bAddress; + }; + + virtual bool DEVCLASSOK(uint8_t klass) { + return (klass == 0x09); + } + +}; + +// 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)); +} +// 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)); +} +// 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)); +} +// 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)); +} +// 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)); +} +// 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)); +} +// 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)); +} +// 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)); +} + +void PrintHubPortStatus(USB *usbptr, uint8_t addr, uint8_t port, bool print_changes = false); + +#endif // __USBHUB_H__