3 Commits

Author SHA1 Message Date
kenji 8e265c2b8f Fix Websocket extended length 2025-09-06 11:25:55 -04:00
kenji 878dcf7355 minor fixes 2025-08-26 07:01:31 -04:00
kenji 84aa9a2e74 add Pico 2 W firmware 2025-08-18 08:09:28 -04:00
8 changed files with 348 additions and 337 deletions
+4
View File
@@ -1,7 +1,9 @@
cmake_minimum_required(VERSION 3.13) cmake_minimum_required(VERSION 3.13)
set(PROJECT webkeyboard) set(PROJECT webkeyboard)
set(PICO_SDK_PATH /home/kenji/programming/pico/c/pico-sdk) set(PICO_SDK_PATH /home/kenji/programming/pico/c/pico-sdk)
if (NOT DEFINED PICO_BOARD)
set(PICO_BOARD pico_w) set(PICO_BOARD pico_w)
endif()
include (${PICO_SDK_PATH}/external/pico_sdk_import.cmake) include (${PICO_SDK_PATH}/external/pico_sdk_import.cmake)
project(${PROJECT} C CXX ASM) project(${PROJECT} C CXX ASM)
@@ -38,6 +40,8 @@ target_sources(${PROJECT} PRIVATE
pico_enable_stdio_usb(${PROJECT} 1) pico_enable_stdio_usb(${PROJECT} 1)
set_target_properties(${PROJECT} PROPERTIES OUTPUT_NAME "${PROJECT}-${PICO_BOARD}")
pico_add_extra_outputs(${PROJECT}) pico_add_extra_outputs(${PROJECT})
target_include_directories(${PROJECT} PRIVATE ${CMAKE_CURRENT_LIST_DIR}) target_include_directories(${PROJECT} PRIVATE ${CMAKE_CURRENT_LIST_DIR})
+13 -12
View File
@@ -2,11 +2,11 @@
## About ## About
This project turns a Raspberry Pi Pico W into a web-based USB HID keyboard This project turns a Raspberry Pi Pico W or Raspberry Pi Pico 2 W into a
device. Users can access a webpage served over HTTP to enter keyboard input web-based USB HID keyboard device. Users can access a webpage served over HTTP
onto the host device of the Raspberry Pi Pico W. Input keys can be entered to enter keyboard input onto the host device of the Raspberry Pi Pico (2) W.
through a keyboard on the client device or by pressing on the keys on the Input keys can be entered through a keyboard on the client device or by
graphical interface served on the webpage. pressing on the keys on the graphical interface served on the webpage.
![Web interface for Web Keyboard](web-ui.jpg) ![Web interface for Web Keyboard](web-ui.jpg)
@@ -14,18 +14,19 @@ graphical interface served on the webpage.
[Installation and demo video](https://youtu.be/uORnxt5DLTw) [Installation and demo video](https://youtu.be/uORnxt5DLTw)
Download the webkeyboard.uf2 file from the latest Download the appropriate firmware file for your board, either
webkeyboard-pico_w.uf2 or webkeyboard-pico2_w.uf2, from the latest
[release](https://git.kkozai.com/kenji/webkeyboard/releases) and flash [release](https://git.kkozai.com/kenji/webkeyboard/releases) and flash
onto the Raspberry Pi Pico W by holding down the BOOTSEL button while plugging onto the Raspberry Pi Pico (2) W by holding down the BOOTSEL button while
into your computer so that it appears as a USB drive, then transfer the plugging into your computer so that it appears as a USB drive, then transfer the
firmware file onto the Pico W. After unmounting, connect the Raspberry Pi Pico firmware file onto the Pico (2) W. After unmounting, connect the Raspberry Pi
W with a micro USB cable to the host computer or other device. Pico (2) W with a micro USB cable to the host computer or other device.
On initial boot, the Raspberry Pi Pico W will enter Access Point mode with On initial boot, the Raspberry Pi Pico (2) W will enter Access Point mode with
SSID "picokb" and password "password". Connect to this network with another SSID "picokb" and password "password". Connect to this network with another
device and open a browser window to http://192.168.0.1. device and open a browser window to http://192.168.0.1.
Go to the "Configure W-Fi" page and enter the SSID and password to the Go to the "Configure W-Fi" page and enter the SSID and password to the
network that you would like the Raspberry Pi Pico W to connect. Optionally, network that you would like the Raspberry Pi Pico (2) W to connect. Optionally,
also enter a hostname for the device and static IP information. Hit the "Save" also enter a hostname for the device and static IP information. Hit the "Save"
button to save the network information to device flash. button to save the network information to device flash.
+1
View File
@@ -332,6 +332,7 @@ function sendKeys(curKeys, is_mouse) {
} }
} else if (socket.readyState == WebSocket.CLOSED) { } else if (socket.readyState == WebSocket.CLOSED) {
socket = new WebSocket("ws://" + window.location.hostname + ":8080/"); socket = new WebSocket("ws://" + window.location.hostname + ":8080/");
socket.onmessage = function (event) { updateLEDs(event.data); };
setTimeout( function () { sendKeys(curKeys, is_mouse); }, 10); setTimeout( function () { sendKeys(curKeys, is_mouse); }, 10);
} else { } else {
setTimeout( function () { sendKeys(curKeys, is_mouse); }, 10); setTimeout( function () { sendKeys(curKeys, is_mouse); }, 10);
+314 -307
View File
@@ -1173,116 +1173,80 @@ static const unsigned char data_index_html[] = {
0x64, 0x6f, 0x77, 0x2e, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x64, 0x6f, 0x77, 0x2e, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69,
0x6f, 0x6e, 0x2e, 0x68, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x6f, 0x6e, 0x2e, 0x68, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d,
0x65, 0x20, 0x2b, 0x20, 0x22, 0x3a, 0x38, 0x30, 0x38, 0x30, 0x65, 0x20, 0x2b, 0x20, 0x22, 0x3a, 0x38, 0x30, 0x38, 0x30,
0x2f, 0x22, 0x29, 0x3b, 0xa, 0x9, 0x9, 0x73, 0x65, 0x74, 0x2f, 0x22, 0x29, 0x3b, 0xa, 0x9, 0x9, 0x73, 0x6f, 0x63,
0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x28, 0x20, 0x66, 0x6b, 0x65, 0x74, 0x2e, 0x6f, 0x6e, 0x6d, 0x65, 0x73, 0x73,
0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x28, 0x29, 0x61, 0x67, 0x65, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63,
0x20, 0x7b, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x4b, 0x65, 0x79, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x28, 0x65, 0x76, 0x65, 0x6e,
0x73, 0x28, 0x63, 0x75, 0x72, 0x4b, 0x65, 0x79, 0x73, 0x2c, 0x74, 0x29, 0x20, 0x7b, 0x20, 0x75, 0x70, 0x64, 0x61, 0x74,
0x20, 0x69, 0x73, 0x5f, 0x6d, 0x6f, 0x75, 0x73, 0x65, 0x29, 0x65, 0x4c, 0x45, 0x44, 0x73, 0x28, 0x65, 0x76, 0x65, 0x6e,
0x3b, 0x20, 0x7d, 0x2c, 0x20, 0x31, 0x30, 0x29, 0x3b, 0xa, 0x74, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x29, 0x3b, 0x20, 0x7d,
0x9, 0x7d, 0x20, 0x65, 0x6c, 0x73, 0x65, 0x20, 0x7b, 0xa, 0x3b, 0xa, 0x9, 0x9, 0x73, 0x65, 0x74, 0x54, 0x69, 0x6d,
0x9, 0x9, 0x73, 0x65, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x65, 0x6f, 0x75, 0x74, 0x28, 0x20, 0x66, 0x75, 0x6e, 0x63,
0x75, 0x74, 0x28, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x28, 0x29, 0x20, 0x7b, 0x20,
0x6f, 0x6e, 0x20, 0x28, 0x29, 0x20, 0x7b, 0x20, 0x73, 0x65, 0x73, 0x65, 0x6e, 0x64, 0x4b, 0x65, 0x79, 0x73, 0x28, 0x63,
0x6e, 0x64, 0x4b, 0x65, 0x79, 0x73, 0x28, 0x63, 0x75, 0x72, 0x75, 0x72, 0x4b, 0x65, 0x79, 0x73, 0x2c, 0x20, 0x69, 0x73,
0x4b, 0x65, 0x79, 0x73, 0x2c, 0x20, 0x69, 0x73, 0x5f, 0x6d, 0x5f, 0x6d, 0x6f, 0x75, 0x73, 0x65, 0x29, 0x3b, 0x20, 0x7d,
0x6f, 0x75, 0x73, 0x65, 0x29, 0x3b, 0x20, 0x7d, 0x2c, 0x20, 0x2c, 0x20, 0x31, 0x30, 0x29, 0x3b, 0xa, 0x9, 0x7d, 0x20,
0x31, 0x30, 0x29, 0x3b, 0xa, 0x9, 0x7d, 0xa, 0x7d, 0xa, 0x65, 0x6c, 0x73, 0x65, 0x20, 0x7b, 0xa, 0x9, 0x9, 0x73,
0xa, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x65, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x28,
0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20,
0x28, 0x64, 0x69, 0x76, 0x5f, 0x69, 0x64, 0x2c, 0x20, 0x6b, 0x28, 0x29, 0x20, 0x7b, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x4b,
0x65, 0x79, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x29, 0x20, 0x7b, 0x65, 0x79, 0x73, 0x28, 0x63, 0x75, 0x72, 0x4b, 0x65, 0x79,
0xa, 0x9, 0x6c, 0x65, 0x74, 0x20, 0x6b, 0x65, 0x79, 0x62, 0x73, 0x2c, 0x20, 0x69, 0x73, 0x5f, 0x6d, 0x6f, 0x75, 0x73,
0x6f, 0x61, 0x72, 0x64, 0x44, 0x69, 0x76, 0x20, 0x3d, 0x20, 0x65, 0x29, 0x3b, 0x20, 0x7d, 0x2c, 0x20, 0x31, 0x30, 0x29,
0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x67, 0x3b, 0xa, 0x9, 0x7d, 0xa, 0x7d, 0xa, 0xa, 0x66, 0x75,
0x65, 0x74, 0x45, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x42, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x63, 0x72, 0x65,
0x79, 0x49, 0x64, 0x28, 0x64, 0x69, 0x76, 0x5f, 0x69, 0x64, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x28, 0x64, 0x69,
0x29, 0x3b, 0xa, 0x9, 0x66, 0x6f, 0x72, 0x20, 0x28, 0x6c, 0x76, 0x5f, 0x69, 0x64, 0x2c, 0x20, 0x6b, 0x65, 0x79, 0x5f,
0x65, 0x74, 0x20, 0x72, 0x6f, 0x77, 0x20, 0x6f, 0x66, 0x20, 0x6c, 0x69, 0x73, 0x74, 0x29, 0x20, 0x7b, 0xa, 0x9, 0x6c,
0x6b, 0x65, 0x79, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x29, 0x20, 0x65, 0x74, 0x20, 0x6b, 0x65, 0x79, 0x62, 0x6f, 0x61, 0x72,
0x7b, 0xa, 0x9, 0x9, 0x6c, 0x65, 0x74, 0x20, 0x6e, 0x65, 0x64, 0x44, 0x69, 0x76, 0x20, 0x3d, 0x20, 0x64, 0x6f, 0x63,
0x77, 0x52, 0x6f, 0x77, 0x20, 0x3d, 0x20, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x67, 0x65, 0x74, 0x45,
0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x63, 0x72, 0x65, 0x61, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x42, 0x79, 0x49, 0x64,
0x74, 0x65, 0x45, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x28, 0x28, 0x64, 0x69, 0x76, 0x5f, 0x69, 0x64, 0x29, 0x3b, 0xa,
0x22, 0x64, 0x69, 0x76, 0x22, 0x29, 0x3b, 0xa, 0x9, 0x9, 0x9, 0x66, 0x6f, 0x72, 0x20, 0x28, 0x6c, 0x65, 0x74, 0x20,
0x6b, 0x65, 0x79, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x44, 0x69, 0x72, 0x6f, 0x77, 0x20, 0x6f, 0x66, 0x20, 0x6b, 0x65, 0x79,
0x76, 0x2e, 0x61, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x43, 0x68, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x29, 0x20, 0x7b, 0xa, 0x9,
0x69, 0x6c, 0x64, 0x28, 0x6e, 0x65, 0x77, 0x52, 0x6f, 0x77, 0x9, 0x6c, 0x65, 0x74, 0x20, 0x6e, 0x65, 0x77, 0x52, 0x6f,
0x29, 0x3b, 0xa, 0x9, 0x9, 0x66, 0x6f, 0x72, 0x20, 0x28, 0x77, 0x20, 0x3d, 0x20, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65,
0x6c, 0x65, 0x74, 0x20, 0x6b, 0x65, 0x79, 0x20, 0x6f, 0x66,
0x20, 0x72, 0x6f, 0x77, 0x29, 0x20, 0x7b, 0xa, 0x9, 0x9,
0x9, 0x6c, 0x65, 0x74, 0x20, 0x6e, 0x65, 0x77, 0x44, 0x69,
0x76, 0x20, 0x3d, 0x20, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65,
0x6e, 0x74, 0x2e, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x45, 0x6e, 0x74, 0x2e, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x45,
0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x28, 0x22, 0x64, 0x69, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x28, 0x22, 0x64, 0x69,
0x76, 0x22, 0x29, 0x3b, 0xa, 0x9, 0x9, 0x9, 0x69, 0x66, 0x76, 0x22, 0x29, 0x3b, 0xa, 0x9, 0x9, 0x6b, 0x65, 0x79,
0x20, 0x28, 0x6b, 0x65, 0x79, 0x2e, 0x69, 0x64, 0x29, 0x20, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x44, 0x69, 0x76, 0x2e, 0x61,
0x7b, 0xa, 0x9, 0x9, 0x9, 0x9, 0x6e, 0x65, 0x77, 0x44, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x43, 0x68, 0x69, 0x6c, 0x64,
0x69, 0x76, 0x2e, 0x69, 0x64, 0x20, 0x3d, 0x20, 0x6b, 0x65, 0x28, 0x6e, 0x65, 0x77, 0x52, 0x6f, 0x77, 0x29, 0x3b, 0xa,
0x79, 0x2e, 0x69, 0x64, 0x3b, 0xa, 0x9, 0x9, 0x9, 0x9, 0x9, 0x9, 0x66, 0x6f, 0x72, 0x20, 0x28, 0x6c, 0x65, 0x74,
0x6e, 0x65, 0x77, 0x44, 0x69, 0x76, 0x2e, 0x69, 0x6e, 0x6e, 0x20, 0x6b, 0x65, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x72, 0x6f,
0x65, 0x72, 0x48, 0x54, 0x4d, 0x4c, 0x20, 0x3d, 0x20, 0x6b, 0x77, 0x29, 0x20, 0x7b, 0xa, 0x9, 0x9, 0x9, 0x6c, 0x65,
0x65, 0x79, 0x2e, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x3b, 0xa, 0x74, 0x20, 0x6e, 0x65, 0x77, 0x44, 0x69, 0x76, 0x20, 0x3d,
0x20, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e,
0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x45, 0x6c, 0x65, 0x6d,
0x65, 0x6e, 0x74, 0x28, 0x22, 0x64, 0x69, 0x76, 0x22, 0x29,
0x3b, 0xa, 0x9, 0x9, 0x9, 0x69, 0x66, 0x20, 0x28, 0x6b,
0x65, 0x79, 0x2e, 0x69, 0x64, 0x29, 0x20, 0x7b, 0xa, 0x9,
0x9, 0x9, 0x9, 0x6e, 0x65, 0x77, 0x44, 0x69, 0x76, 0x2e,
0x69, 0x64, 0x20, 0x3d, 0x20, 0x6b, 0x65, 0x79, 0x2e, 0x69,
0x64, 0x3b, 0xa, 0x9, 0x9, 0x9, 0x9, 0x6e, 0x65, 0x77,
0x44, 0x69, 0x76, 0x2e, 0x69, 0x6e, 0x6e, 0x65, 0x72, 0x48,
0x54, 0x4d, 0x4c, 0x20, 0x3d, 0x20, 0x6b, 0x65, 0x79, 0x2e,
0x6c, 0x61, 0x62, 0x65, 0x6c, 0x3b, 0xa, 0x9, 0x9, 0x9,
0x9, 0x6e, 0x65, 0x77, 0x44, 0x69, 0x76, 0x2e, 0x63, 0x6c,
0x61, 0x73, 0x73, 0x4e, 0x61, 0x6d, 0x65, 0x20, 0x3d, 0x20,
0x22, 0x6b, 0x65, 0x79, 0x22, 0x3b, 0xa, 0x9, 0x9, 0x9,
0x9, 0x69, 0x66, 0x20, 0x28, 0x6b, 0x65, 0x79, 0x2e, 0x72,
0x65, 0x70, 0x65, 0x61, 0x74, 0x29, 0x20, 0x7b, 0xa, 0x9,
0x9, 0x9, 0x9, 0x9, 0x6e, 0x65, 0x77, 0x44, 0x69, 0x76, 0x9, 0x9, 0x9, 0x9, 0x6e, 0x65, 0x77, 0x44, 0x69, 0x76,
0x2e, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x4e, 0x61, 0x6d, 0x65, 0x2e, 0x61, 0x64, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x4c,
0x20, 0x3d, 0x20, 0x22, 0x6b, 0x65, 0x79, 0x22, 0x3b, 0xa, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x28, 0x22, 0x74,
0x9, 0x9, 0x9, 0x9, 0x69, 0x66, 0x20, 0x28, 0x6b, 0x65, 0x6f, 0x75, 0x63, 0x68, 0x73, 0x74, 0x61, 0x72, 0x74, 0x22,
0x79, 0x2e, 0x72, 0x65, 0x70, 0x65, 0x61, 0x74, 0x29, 0x20,
0x7b, 0xa, 0x9, 0x9, 0x9, 0x9, 0x9, 0x6e, 0x65, 0x77,
0x44, 0x69, 0x76, 0x2e, 0x61, 0x64, 0x64, 0x45, 0x76, 0x65,
0x6e, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72,
0x28, 0x22, 0x74, 0x6f, 0x75, 0x63, 0x68, 0x73, 0x74, 0x61,
0x72, 0x74, 0x22, 0x2c, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74,
0x69, 0x6f, 0x6e, 0x20, 0x28, 0x65, 0x76, 0x65, 0x6e, 0x74,
0x29, 0x20, 0x7b, 0xa, 0x9, 0x9, 0x9, 0x9, 0x9, 0x9,
0x65, 0x76, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x72, 0x65, 0x76,
0x65, 0x6e, 0x74, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74,
0x28, 0x29, 0x3b, 0x20, 0x70, 0x72, 0x65, 0x73, 0x73, 0x4b,
0x65, 0x79, 0x28, 0x6b, 0x65, 0x79, 0x2e, 0x69, 0x64, 0x2c,
0x20, 0x74, 0x72, 0x75, 0x65, 0x29, 0x3b, 0x20, 0x7d, 0x29,
0x3b, 0xa, 0x9, 0x9, 0x9, 0x9, 0x9, 0x6e, 0x65, 0x77,
0x44, 0x69, 0x76, 0x2e, 0x61, 0x64, 0x64, 0x45, 0x76, 0x65,
0x6e, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72,
0x28, 0x22, 0x74, 0x6f, 0x75, 0x63, 0x68, 0x65, 0x6e, 0x64,
0x22, 0x2c, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f,
0x6e, 0x20, 0x28, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x29, 0x20,
0x7b, 0xa, 0x9, 0x9, 0x9, 0x9, 0x9, 0x9, 0x65, 0x76,
0x65, 0x6e, 0x74, 0x2e, 0x70, 0x72, 0x65, 0x76, 0x65, 0x6e,
0x74, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x28, 0x29,
0x3b, 0x20, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x4b,
0x65, 0x79, 0x28, 0x6b, 0x65, 0x79, 0x2e, 0x69, 0x64, 0x2c,
0x20, 0x74, 0x72, 0x75, 0x65, 0x29, 0x3b, 0x20, 0x7d, 0x29,
0x3b, 0xa, 0x9, 0x9, 0x9, 0x9, 0x9, 0x6e, 0x65, 0x77,
0x44, 0x69, 0x76, 0x2e, 0x61, 0x64, 0x64, 0x45, 0x76, 0x65,
0x6e, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72,
0x28, 0x22, 0x6d, 0x6f, 0x75, 0x73, 0x65, 0x64, 0x6f, 0x77,
0x6e, 0x22, 0x2c, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69,
0x6f, 0x6e, 0x20, 0x28, 0x29, 0x20, 0x7b, 0xa, 0x9, 0x9,
0x9, 0x9, 0x9, 0x9, 0x70, 0x72, 0x65, 0x73, 0x73, 0x4b,
0x65, 0x79, 0x28, 0x6b, 0x65, 0x79, 0x2e, 0x69, 0x64, 0x2c,
0x20, 0x74, 0x72, 0x75, 0x65, 0x29, 0x3b, 0x20, 0x7d, 0x29,
0x3b, 0xa, 0x9, 0x9, 0x9, 0x9, 0x9, 0x6e, 0x65, 0x77,
0x44, 0x69, 0x76, 0x2e, 0x61, 0x64, 0x64, 0x45, 0x76, 0x65,
0x6e, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72,
0x28, 0x22, 0x6d, 0x6f, 0x75, 0x73, 0x65, 0x75, 0x70, 0x22,
0x2c, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e,
0x20, 0x28, 0x29, 0x20, 0x7b, 0xa, 0x9, 0x9, 0x9, 0x9, 0x20, 0x28, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x29, 0x20, 0x7b,
0x9, 0x9, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x4b, 0xa, 0x9, 0x9, 0x9, 0x9, 0x9, 0x9, 0x65, 0x76, 0x65,
0x65, 0x79, 0x28, 0x6b, 0x65, 0x79, 0x2e, 0x69, 0x64, 0x2c, 0x6e, 0x74, 0x2e, 0x70, 0x72, 0x65, 0x76, 0x65, 0x6e, 0x74,
0x20, 0x74, 0x72, 0x75, 0x65, 0x29, 0x3b, 0x20, 0x7d, 0x29, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x28, 0x29, 0x3b,
0x3b, 0xa, 0x9, 0x9, 0x9, 0x9, 0x7d, 0x20, 0x65, 0x6c, 0x20, 0x70, 0x72, 0x65, 0x73, 0x73, 0x4b, 0x65, 0x79, 0x28,
0x73, 0x65, 0x20, 0x7b, 0xa, 0x9, 0x9, 0x9, 0x9, 0x9, 0x6b, 0x65, 0x79, 0x2e, 0x69, 0x64, 0x2c, 0x20, 0x74, 0x72,
0x6e, 0x65, 0x77, 0x44, 0x69, 0x76, 0x2e, 0x61, 0x64, 0x64, 0x75, 0x65, 0x29, 0x3b, 0x20, 0x7d, 0x29, 0x3b, 0xa, 0x9,
0x45, 0x76, 0x65, 0x6e, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x65,
0x6e, 0x65, 0x72, 0x28, 0x22, 0x74, 0x6f, 0x75, 0x63, 0x68,
0x73, 0x74, 0x61, 0x72, 0x74, 0x22, 0x2c, 0x20, 0x66, 0x75,
0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x28, 0x65, 0x76,
0x65, 0x6e, 0x74, 0x29, 0x20, 0x7b, 0xa, 0x9, 0x9, 0x9,
0x9, 0x9, 0x9, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x2e, 0x70,
0x72, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x44, 0x65, 0x66, 0x61,
0x75, 0x6c, 0x74, 0x28, 0x29, 0x3b, 0x20, 0x70, 0x72, 0x65,
0x73, 0x73, 0x4b, 0x65, 0x79, 0x28, 0x6b, 0x65, 0x79, 0x2e,
0x69, 0x64, 0x29, 0x3b, 0x20, 0x7d, 0x29, 0x3b, 0xa, 0x9,
0x9, 0x9, 0x9, 0x9, 0x6e, 0x65, 0x77, 0x44, 0x69, 0x76, 0x9, 0x9, 0x9, 0x9, 0x6e, 0x65, 0x77, 0x44, 0x69, 0x76,
0x2e, 0x61, 0x64, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x4c, 0x2e, 0x61, 0x64, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x4c,
0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x28, 0x22, 0x74, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x28, 0x22, 0x74,
@@ -1293,219 +1257,262 @@ static const unsigned char data_index_html[] = {
0x2e, 0x70, 0x72, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x44, 0x65, 0x2e, 0x70, 0x72, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x44, 0x65,
0x66, 0x61, 0x75, 0x6c, 0x74, 0x28, 0x29, 0x3b, 0x20, 0x72, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x28, 0x29, 0x3b, 0x20, 0x72,
0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x4b, 0x65, 0x79, 0x28, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x4b, 0x65, 0x79, 0x28,
0x6b, 0x65, 0x79, 0x2e, 0x69, 0x64, 0x29, 0x3b, 0x20, 0x7d, 0x6b, 0x65, 0x79, 0x2e, 0x69, 0x64, 0x2c, 0x20, 0x74, 0x72,
0x29, 0x3b, 0xa, 0x9, 0x9, 0x9, 0x9, 0x9, 0x6e, 0x65, 0x75, 0x65, 0x29, 0x3b, 0x20, 0x7d, 0x29, 0x3b, 0xa, 0x9,
0x77, 0x44, 0x69, 0x76, 0x2e, 0x61, 0x64, 0x64, 0x45, 0x76, 0x9, 0x9, 0x9, 0x9, 0x6e, 0x65, 0x77, 0x44, 0x69, 0x76,
0x65, 0x6e, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x2e, 0x61, 0x64, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x4c,
0x72, 0x28, 0x22, 0x6d, 0x6f, 0x75, 0x73, 0x65, 0x64, 0x6f, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x28, 0x22, 0x6d,
0x77, 0x6e, 0x22, 0x2c, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x6f, 0x75, 0x73, 0x65, 0x64, 0x6f, 0x77, 0x6e, 0x22, 0x2c,
0x69, 0x6f, 0x6e, 0x20, 0x28, 0x29, 0x20, 0x7b, 0xa, 0x9, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20,
0x9, 0x9, 0x9, 0x9, 0x9, 0x70, 0x72, 0x65, 0x73, 0x73, 0x28, 0x29, 0x20, 0x7b, 0xa, 0x9, 0x9, 0x9, 0x9, 0x9,
0x4b, 0x65, 0x79, 0x28, 0x6b, 0x65, 0x79, 0x2e, 0x69, 0x64, 0x9, 0x70, 0x72, 0x65, 0x73, 0x73, 0x4b, 0x65, 0x79, 0x28,
0x29, 0x3b, 0x20, 0x7d, 0x29, 0x3b, 0xa, 0x9, 0x9, 0x9, 0x6b, 0x65, 0x79, 0x2e, 0x69, 0x64, 0x2c, 0x20, 0x74, 0x72,
0x9, 0x9, 0x6e, 0x65, 0x77, 0x44, 0x69, 0x76, 0x2e, 0x61, 0x75, 0x65, 0x29, 0x3b, 0x20, 0x7d, 0x29, 0x3b, 0xa, 0x9,
0x64, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x4c, 0x69, 0x73, 0x9, 0x9, 0x9, 0x9, 0x6e, 0x65, 0x77, 0x44, 0x69, 0x76,
0x74, 0x65, 0x6e, 0x65, 0x72, 0x28, 0x22, 0x6d, 0x6f, 0x75, 0x2e, 0x61, 0x64, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x4c,
0x73, 0x65, 0x75, 0x70, 0x22, 0x2c, 0x20, 0x66, 0x75, 0x6e, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x28, 0x22, 0x6d,
0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x28, 0x29, 0x20, 0x7b, 0x6f, 0x75, 0x73, 0x65, 0x75, 0x70, 0x22, 0x2c, 0x20, 0x66,
0xa, 0x9, 0x9, 0x9, 0x9, 0x9, 0x9, 0x72, 0x65, 0x6c, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x28, 0x29,
0x65, 0x61, 0x73, 0x65, 0x4b, 0x65, 0x79, 0x28, 0x6b, 0x65, 0x20, 0x7b, 0xa, 0x9, 0x9, 0x9, 0x9, 0x9, 0x9, 0x72,
0x79, 0x2e, 0x69, 0x64, 0x29, 0x3b, 0x20, 0x7d, 0x29, 0x3b, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x4b, 0x65, 0x79, 0x28,
0xa, 0x9, 0x9, 0x9, 0x9, 0x7d, 0xa, 0x9, 0x9, 0x9, 0x6b, 0x65, 0x79, 0x2e, 0x69, 0x64, 0x2c, 0x20, 0x74, 0x72,
0x7d, 0x20, 0x65, 0x6c, 0x73, 0x65, 0x20, 0x7b, 0xa, 0x9, 0x75, 0x65, 0x29, 0x3b, 0x20, 0x7d, 0x29, 0x3b, 0xa, 0x9,
0x9, 0x9, 0x9, 0x6e, 0x65, 0x77, 0x44, 0x69, 0x76, 0x2e, 0x9, 0x9, 0x9, 0x7d, 0x20, 0x65, 0x6c, 0x73, 0x65, 0x20,
0x63, 0x6c, 0x61, 0x73, 0x73, 0x4e, 0x61, 0x6d, 0x65, 0x20, 0x7b, 0xa, 0x9, 0x9, 0x9, 0x9, 0x9, 0x6e, 0x65, 0x77,
0x3d, 0x20, 0x22, 0x6b, 0x65, 0x79, 0x20, 0x62, 0x6c, 0x61,
0x6e, 0x6b, 0x22, 0x3b, 0xa, 0x9, 0x9, 0x9, 0x7d, 0xa,
0x9, 0x9, 0x9, 0x6e, 0x65, 0x77, 0x52, 0x6f, 0x77, 0x2e,
0x61, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x43, 0x68, 0x69, 0x6c,
0x64, 0x28, 0x6e, 0x65, 0x77, 0x44, 0x69, 0x76, 0x29, 0x3b,
0xa, 0x9, 0x9, 0x9, 0x69, 0x66, 0x20, 0x28, 0x6b, 0x65,
0x79, 0x2e, 0x77, 0x69, 0x64, 0x74, 0x68, 0x29, 0x20, 0x7b,
0xa, 0x9, 0x9, 0x9, 0x9, 0x6e, 0x65, 0x77, 0x44, 0x69,
0x76, 0x2e, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x20, 0x3d, 0x20,
0x22, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3a, 0x22, 0x20, 0x2b,
0x20, 0x28, 0x6b, 0x65, 0x79, 0x2e, 0x77, 0x69, 0x64, 0x74,
0x68, 0x2a, 0x6e, 0x65, 0x77, 0x44, 0x69, 0x76, 0x2e, 0x63,
0x6c, 0x69, 0x65, 0x6e, 0x74, 0x57, 0x69, 0x64, 0x74, 0x68,
0x20, 0x29, 0x20, 0x2b, 0x20, 0x22, 0x70, 0x78, 0x3b, 0x22,
0x3b, 0xa, 0x9, 0x9, 0x9, 0x7d, 0xa, 0x9, 0x9, 0x9,
0x69, 0x66, 0x20, 0x28, 0x6b, 0x65, 0x79, 0x2e, 0x68, 0x65,
0x69, 0x67, 0x68, 0x74, 0x29, 0x20, 0x7b, 0xa, 0x9, 0x9,
0x9, 0x9, 0x6e, 0x65, 0x77, 0x44, 0x69, 0x76, 0x2e, 0x73,
0x74, 0x79, 0x6c, 0x65, 0x20, 0x3d, 0x20, 0x22, 0x68, 0x65,
0x69, 0x67, 0x68, 0x74, 0x3a, 0x22, 0x20, 0x2b, 0x20, 0x28,
0x6b, 0x65, 0x79, 0x2e, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74,
0x2a, 0x6e, 0x65, 0x77, 0x44, 0x69, 0x76, 0x2e, 0x63, 0x6c,
0x69, 0x65, 0x6e, 0x74, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74,
0x20, 0x29, 0x20, 0x2b, 0x20, 0x22, 0x70, 0x78, 0x3b, 0x20,
0x66, 0x6c, 0x6f, 0x61, 0x74, 0x3a, 0x20, 0x72, 0x69, 0x67,
0x68, 0x74, 0x3b, 0x22, 0x3b, 0xa, 0x9, 0x9, 0x9, 0x7d,
0xa, 0x9, 0x9, 0x7d, 0xa, 0x9, 0x7d, 0xa, 0x7d, 0xa,
0xa, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20,
0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x72,
0x6f, 0x73, 0x28, 0x6d, 0x61, 0x63, 0x72, 0x6f, 0x5f, 0x69,
0x64, 0x29, 0x20, 0x7b, 0xa, 0x9, 0x6c, 0x65, 0x74, 0x20,
0x6d, 0x61, 0x63, 0x72, 0x6f, 0x44, 0x69, 0x76, 0x20, 0x3d,
0x20, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e,
0x67, 0x65, 0x74, 0x45, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74,
0x42, 0x79, 0x49, 0x64, 0x28, 0x6d, 0x61, 0x63, 0x72, 0x6f,
0x5f, 0x69, 0x64, 0x29, 0x3b, 0xa, 0x9, 0x66, 0x6f, 0x72,
0x20, 0x28, 0x6c, 0x65, 0x74, 0x20, 0x6d, 0x61, 0x63, 0x72,
0x6f, 0x20, 0x6f, 0x66, 0x20, 0x6d, 0x61, 0x63, 0x72, 0x6f,
0x5f, 0x6c, 0x69, 0x73, 0x74, 0x29, 0x20, 0x7b, 0xa, 0x9,
0x9, 0x6c, 0x65, 0x74, 0x20, 0x6e, 0x65, 0x77, 0x44, 0x69,
0x76, 0x20, 0x3d, 0x20, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65,
0x6e, 0x74, 0x2e, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x45,
0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x28, 0x22, 0x64, 0x69,
0x76, 0x22, 0x29, 0x3b, 0xa, 0x9, 0x9, 0x6e, 0x65, 0x77,
0x44, 0x69, 0x76, 0x2e, 0x69, 0x64, 0x20, 0x3d, 0x20, 0x6d,
0x61, 0x63, 0x72, 0x6f, 0x2e, 0x69, 0x64, 0x3b, 0xa, 0x9,
0x9, 0x6e, 0x65, 0x77, 0x44, 0x69, 0x76, 0x2e, 0x74, 0x65,
0x78, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x20,
0x3d, 0x20, 0x6d, 0x61, 0x63, 0x72, 0x6f, 0x2e, 0x6c, 0x61,
0x62, 0x65, 0x6c, 0x3b, 0xa, 0x9, 0x9, 0x6e, 0x65, 0x77,
0x44, 0x69, 0x76, 0x2e, 0x61, 0x64, 0x64, 0x45, 0x76, 0x65, 0x44, 0x69, 0x76, 0x2e, 0x61, 0x64, 0x64, 0x45, 0x76, 0x65,
0x6e, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x6e, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72,
0x28, 0x22, 0x74, 0x6f, 0x75, 0x63, 0x68, 0x73, 0x74, 0x61, 0x28, 0x22, 0x74, 0x6f, 0x75, 0x63, 0x68, 0x73, 0x74, 0x61,
0x72, 0x74, 0x22, 0x2c, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x72, 0x74, 0x22, 0x2c, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74,
0x69, 0x6f, 0x6e, 0x20, 0x28, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x28, 0x65, 0x76, 0x65, 0x6e, 0x74,
0x29, 0x20, 0x7b, 0xa, 0x9, 0x9, 0x9, 0x65, 0x76, 0x65, 0x29, 0x20, 0x7b, 0xa, 0x9, 0x9, 0x9, 0x9, 0x9, 0x9,
0x6e, 0x74, 0x2e, 0x70, 0x72, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x72, 0x65, 0x76,
0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x28, 0x29, 0x3b, 0x65, 0x6e, 0x74, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74,
0x20, 0x73, 0x65, 0x6e, 0x64, 0x4b, 0x65, 0x79, 0x73, 0x28, 0x28, 0x29, 0x3b, 0x20, 0x70, 0x72, 0x65, 0x73, 0x73, 0x4b,
0x6d, 0x61, 0x63, 0x72, 0x6f, 0x2e, 0x6b, 0x65, 0x79, 0x73, 0x65, 0x79, 0x28, 0x6b, 0x65, 0x79, 0x2e, 0x69, 0x64, 0x29,
0x29, 0x3b, 0x20, 0x7d, 0x29, 0x3b, 0xa, 0x9, 0x9, 0x6e, 0x3b, 0x20, 0x7d, 0x29, 0x3b, 0xa, 0x9, 0x9, 0x9, 0x9,
0x9, 0x6e, 0x65, 0x77, 0x44, 0x69, 0x76, 0x2e, 0x61, 0x64,
0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x4c, 0x69, 0x73, 0x74,
0x65, 0x6e, 0x65, 0x72, 0x28, 0x22, 0x74, 0x6f, 0x75, 0x63,
0x68, 0x65, 0x6e, 0x64, 0x22, 0x2c, 0x20, 0x66, 0x75, 0x6e,
0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x28, 0x65, 0x76, 0x65,
0x6e, 0x74, 0x29, 0x20, 0x7b, 0xa, 0x9, 0x9, 0x9, 0x9,
0x9, 0x9, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x72,
0x65, 0x76, 0x65, 0x6e, 0x74, 0x44, 0x65, 0x66, 0x61, 0x75,
0x6c, 0x74, 0x28, 0x29, 0x3b, 0x20, 0x72, 0x65, 0x6c, 0x65,
0x61, 0x73, 0x65, 0x4b, 0x65, 0x79, 0x28, 0x6b, 0x65, 0x79,
0x2e, 0x69, 0x64, 0x29, 0x3b, 0x20, 0x7d, 0x29, 0x3b, 0xa,
0x9, 0x9, 0x9, 0x9, 0x9, 0x6e, 0x65, 0x77, 0x44, 0x69,
0x76, 0x2e, 0x61, 0x64, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74,
0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x28, 0x22,
0x6d, 0x6f, 0x75, 0x73, 0x65, 0x64, 0x6f, 0x77, 0x6e, 0x22,
0x2c, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e,
0x20, 0x28, 0x29, 0x20, 0x7b, 0xa, 0x9, 0x9, 0x9, 0x9,
0x9, 0x9, 0x70, 0x72, 0x65, 0x73, 0x73, 0x4b, 0x65, 0x79,
0x28, 0x6b, 0x65, 0x79, 0x2e, 0x69, 0x64, 0x29, 0x3b, 0x20,
0x7d, 0x29, 0x3b, 0xa, 0x9, 0x9, 0x9, 0x9, 0x9, 0x6e,
0x65, 0x77, 0x44, 0x69, 0x76, 0x2e, 0x61, 0x64, 0x64, 0x45, 0x65, 0x77, 0x44, 0x69, 0x76, 0x2e, 0x61, 0x64, 0x64, 0x45,
0x76, 0x65, 0x6e, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x76, 0x65, 0x6e, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e,
0x65, 0x72, 0x28, 0x22, 0x74, 0x6f, 0x75, 0x63, 0x68, 0x65, 0x65, 0x72, 0x28, 0x22, 0x6d, 0x6f, 0x75, 0x73, 0x65, 0x75,
0x6e, 0x64, 0x22, 0x2c, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x70, 0x22, 0x2c, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69,
0x69, 0x6f, 0x6e, 0x20, 0x28, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x6f, 0x6e, 0x20, 0x28, 0x29, 0x20, 0x7b, 0xa, 0x9, 0x9,
0x29, 0x20, 0x7b, 0xa, 0x9, 0x9, 0x9, 0x65, 0x76, 0x65, 0x9, 0x9, 0x9, 0x9, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73,
0x6e, 0x74, 0x2e, 0x70, 0x72, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x28, 0x6b, 0x65, 0x79, 0x2e, 0x69,
0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x28, 0x29, 0x3b, 0x64, 0x29, 0x3b, 0x20, 0x7d, 0x29, 0x3b, 0xa, 0x9, 0x9,
0x20, 0x73, 0x65, 0x6e, 0x64, 0x4b, 0x65, 0x79, 0x73, 0x28, 0x9, 0x9, 0x7d, 0xa, 0x9, 0x9, 0x9, 0x7d, 0x20, 0x65,
0x5b, 0x5d, 0x29, 0x3b, 0x3b, 0x20, 0x7d, 0x29, 0x3b, 0xa, 0x6c, 0x73, 0x65, 0x20, 0x7b, 0xa, 0x9, 0x9, 0x9, 0x9,
0x9, 0x9, 0x6e, 0x65, 0x77, 0x44, 0x69, 0x76, 0x2e, 0x61,
0x64, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x4c, 0x69, 0x73,
0x74, 0x65, 0x6e, 0x65, 0x72, 0x28, 0x22, 0x6d, 0x6f, 0x75,
0x73, 0x65, 0x64, 0x6f, 0x77, 0x6e, 0x22, 0x2c, 0x20, 0x66,
0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x28, 0x29,
0x20, 0x7b, 0xa, 0x9, 0x9, 0x9, 0x73, 0x65, 0x6e, 0x64,
0x4b, 0x65, 0x79, 0x73, 0x28, 0x6d, 0x61, 0x63, 0x72, 0x6f,
0x2e, 0x6b, 0x65, 0x79, 0x73, 0x29, 0x3b, 0x20, 0x7d, 0x29,
0x3b, 0xa, 0x9, 0x9, 0x6e, 0x65, 0x77, 0x44, 0x69, 0x76,
0x2e, 0x61, 0x64, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x4c,
0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x28, 0x22, 0x6d,
0x6f, 0x75, 0x73, 0x65, 0x75, 0x70, 0x22, 0x2c, 0x20, 0x66,
0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x28, 0x29,
0x20, 0x7b, 0xa, 0x9, 0x9, 0x9, 0x73, 0x65, 0x6e, 0x64,
0x4b, 0x65, 0x79, 0x73, 0x28, 0x5b, 0x5d, 0x29, 0x3b, 0x20,
0x7d, 0x29, 0x3b, 0xa, 0x9, 0x9, 0x6d, 0x61, 0x63, 0x72,
0x6f, 0x44, 0x69, 0x76, 0x2e, 0x61, 0x70, 0x70, 0x65, 0x6e,
0x64, 0x43, 0x68, 0x69, 0x6c, 0x64, 0x28, 0x6e, 0x65, 0x77,
0x44, 0x69, 0x76, 0x29, 0x3b, 0xa, 0x9, 0x7d, 0xa, 0x7d,
0xa, 0xa, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e,
0x20, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x49, 0x6e, 0x64,
0x69, 0x63, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x28, 0x69, 0x6e,
0x64, 0x69, 0x63, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x69, 0x64,
0x29, 0x20, 0x7b, 0xa, 0x9, 0x6c, 0x65, 0x74, 0x20, 0x69,
0x6e, 0x64, 0x69, 0x63, 0x61, 0x74, 0x6f, 0x72, 0x44, 0x69,
0x76, 0x20, 0x3d, 0x20, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65,
0x6e, 0x74, 0x2e, 0x67, 0x65, 0x74, 0x45, 0x6c, 0x65, 0x6d,
0x65, 0x6e, 0x74, 0x42, 0x79, 0x49, 0x64, 0x28, 0x69, 0x6e,
0x64, 0x69, 0x63, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x69, 0x64,
0x29, 0x3b, 0xa, 0x9, 0x66, 0x6f, 0x72, 0x20, 0x28, 0x6c,
0x65, 0x74, 0x20, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x61, 0x74,
0x6f, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x69, 0x6e, 0x64, 0x69,
0x63, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x6c, 0x69, 0x73, 0x74,
0x29, 0x20, 0x7b, 0xa, 0x9, 0x9, 0x6c, 0x65, 0x74, 0x20,
0x6e, 0x65, 0x77, 0x44, 0x69, 0x76, 0x20, 0x3d, 0x20, 0x64,
0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x63, 0x72,
0x65, 0x61, 0x74, 0x65, 0x45, 0x6c, 0x65, 0x6d, 0x65, 0x6e,
0x74, 0x28, 0x22, 0x64, 0x69, 0x76, 0x22, 0x29, 0x3b, 0xa,
0x9, 0x9, 0x6e, 0x65, 0x77, 0x44, 0x69, 0x76, 0x2e, 0x69,
0x64, 0x20, 0x3d, 0x20, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x61,
0x74, 0x6f, 0x72, 0x2e, 0x69, 0x64, 0x3b, 0xa, 0x9, 0x9,
0x6e, 0x65, 0x77, 0x44, 0x69, 0x76, 0x2e, 0x74, 0x65, 0x78,
0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x20, 0x3d,
0x20, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x61, 0x74, 0x6f, 0x72,
0x2e, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x3b, 0xa, 0x9, 0x9,
0x6e, 0x65, 0x77, 0x44, 0x69, 0x76, 0x2e, 0x63, 0x6c, 0x61, 0x6e, 0x65, 0x77, 0x44, 0x69, 0x76, 0x2e, 0x63, 0x6c, 0x61,
0x73, 0x73, 0x4e, 0x61, 0x6d, 0x65, 0x20, 0x3d, 0x20, 0x22, 0x73, 0x73, 0x4e, 0x61, 0x6d, 0x65, 0x20, 0x3d, 0x20, 0x22,
0x6f, 0x66, 0x66, 0x22, 0x3b, 0xa, 0x9, 0x9, 0x69, 0x6e, 0x6b, 0x65, 0x79, 0x20, 0x62, 0x6c, 0x61, 0x6e, 0x6b, 0x22,
0x64, 0x69, 0x63, 0x61, 0x74, 0x6f, 0x72, 0x44, 0x69, 0x76, 0x3b, 0xa, 0x9, 0x9, 0x9, 0x7d, 0xa, 0x9, 0x9, 0x9,
0x2e, 0x61, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x43, 0x68, 0x69, 0x6e, 0x65, 0x77, 0x52, 0x6f, 0x77, 0x2e, 0x61, 0x70, 0x70,
0x6c, 0x64, 0x28, 0x6e, 0x65, 0x77, 0x44, 0x69, 0x76, 0x29, 0x65, 0x6e, 0x64, 0x43, 0x68, 0x69, 0x6c, 0x64, 0x28, 0x6e,
0x3b, 0xa, 0x9, 0x7d, 0xa, 0x7d, 0xa, 0xa, 0x66, 0x75, 0x65, 0x77, 0x44, 0x69, 0x76, 0x29, 0x3b, 0xa, 0x9, 0x9,
0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x75, 0x70, 0x64, 0x9, 0x69, 0x66, 0x20, 0x28, 0x6b, 0x65, 0x79, 0x2e, 0x77,
0x61, 0x74, 0x65, 0x4c, 0x45, 0x44, 0x73, 0x28, 0x63, 0x75, 0x69, 0x64, 0x74, 0x68, 0x29, 0x20, 0x7b, 0xa, 0x9, 0x9,
0x72, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x29, 0x20, 0x7b, 0x9, 0x9, 0x6e, 0x65, 0x77, 0x44, 0x69, 0x76, 0x2e, 0x73,
0xa, 0x9, 0x6c, 0x65, 0x74, 0x20, 0x6f, 0x6e, 0x5f, 0x6c, 0x74, 0x79, 0x6c, 0x65, 0x20, 0x3d, 0x20, 0x22, 0x77, 0x69,
0x65, 0x64, 0x73, 0x20, 0x3d, 0x20, 0x63, 0x75, 0x72, 0x5f, 0x64, 0x74, 0x68, 0x3a, 0x22, 0x20, 0x2b, 0x20, 0x28, 0x6b,
0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x73, 0x70, 0x6c, 0x69, 0x65, 0x79, 0x2e, 0x77, 0x69, 0x64, 0x74, 0x68, 0x2a, 0x6e,
0x74, 0x28, 0x22, 0x2c, 0x22, 0x29, 0x3b, 0xa, 0x9, 0x66, 0x65, 0x77, 0x44, 0x69, 0x76, 0x2e, 0x63, 0x6c, 0x69, 0x65,
0x6f, 0x72, 0x20, 0x28, 0x6c, 0x65, 0x74, 0x20, 0x69, 0x6e, 0x6e, 0x74, 0x57, 0x69, 0x64, 0x74, 0x68, 0x20, 0x29, 0x20,
0x64, 0x69, 0x63, 0x61, 0x74, 0x6f, 0x72, 0x20, 0x6f, 0x66, 0x2b, 0x20, 0x22, 0x70, 0x78, 0x3b, 0x22, 0x3b, 0xa, 0x9,
0x20, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x61, 0x74, 0x6f, 0x72, 0x9, 0x9, 0x7d, 0xa, 0x9, 0x9, 0x9, 0x69, 0x66, 0x20,
0x5f, 0x6c, 0x69, 0x73, 0x74, 0x29, 0x20, 0x7b, 0xa, 0x9, 0x28, 0x6b, 0x65, 0x79, 0x2e, 0x68, 0x65, 0x69, 0x67, 0x68,
0x9, 0x6c, 0x65, 0x74, 0x20, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x74, 0x29, 0x20, 0x7b, 0xa, 0x9, 0x9, 0x9, 0x9, 0x6e,
0x61, 0x74, 0x6f, 0x72, 0x5f, 0x64, 0x69, 0x76, 0x20, 0x3d, 0x65, 0x77, 0x44, 0x69, 0x76, 0x2e, 0x73, 0x74, 0x79, 0x6c,
0x65, 0x20, 0x3d, 0x20, 0x22, 0x68, 0x65, 0x69, 0x67, 0x68,
0x74, 0x3a, 0x22, 0x20, 0x2b, 0x20, 0x28, 0x6b, 0x65, 0x79,
0x2e, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x2a, 0x6e, 0x65,
0x77, 0x44, 0x69, 0x76, 0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e,
0x74, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x20, 0x29, 0x20,
0x2b, 0x20, 0x22, 0x70, 0x78, 0x3b, 0x20, 0x66, 0x6c, 0x6f,
0x61, 0x74, 0x3a, 0x20, 0x72, 0x69, 0x67, 0x68, 0x74, 0x3b,
0x22, 0x3b, 0xa, 0x9, 0x9, 0x9, 0x7d, 0xa, 0x9, 0x9,
0x7d, 0xa, 0x9, 0x7d, 0xa, 0x7d, 0xa, 0xa, 0x66, 0x75,
0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x63, 0x72, 0x65,
0x61, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x72, 0x6f, 0x73, 0x28,
0x6d, 0x61, 0x63, 0x72, 0x6f, 0x5f, 0x69, 0x64, 0x29, 0x20,
0x7b, 0xa, 0x9, 0x6c, 0x65, 0x74, 0x20, 0x6d, 0x61, 0x63,
0x72, 0x6f, 0x44, 0x69, 0x76, 0x20, 0x3d, 0x20, 0x64, 0x6f,
0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x67, 0x65, 0x74,
0x45, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x42, 0x79, 0x49,
0x64, 0x28, 0x6d, 0x61, 0x63, 0x72, 0x6f, 0x5f, 0x69, 0x64,
0x29, 0x3b, 0xa, 0x9, 0x66, 0x6f, 0x72, 0x20, 0x28, 0x6c,
0x65, 0x74, 0x20, 0x6d, 0x61, 0x63, 0x72, 0x6f, 0x20, 0x6f,
0x66, 0x20, 0x6d, 0x61, 0x63, 0x72, 0x6f, 0x5f, 0x6c, 0x69,
0x73, 0x74, 0x29, 0x20, 0x7b, 0xa, 0x9, 0x9, 0x6c, 0x65,
0x74, 0x20, 0x6e, 0x65, 0x77, 0x44, 0x69, 0x76, 0x20, 0x3d,
0x20, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e,
0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x45, 0x6c, 0x65, 0x6d,
0x65, 0x6e, 0x74, 0x28, 0x22, 0x64, 0x69, 0x76, 0x22, 0x29,
0x3b, 0xa, 0x9, 0x9, 0x6e, 0x65, 0x77, 0x44, 0x69, 0x76,
0x2e, 0x69, 0x64, 0x20, 0x3d, 0x20, 0x6d, 0x61, 0x63, 0x72,
0x6f, 0x2e, 0x69, 0x64, 0x3b, 0xa, 0x9, 0x9, 0x6e, 0x65,
0x77, 0x44, 0x69, 0x76, 0x2e, 0x74, 0x65, 0x78, 0x74, 0x43,
0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x20, 0x3d, 0x20, 0x6d,
0x61, 0x63, 0x72, 0x6f, 0x2e, 0x6c, 0x61, 0x62, 0x65, 0x6c,
0x3b, 0xa, 0x9, 0x9, 0x6e, 0x65, 0x77, 0x44, 0x69, 0x76,
0x2e, 0x61, 0x64, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x4c,
0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x28, 0x22, 0x74,
0x6f, 0x75, 0x63, 0x68, 0x73, 0x74, 0x61, 0x72, 0x74, 0x22,
0x2c, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e,
0x20, 0x28, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x29, 0x20, 0x7b,
0xa, 0x9, 0x9, 0x9, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x2e,
0x70, 0x72, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x44, 0x65, 0x66,
0x61, 0x75, 0x6c, 0x74, 0x28, 0x29, 0x3b, 0x20, 0x73, 0x65,
0x6e, 0x64, 0x4b, 0x65, 0x79, 0x73, 0x28, 0x6d, 0x61, 0x63,
0x72, 0x6f, 0x2e, 0x6b, 0x65, 0x79, 0x73, 0x29, 0x3b, 0x20,
0x7d, 0x29, 0x3b, 0xa, 0x9, 0x9, 0x6e, 0x65, 0x77, 0x44,
0x69, 0x76, 0x2e, 0x61, 0x64, 0x64, 0x45, 0x76, 0x65, 0x6e,
0x74, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x28,
0x22, 0x74, 0x6f, 0x75, 0x63, 0x68, 0x65, 0x6e, 0x64, 0x22,
0x2c, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e,
0x20, 0x28, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x29, 0x20, 0x7b,
0xa, 0x9, 0x9, 0x9, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x2e,
0x70, 0x72, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x44, 0x65, 0x66,
0x61, 0x75, 0x6c, 0x74, 0x28, 0x29, 0x3b, 0x20, 0x73, 0x65,
0x6e, 0x64, 0x4b, 0x65, 0x79, 0x73, 0x28, 0x5b, 0x5d, 0x29,
0x3b, 0x3b, 0x20, 0x7d, 0x29, 0x3b, 0xa, 0x9, 0x9, 0x6e,
0x65, 0x77, 0x44, 0x69, 0x76, 0x2e, 0x61, 0x64, 0x64, 0x45,
0x76, 0x65, 0x6e, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e,
0x65, 0x72, 0x28, 0x22, 0x6d, 0x6f, 0x75, 0x73, 0x65, 0x64,
0x6f, 0x77, 0x6e, 0x22, 0x2c, 0x20, 0x66, 0x75, 0x6e, 0x63,
0x74, 0x69, 0x6f, 0x6e, 0x20, 0x28, 0x29, 0x20, 0x7b, 0xa,
0x9, 0x9, 0x9, 0x73, 0x65, 0x6e, 0x64, 0x4b, 0x65, 0x79,
0x73, 0x28, 0x6d, 0x61, 0x63, 0x72, 0x6f, 0x2e, 0x6b, 0x65,
0x79, 0x73, 0x29, 0x3b, 0x20, 0x7d, 0x29, 0x3b, 0xa, 0x9,
0x9, 0x6e, 0x65, 0x77, 0x44, 0x69, 0x76, 0x2e, 0x61, 0x64,
0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x4c, 0x69, 0x73, 0x74,
0x65, 0x6e, 0x65, 0x72, 0x28, 0x22, 0x6d, 0x6f, 0x75, 0x73,
0x65, 0x75, 0x70, 0x22, 0x2c, 0x20, 0x66, 0x75, 0x6e, 0x63,
0x74, 0x69, 0x6f, 0x6e, 0x20, 0x28, 0x29, 0x20, 0x7b, 0xa,
0x9, 0x9, 0x9, 0x73, 0x65, 0x6e, 0x64, 0x4b, 0x65, 0x79,
0x73, 0x28, 0x5b, 0x5d, 0x29, 0x3b, 0x20, 0x7d, 0x29, 0x3b,
0xa, 0x9, 0x9, 0x6d, 0x61, 0x63, 0x72, 0x6f, 0x44, 0x69,
0x76, 0x2e, 0x61, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x43, 0x68,
0x69, 0x6c, 0x64, 0x28, 0x6e, 0x65, 0x77, 0x44, 0x69, 0x76,
0x29, 0x3b, 0xa, 0x9, 0x7d, 0xa, 0x7d, 0xa, 0xa, 0x66,
0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x63, 0x72,
0x65, 0x61, 0x74, 0x65, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x61,
0x74, 0x6f, 0x72, 0x73, 0x28, 0x69, 0x6e, 0x64, 0x69, 0x63,
0x61, 0x74, 0x6f, 0x72, 0x5f, 0x69, 0x64, 0x29, 0x20, 0x7b,
0xa, 0x9, 0x6c, 0x65, 0x74, 0x20, 0x69, 0x6e, 0x64, 0x69,
0x63, 0x61, 0x74, 0x6f, 0x72, 0x44, 0x69, 0x76, 0x20, 0x3d,
0x20, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x20, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e,
0x67, 0x65, 0x74, 0x45, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x67, 0x65, 0x74, 0x45, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74,
0x42, 0x79, 0x49, 0x64, 0x28, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x42, 0x79, 0x49, 0x64, 0x28, 0x69, 0x6e, 0x64, 0x69, 0x63,
0x61, 0x74, 0x6f, 0x72, 0x2e, 0x69, 0x64, 0x29, 0x3b, 0xa, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x69, 0x64, 0x29, 0x3b, 0xa,
0x9, 0x9, 0x69, 0x66, 0x20, 0x28, 0x6f, 0x6e, 0x5f, 0x6c, 0x9, 0x66, 0x6f, 0x72, 0x20, 0x28, 0x6c, 0x65, 0x74, 0x20,
0x65, 0x64, 0x73, 0x2e, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x61, 0x74, 0x6f, 0x72, 0x20,
0x65, 0x73, 0x28, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x61, 0x74, 0x6f, 0x66, 0x20, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x61, 0x74,
0x6f, 0x72, 0x2e, 0x69, 0x64, 0x29, 0x29, 0x20, 0x7b, 0xa, 0x6f, 0x72, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x29, 0x20, 0x7b,
0x9, 0x9, 0x9, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x61, 0x74, 0xa, 0x9, 0x9, 0x6c, 0x65, 0x74, 0x20, 0x6e, 0x65, 0x77,
0x6f, 0x72, 0x5f, 0x64, 0x69, 0x76, 0x2e, 0x63, 0x6c, 0x61, 0x44, 0x69, 0x76, 0x20, 0x3d, 0x20, 0x64, 0x6f, 0x63, 0x75,
0x73, 0x73, 0x4e, 0x61, 0x6d, 0x65, 0x20, 0x3d, 0x20, 0x22, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x63, 0x72, 0x65, 0x61, 0x74,
0x6f, 0x6e, 0x22, 0x3b, 0xa, 0x9, 0x9, 0x7d, 0x20, 0x65, 0x65, 0x45, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x28, 0x22,
0x6c, 0x73, 0x65, 0x20, 0x7b, 0xa, 0x9, 0x9, 0x9, 0x69, 0x64, 0x69, 0x76, 0x22, 0x29, 0x3b, 0xa, 0x9, 0x9, 0x6e,
0x6e, 0x64, 0x69, 0x63, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x64, 0x65, 0x77, 0x44, 0x69, 0x76, 0x2e, 0x69, 0x64, 0x20, 0x3d,
0x69, 0x76, 0x2e, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x4e, 0x61, 0x20, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x61, 0x74, 0x6f, 0x72,
0x6d, 0x65, 0x20, 0x3d, 0x20, 0x22, 0x6f, 0x66, 0x66, 0x22, 0x2e, 0x69, 0x64, 0x3b, 0xa, 0x9, 0x9, 0x6e, 0x65, 0x77,
0x3b, 0xa, 0x9, 0x9, 0x7d, 0xa, 0x9, 0x7d, 0xa, 0x7d, 0x44, 0x69, 0x76, 0x2e, 0x74, 0x65, 0x78, 0x74, 0x43, 0x6f,
0xa, 0xa, 0x3c, 0x2f, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x20, 0x3d, 0x20, 0x69, 0x6e,
0x3e, 0xa, 0xa, 0x3c, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x3e, 0x64, 0x69, 0x63, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x6c, 0x61,
0xa, 0xa, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0xa, 0x3c, 0x62, 0x65, 0x6c, 0x3b, 0xa, 0x9, 0x9, 0x6e, 0x65, 0x77,
0x64, 0x69, 0x76, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x44, 0x69, 0x76, 0x2e, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x4e,
0x22, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x61, 0x6d, 0x65, 0x20, 0x3d, 0x20, 0x22, 0x6f, 0x66, 0x66,
0x22, 0x3e, 0xa, 0x9, 0x3c, 0x64, 0x69, 0x76, 0x20, 0x69, 0x22, 0x3b, 0xa, 0x9, 0x9, 0x69, 0x6e, 0x64, 0x69, 0x63,
0x64, 0x3d, 0x22, 0x6b, 0x65, 0x79, 0x62, 0x6f, 0x61, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x44, 0x69, 0x76, 0x2e, 0x61, 0x70,
0x64, 0x22, 0x3e, 0x3c, 0x2f, 0x64, 0x69, 0x76, 0x3e, 0xa, 0x70, 0x65, 0x6e, 0x64, 0x43, 0x68, 0x69, 0x6c, 0x64, 0x28,
0x9, 0x3c, 0x64, 0x69, 0x76, 0x3e, 0xa, 0x9, 0x9, 0x3c, 0x6e, 0x65, 0x77, 0x44, 0x69, 0x76, 0x29, 0x3b, 0xa, 0x9,
0x64, 0x69, 0x76, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x69, 0x6e, 0x7d, 0xa, 0x7d, 0xa, 0xa, 0x66, 0x75, 0x6e, 0x63, 0x74,
0x64, 0x69, 0x63, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x22, 0x3e, 0x69, 0x6f, 0x6e, 0x20, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65,
0x3c, 0x2f, 0x64, 0x69, 0x76, 0x3e, 0xa, 0x9, 0x9, 0x3c, 0x4c, 0x45, 0x44, 0x73, 0x28, 0x63, 0x75, 0x72, 0x5f, 0x73,
0x64, 0x69, 0x76, 0x3e, 0x4d, 0x6f, 0x75, 0x73, 0x65, 0x20, 0x74, 0x61, 0x74, 0x65, 0x29, 0x20, 0x7b, 0xa, 0x9, 0x6c,
0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x73, 0x3a, 0x3c, 0x65, 0x74, 0x20, 0x6f, 0x6e, 0x5f, 0x6c, 0x65, 0x64, 0x73,
0x2f, 0x64, 0x69, 0x76, 0x3e, 0xa, 0x9, 0x9, 0x3c, 0x64, 0x20, 0x3d, 0x20, 0x63, 0x75, 0x72, 0x5f, 0x73, 0x74, 0x61,
0x69, 0x76, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x6d, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x73, 0x70, 0x6c, 0x69, 0x74, 0x28, 0x22,
0x73, 0x65, 0x22, 0x3e, 0x3c, 0x2f, 0x64, 0x69, 0x76, 0x3e, 0x2c, 0x22, 0x29, 0x3b, 0xa, 0x9, 0x66, 0x6f, 0x72, 0x20,
0xa, 0x9, 0x3c, 0x2f, 0x64, 0x69, 0x76, 0x3e, 0xa, 0x3c, 0x28, 0x6c, 0x65, 0x74, 0x20, 0x69, 0x6e, 0x64, 0x69, 0x63,
0x2f, 0x64, 0x69, 0x76, 0x3e, 0xa, 0xa, 0x3c, 0x64, 0x69, 0x61, 0x74, 0x6f, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x69, 0x6e,
0x76, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x6d, 0x61, 0x63, 0x72, 0x64, 0x69, 0x63, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x6c, 0x69,
0x6f, 0x73, 0x22, 0x3e, 0x3c, 0x2f, 0x64, 0x69, 0x76, 0x3e, 0x73, 0x74, 0x29, 0x20, 0x7b, 0xa, 0x9, 0x9, 0x6c, 0x65,
0xa, 0xa, 0x3c, 0x64, 0x69, 0x76, 0x3e, 0xa, 0x9, 0x3c, 0x74, 0x20, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x61, 0x74, 0x6f,
0x64, 0x69, 0x76, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x72, 0x5f, 0x64, 0x69, 0x76, 0x20, 0x3d, 0x20, 0x64, 0x6f,
0x22, 0x6d, 0x65, 0x6e, 0x75, 0x22, 0x3e, 0xa, 0x9, 0x9, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x67, 0x65, 0x74,
0x3c, 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x77, 0x45, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x42, 0x79, 0x49,
0x69, 0x66, 0x69, 0x2e, 0x73, 0x68, 0x74, 0x6d, 0x6c, 0x22, 0x64, 0x28, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x61, 0x74, 0x6f,
0x3e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, 0x72, 0x2e, 0x69, 0x64, 0x29, 0x3b, 0xa, 0x9, 0x9, 0x69,
0x20, 0x57, 0x69, 0x2d, 0x46, 0x69, 0x3c, 0x2f, 0x61, 0x3e, 0x66, 0x20, 0x28, 0x6f, 0x6e, 0x5f, 0x6c, 0x65, 0x64, 0x73,
0xa, 0x9, 0x3c, 0x2f, 0x64, 0x69, 0x76, 0x3e, 0xa, 0x9, 0x2e, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x73, 0x28,
0x3c, 0x64, 0x69, 0x76, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x61, 0x74, 0x6f, 0x72, 0x2e,
0x3d, 0x22, 0x6d, 0x65, 0x6e, 0x75, 0x22, 0x3e, 0xa, 0x9, 0x69, 0x64, 0x29, 0x29, 0x20, 0x7b, 0xa, 0x9, 0x9, 0x9,
0x9, 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x61, 0x74, 0x6f, 0x72, 0x5f,
0x72, 0x65, 0x62, 0x6f, 0x6f, 0x74, 0x2e, 0x63, 0x67, 0x69, 0x64, 0x69, 0x76, 0x2e, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x4e,
0x22, 0x3e, 0x52, 0x65, 0x62, 0x6f, 0x6f, 0x74, 0x3c, 0x2f, 0x61, 0x6d, 0x65, 0x20, 0x3d, 0x20, 0x22, 0x6f, 0x6e, 0x22,
0x61, 0x3e, 0xa, 0x9, 0x3c, 0x2f, 0x64, 0x69, 0x76, 0x3e, 0x3b, 0xa, 0x9, 0x9, 0x7d, 0x20, 0x65, 0x6c, 0x73, 0x65,
0xa, 0x3c, 0x2f, 0x64, 0x69, 0x76, 0x3e, 0xa, 0xa, 0x3c, 0x20, 0x7b, 0xa, 0x9, 0x9, 0x9, 0x69, 0x6e, 0x64, 0x69,
0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0xa, 0xa, 0x3c, 0x2f, 0x63, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x64, 0x69, 0x76, 0x2e,
0x68, 0x74, 0x6d, 0x6c, 0x3e, 0xa, }; 0x63, 0x6c, 0x61, 0x73, 0x73, 0x4e, 0x61, 0x6d, 0x65, 0x20,
0x3d, 0x20, 0x22, 0x6f, 0x66, 0x66, 0x22, 0x3b, 0xa, 0x9,
0x9, 0x7d, 0xa, 0x9, 0x7d, 0xa, 0x7d, 0xa, 0xa, 0x3c,
0x2f, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x3e, 0xa, 0xa,
0x3c, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x3e, 0xa, 0xa, 0x3c,
0x62, 0x6f, 0x64, 0x79, 0x3e, 0xa, 0x3c, 0x64, 0x69, 0x76,
0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x63, 0x6f,
0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x22, 0x3e, 0xa,
0x9, 0x3c, 0x64, 0x69, 0x76, 0x20, 0x69, 0x64, 0x3d, 0x22,
0x6b, 0x65, 0x79, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x22, 0x3e,
0x3c, 0x2f, 0x64, 0x69, 0x76, 0x3e, 0xa, 0x9, 0x3c, 0x64,
0x69, 0x76, 0x3e, 0xa, 0x9, 0x9, 0x3c, 0x64, 0x69, 0x76,
0x20, 0x69, 0x64, 0x3d, 0x22, 0x69, 0x6e, 0x64, 0x69, 0x63,
0x61, 0x74, 0x6f, 0x72, 0x73, 0x22, 0x3e, 0x3c, 0x2f, 0x64,
0x69, 0x76, 0x3e, 0xa, 0x9, 0x9, 0x3c, 0x64, 0x69, 0x76,
0x3e, 0x4d, 0x6f, 0x75, 0x73, 0x65, 0x20, 0x43, 0x6f, 0x6e,
0x74, 0x72, 0x6f, 0x6c, 0x73, 0x3a, 0x3c, 0x2f, 0x64, 0x69,
0x76, 0x3e, 0xa, 0x9, 0x9, 0x3c, 0x64, 0x69, 0x76, 0x20,
0x69, 0x64, 0x3d, 0x22, 0x6d, 0x6f, 0x75, 0x73, 0x65, 0x22,
0x3e, 0x3c, 0x2f, 0x64, 0x69, 0x76, 0x3e, 0xa, 0x9, 0x3c,
0x2f, 0x64, 0x69, 0x76, 0x3e, 0xa, 0x3c, 0x2f, 0x64, 0x69,
0x76, 0x3e, 0xa, 0xa, 0x3c, 0x64, 0x69, 0x76, 0x20, 0x69,
0x64, 0x3d, 0x22, 0x6d, 0x61, 0x63, 0x72, 0x6f, 0x73, 0x22,
0x3e, 0x3c, 0x2f, 0x64, 0x69, 0x76, 0x3e, 0xa, 0xa, 0x3c,
0x64, 0x69, 0x76, 0x3e, 0xa, 0x9, 0x3c, 0x64, 0x69, 0x76,
0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x6d, 0x65,
0x6e, 0x75, 0x22, 0x3e, 0xa, 0x9, 0x9, 0x3c, 0x61, 0x20,
0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x77, 0x69, 0x66, 0x69,
0x2e, 0x73, 0x68, 0x74, 0x6d, 0x6c, 0x22, 0x3e, 0x43, 0x6f,
0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, 0x20, 0x57, 0x69,
0x2d, 0x46, 0x69, 0x3c, 0x2f, 0x61, 0x3e, 0xa, 0x9, 0x3c,
0x2f, 0x64, 0x69, 0x76, 0x3e, 0xa, 0x9, 0x3c, 0x64, 0x69,
0x76, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x6d,
0x65, 0x6e, 0x75, 0x22, 0x3e, 0xa, 0x9, 0x9, 0x3c, 0x61,
0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x72, 0x65, 0x62,
0x6f, 0x6f, 0x74, 0x2e, 0x63, 0x67, 0x69, 0x22, 0x3e, 0x52,
0x65, 0x62, 0x6f, 0x6f, 0x74, 0x3c, 0x2f, 0x61, 0x3e, 0xa,
0x9, 0x3c, 0x2f, 0x64, 0x69, 0x76, 0x3e, 0xa, 0x3c, 0x2f,
0x64, 0x69, 0x76, 0x3e, 0xa, 0xa, 0x3c, 0x2f, 0x62, 0x6f,
0x64, 0x79, 0x3e, 0xa, 0xa, 0x3c, 0x2f, 0x68, 0x74, 0x6d,
0x6c, 0x3e, 0xa, };
static const unsigned char data_success_html[] = { static const unsigned char data_success_html[] = {
/* /success.html */ /* /success.html */
+3 -1
View File
@@ -86,7 +86,7 @@ uint8_t const desc_fs_configuration[] =
// Interface number, string index, protocol, report descriptor len, EP In address, size & polling interval // Interface number, string index, protocol, report descriptor len, EP In address, size & polling interval
TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, EPNUM_CDC_NOTIF, 8, EPNUM_CDC_OUT, EPNUM_CDC_IN, 64), TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, EPNUM_CDC_NOTIF, 8, EPNUM_CDC_OUT, EPNUM_CDC_IN, 64),
TUD_HID_DESCRIPTOR(ITF_NUM_HID, 5, HID_ITF_PROTOCOL_NONE, sizeof(desc_hid_report), EPNUM_HID, CFG_TUD_HID_EP_BUFSIZE, 5), TUD_HID_DESCRIPTOR(ITF_NUM_HID, 5, HID_ITF_PROTOCOL_NONE, sizeof(desc_hid_report), EPNUM_HID, CFG_TUD_HID_EP_BUFSIZE, 8),
}; };
// Invoked when received GET CONFIGURATION DESCRIPTOR // Invoked when received GET CONFIGURATION DESCRIPTOR
@@ -110,6 +110,8 @@ char const* string_desc_arr [] =
"Raspberry Pi", // 1: Manufacturer "Raspberry Pi", // 1: Manufacturer
"Pico Web Keyboard", // 2: Product "Pico Web Keyboard", // 2: Product
NULL, // 3: Serials, should use chip ID NULL, // 3: Serials, should use chip ID
"Pico Web Keyboard CDC", // 4: CDC
"Pico Web Keyboard HID", // 5: HID
}; };
static uint16_t _desc_str[32+1]; static uint16_t _desc_str[32+1];
+1 -1
View File
@@ -41,7 +41,7 @@ enum
ITF_NUM_TOTAL ITF_NUM_TOTAL
}; };
#define USB_PID 0x0ebd #define USB_PID 0x0EBD
#define USB_VID 0xCEC0 #define USB_VID 0xCEC0
#define USB_BCD 0x0200 #define USB_BCD 0x0200
+9 -13
View File
@@ -70,7 +70,7 @@ static void ws_state_free(struct ws_state *wss) {
} else { } else {
struct ws_state * last; struct ws_state * last;
for (last = ws_connections; last->next != NULL; last = last->next) { for (last = ws_connections; last->next != NULL; last = last->next) {
if (last->next = wss) { if (last->next == wss) {
last->next = wss->next; last->next = wss->next;
break; break;
} }
@@ -187,6 +187,8 @@ static err_t ws_recv(void *arg, struct altcp_pcb *pcb, struct pbuf *p, err_t err
// called when data has been sent over the websocket // called when data has been sent over the websocket
static err_t ws_sent(void *arg, struct altcp_pcb *pcb, uint16_t len) { static err_t ws_sent(void *arg, struct altcp_pcb *pcb, uint16_t len) {
(void) pcb;
struct ws_state *wss = (struct ws_state *)arg; struct ws_state *wss = (struct ws_state *)arg;
LWIP_DEBUGF(WS_DEBUG | LWIP_DBG_TRACE, ("ws_sent %p\n", (void*) pcb)); LWIP_DEBUGF(WS_DEBUG | LWIP_DBG_TRACE, ("ws_sent %p\n", (void*) pcb));
@@ -309,13 +311,11 @@ static err_t ws_handshake(struct altcp_pcb *pcb, struct ws_state *wss, struct pb
// create response packet with encoded response key // create response packet with encoded response key
unsigned char response[sizeof(WS_RESPONSE) + sizeof(key_base64)+3]; unsigned char response[sizeof(WS_RESPONSE) + sizeof(key_base64)+3];
//strncpy(response, WS_RESPONSE, sizeof(WS_RESPONSE));
//strlcpy(&response[sizeof(WS_RESPONSE)-1], key_base64, strlen(key_base64));
size_t count = sprintf(response, "%s%s\r\n\r\n", WS_RESPONSE, key_base64); size_t count = sprintf(response, "%s%s\r\n\r\n", WS_RESPONSE, key_base64);
// send completed data packet // send completed data packet
LWIP_DEBUGF(WS_DEBUG, ("ws_handshake: sending response\n")); LWIP_DEBUGF(WS_DEBUG, ("ws_handshake: sending response\n"));
if(altcp_write(pcb, response, strlen(response), TCP_WRITE_FLAG_COPY) == ERR_OK) { if(altcp_write(pcb, response, count, TCP_WRITE_FLAG_COPY) == ERR_OK) {
wss->active = true; wss->active = true;
} }
@@ -341,6 +341,7 @@ static err_t ws_handshake(struct altcp_pcb *pcb, struct ws_state *wss, struct pb
// handle reading of websocket data and pass to ws_receive_cb // handle reading of websocket data and pass to ws_receive_cb
static err_t ws_read(struct altcp_pcb *pcb, struct ws_state *wss, struct pbuf *p) { static err_t ws_read(struct altcp_pcb *pcb, struct ws_state *wss, struct pbuf *p) {
(void) pcb;
uint8_t *data = (uint8_t *) p->payload; uint8_t *data = (uint8_t *) p->payload;
uint16_t len = p->len; uint16_t len = p->len;
@@ -353,27 +354,24 @@ static err_t ws_read(struct altcp_pcb *pcb, struct ws_state *wss, struct pbuf *p
uint8_t masked = data[1] & 0x80; uint8_t masked = data[1] & 0x80;
uint16_t msg_len = data[1] & 0x7F; uint16_t msg_len = data[1] & 0x7F;
uint8_t *msg; uint8_t *msg;
uint8_t *mask;
switch (msg_len) { switch (msg_len) {
case 126: // next two bytes are length case 126: // next two bytes are length
memcpy(&msg_len, &data[2], 2); msg_len = ( (uint16_t)data[2] << 8) | data[3];
if (len >= 8) { if (len >= 8) {
msg = &data[8]; msg = &data[8];
mask = &data[4];
} }
break; break;
case 127: // next four bytes are length case 127: // next four bytes are length
// lwIP's pbuf only handles 16-bit lengths, so error // lwIP's pbuf only handles 16-bit lengths, so error
LWIP_DEBUGF(WS_DEBUG, ("ws_read: received 64-bit length %u\n", msg_len)); LWIP_DEBUGF(WS_DEBUG, ("ws_read: received 64-bit length %u\n", msg_len));
return ERR_MEM; return ERR_MEM;
//memcpy(&msg_len, &data[2], 4);
//if (len >= 10) {
// msg = &data[10];
//}
//break;
default: default:
if (len >= 6) { if (len >= 6) {
msg = &data[6]; msg = &data[6];
mask = &data[2];
} }
break; break;
} }
@@ -387,8 +385,6 @@ static err_t ws_read(struct altcp_pcb *pcb, struct ws_state *wss, struct pbuf *p
if (msg && ws_receive_cb != NULL) { if (msg && ws_receive_cb != NULL) {
// unmask the data if mask bit is received // unmask the data if mask bit is received
if (masked) { if (masked) {
uint8_t *mask = &data[2];
for (int i=0; i<msg_len; i++) { for (int i=0; i<msg_len; i++) {
msg[i] ^= mask[i % 4]; msg[i] ^= mask[i % 4];
} }
+1 -1
View File
@@ -7,7 +7,7 @@
#define WS_MAX_RETRIES 10 #define WS_MAX_RETRIES 10
#define WS_POLL_INTERVAL 60 // WS_POLL_INTERVAL/2 seconds #define WS_POLL_INTERVAL 60 // WS_POLL_INTERVAL/2 seconds
#define WS_MAX_CONN 4 #define WS_MAX_CONN 4
#define WS_BUFFER_SIZE 512 #define WS_BUFFER_SIZE 1024
#define OP_CONT 0x00 #define OP_CONT 0x00
#define OP_TEXT 0x01 #define OP_TEXT 0x01