code clean up and added comments
This commit is contained in:
@@ -18,24 +18,24 @@ 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 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://picokb](http://picokb).
|
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 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.
|
||||||
|
|
||||||
Browse back to the main UI page at [http://picokb](http://picokb) and press
|
Browse back to the main UI page at http://192.168.0.1 and press
|
||||||
"Reboot". The device should automatically connect to the network with the
|
"Reboot". The device should automatically connect to the network with the
|
||||||
saved information. You can then connect to the device using a web browser
|
saved information. You can then connect to the device using a web browser
|
||||||
at the device's assigned IP or hostname by accessing http://IP_ADDRESS or
|
at the device's assigned IP or hostname by accessing http://IP_ADDRESS or
|
||||||
http://HOSTNAME
|
http://HOSTNAME (http://picokb is no hostname is set).
|
||||||
|
|
||||||
If the Pico W fails to connect to the saved Wi-Fi network, it will once again
|
If the Pico W fails to connect to the saved Wi-Fi network, it will once again
|
||||||
enter Access Point mode, and you can connect to the device directly to modify
|
enter Access Point mode, and you can connect to the device directly to modify
|
||||||
the network information.
|
the network information.
|
||||||
|
|
||||||
Alternatively, you can use the device directly in Access Point mode by
|
Alternatively, you can use the device directly in Access Point mode by
|
||||||
accessing the device at [http://picokb](http://picokb). The program is
|
accessing the device at http://192.168.0.1. The program is
|
||||||
set to reboot automatically to try to reconnect to the nextwork after 10
|
set to reboot automatically to try to reconnect to the nextwork after 10
|
||||||
minutes of inactivity if no keyboard input is received during that time.
|
minutes of inactivity if no keyboard input is received during that time.
|
||||||
|
|
||||||
@@ -44,7 +44,7 @@ minutes of inactivity if no keyboard input is received during that time.
|
|||||||
This software is distributed under the [GNU General Public License version
|
This software is distributed under the [GNU General Public License version
|
||||||
3](LICENSE), with the exception of the libraries in the following section.
|
3](LICENSE), with the exception of the libraries in the following section.
|
||||||
|
|
||||||
## Attributions
|
## Credits
|
||||||
|
|
||||||
The project uses code from the following sources:
|
The project uses code from the following sources:
|
||||||
|
|
||||||
@@ -53,5 +53,6 @@ The project uses code from the following sources:
|
|||||||
- [Raspberry Pi Pico SDK Examples](https://github.com/raspberrypi/pico-examples)
|
- [Raspberry Pi Pico SDK Examples](https://github.com/raspberrypi/pico-examples)
|
||||||
for a modified version of [pico_w/wifi/lwipopts_examples_common.h](lwipopts.h)
|
for a modified version of [pico_w/wifi/lwipopts_examples_common.h](lwipopts.h)
|
||||||
distributed under the BSD-3-Clause license
|
distributed under the BSD-3-Clause license
|
||||||
- [TinyUSB](https://github.com/hathach/tinyusb) for the base version of
|
- [TinyUSB](https://github.com/hathach/tinyusb) for template versions of
|
||||||
[tusb_config.h](tusb_config.h) distributed under the MIT license
|
[hid.c](hid.c), [tusb_config.h](tusb_config.h), and
|
||||||
|
[usb_descriptors.c/h](usb_descriptors.c) distributed under the MIT license
|
||||||
|
|||||||
Binary file not shown.
@@ -44,7 +44,6 @@ int run_hid_device(void) {
|
|||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
tud_task(); // tinyusb device task
|
tud_task(); // tinyusb device task
|
||||||
//tud_cdc_write_flush();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -59,10 +58,11 @@ void tud_hid_set_report_cb(uint8_t instance, uint8_t report_id, hid_report_type_
|
|||||||
|
|
||||||
|
|
||||||
if (instance == 0 && report_type==HID_REPORT_TYPE_OUTPUT && report_id==REPORT_ID_KEYBOARD && bufsize==1) {
|
if (instance == 0 && report_type==HID_REPORT_TYPE_OUTPUT && report_id==REPORT_ID_KEYBOARD && bufsize==1) {
|
||||||
//received keyboard LED status, so update
|
//received keyboard indicator LED status, so update
|
||||||
set_indicator(buffer);
|
set_indicator(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// forward USB report to CDC for debugging
|
||||||
char tempbuf[128];
|
char tempbuf[128];
|
||||||
size_t count;
|
size_t count;
|
||||||
if(bufsize>0) {
|
if(bufsize>0) {
|
||||||
@@ -84,13 +84,7 @@ void tud_hid_set_report_cb(uint8_t instance, uint8_t report_id, hid_report_type_
|
|||||||
|
|
||||||
uint16_t tud_hid_get_report_cb(uint8_t instance, uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen)
|
uint16_t tud_hid_get_report_cb(uint8_t instance, uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen)
|
||||||
{
|
{
|
||||||
// TODO not Implemented
|
// echo USB communication to CDC for debugging
|
||||||
(void) instance;
|
|
||||||
(void) report_id;
|
|
||||||
(void) report_type;
|
|
||||||
(void) buffer;
|
|
||||||
(void) reqlen;
|
|
||||||
|
|
||||||
char tempbuf[128];
|
char tempbuf[128];
|
||||||
size_t count;
|
size_t count;
|
||||||
if(reqlen>0) {
|
if(reqlen>0) {
|
||||||
@@ -108,29 +102,3 @@ uint16_t tud_hid_get_report_cb(uint8_t instance, uint8_t report_id, hid_report_t
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Invoked when sent REPORT successfully to host
|
|
||||||
// Application can use this to send the next report
|
|
||||||
// Note: For composite reports, report[0] is report ID
|
|
||||||
/*
|
|
||||||
void tud_hid_report_complete_cb(uint8_t instance, uint8_t const* report, uint16_t len)
|
|
||||||
{
|
|
||||||
(void) instance;
|
|
||||||
(void) len;
|
|
||||||
|
|
||||||
char tempbuf[128];
|
|
||||||
size_t count;
|
|
||||||
if(len>0) {
|
|
||||||
count = sprintf(tempbuf, "\nDevice sent report on interface %u (%u)\n", instance, len);
|
|
||||||
tud_cdc_write(tempbuf, count);
|
|
||||||
for(int i=0;i<len;i++){
|
|
||||||
count=sprintf(tempbuf,"%02X ",report[i]);
|
|
||||||
tud_cdc_write(tempbuf,count);
|
|
||||||
}
|
|
||||||
count = sprintf(tempbuf, "\n");
|
|
||||||
tud_cdc_write(tempbuf,count);
|
|
||||||
tud_cdc_write_flush();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|||||||
@@ -10,16 +10,21 @@
|
|||||||
int main() {
|
int main() {
|
||||||
stdio_init_all();
|
stdio_init_all();
|
||||||
|
|
||||||
|
// setup multicore processes
|
||||||
multicore_reset_core1();
|
multicore_reset_core1();
|
||||||
multicore_launch_core1(core1_main);
|
multicore_launch_core1(core1_main);
|
||||||
|
|
||||||
|
// allow core 1 to pause core 0
|
||||||
|
// this is needed to allow saving network config to flash
|
||||||
multicore_lockout_victim_init();
|
multicore_lockout_victim_init();
|
||||||
|
|
||||||
|
// run USB HID device on core 0
|
||||||
run_hid_device();
|
run_hid_device();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void core1_main() {
|
void core1_main() {
|
||||||
|
// run HTTP services on core 1
|
||||||
run_http_server();
|
run_http_server();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+20
-6
@@ -7,19 +7,29 @@
|
|||||||
#include "parse_keys.h"
|
#include "parse_keys.h"
|
||||||
#include "usb_descriptors.h"
|
#include "usb_descriptors.h"
|
||||||
|
|
||||||
|
// take a list of Javascript keys representing pressed keys and turn into
|
||||||
|
// a 8 byte USB boot keyboard report format
|
||||||
void parse_key_list(char * keys) {
|
void parse_key_list(char * keys) {
|
||||||
uint8_t keypos = 2;
|
uint8_t keypos = 2; // bytes 2-7 are used for normal keys
|
||||||
uint8_t code = 0x00;
|
uint8_t code = 0x00;
|
||||||
static unsigned char boot_report[8];
|
static unsigned char boot_report[8];
|
||||||
memset(boot_report, 0x00, 8);
|
memset(boot_report, 0x00, 8);
|
||||||
|
|
||||||
|
// Javascript sends the list as comma delimited, so split into individual
|
||||||
|
// keys by splitting at commas
|
||||||
char * token = strtok(keys, ",");
|
char * token = strtok(keys, ",");
|
||||||
while (token != NULL) {
|
while (token != NULL) {
|
||||||
code = parse_key_single(token);
|
code = parse_key_single(token);
|
||||||
if (code && keypos < 9) {
|
// add scan code to the boot report unless we have already added
|
||||||
|
// the 8th byte (6 scan codes) to the report
|
||||||
|
if (code && keypos < 8) {
|
||||||
boot_report[keypos] = code;
|
boot_report[keypos] = code;
|
||||||
keypos++;
|
keypos++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if a scan code was not returned, it might be a modifier
|
||||||
|
// search for the correct modifier bit and add it to byte 0 of the
|
||||||
|
// USB boot keyboard report
|
||||||
if (code == 0x00) {
|
if (code == 0x00) {
|
||||||
code = parse_mod(token);
|
code = parse_mod(token);
|
||||||
if (code) {
|
if (code) {
|
||||||
@@ -29,6 +39,7 @@ void parse_key_list(char * keys) {
|
|||||||
token = strtok(NULL, ",");
|
token = strtok(NULL, ",");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// print resulting HID boot keyboard report to CDC for debugging
|
||||||
printf("HID report: ");
|
printf("HID report: ");
|
||||||
for(int i=0; i<8; i++){
|
for(int i=0; i<8; i++){
|
||||||
printf("%02X ",boot_report[i]);
|
printf("%02X ",boot_report[i]);
|
||||||
@@ -38,24 +49,27 @@ void parse_key_list(char * keys) {
|
|||||||
tud_hid_report(REPORT_ID_KEYBOARD, boot_report, 8);
|
tud_hid_report(REPORT_ID_KEYBOARD, boot_report, 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t parse_key_single(char * key) {
|
|
||||||
//printf("single key: %s\n", key);
|
|
||||||
|
|
||||||
|
// take a single Javascript key code and convert it to USB HID scancode
|
||||||
|
// if it is a regular key, i.e. not a modifier key
|
||||||
|
uint8_t parse_key_single(char * key) {
|
||||||
|
// search keycode dictionary defined in parse_keys.h to see if it's a
|
||||||
|
// regular key
|
||||||
for (int i=0; i < NKEYS; i++) {
|
for (int i=0; i < NKEYS; i++) {
|
||||||
keycode_dict * keycode = &keytable[i];
|
keycode_dict * keycode = &keytable[i];
|
||||||
if (strcmp(keycode->key, key) == 0){
|
if (strcmp(keycode->key, key) == 0){
|
||||||
//printf("key found");
|
|
||||||
return keycode->val;
|
return keycode->val;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// key not found in lookup table
|
||||||
return 0x00;
|
return 0x00;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// parse modifier keys and turn them into the appropriate modifier bit code
|
||||||
uint8_t parse_mod(char * key) {
|
uint8_t parse_mod(char * key) {
|
||||||
for (int i=0; i < NMODS; i++) {
|
for (int i=0; i < NMODS; i++) {
|
||||||
keycode_dict * modcode = &modtable[i];
|
keycode_dict * modcode = &modtable[i];
|
||||||
if (strcmp(modcode->key, key) == 0){
|
if (strcmp(modcode->key, key) == 0){
|
||||||
//printf("key found");
|
|
||||||
return modcode->val;
|
return modcode->val;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-8
@@ -9,6 +9,8 @@ uint8_t parse_mod(char * key);
|
|||||||
|
|
||||||
typedef struct { char * key; uint8_t val; } keycode_dict;
|
typedef struct { char * key; uint8_t val; } keycode_dict;
|
||||||
|
|
||||||
|
|
||||||
|
// modifier key bit codes
|
||||||
#define KEY_MOD_LCTRL 0x01
|
#define KEY_MOD_LCTRL 0x01
|
||||||
#define KEY_MOD_LSHIFT 0x02
|
#define KEY_MOD_LSHIFT 0x02
|
||||||
#define KEY_MOD_LALT 0x04
|
#define KEY_MOD_LALT 0x04
|
||||||
@@ -18,14 +20,7 @@ typedef struct { char * key; uint8_t val; } keycode_dict;
|
|||||||
#define KEY_MOD_RALT 0x40
|
#define KEY_MOD_RALT 0x40
|
||||||
#define KEY_MOD_RMETA 0x80
|
#define KEY_MOD_RMETA 0x80
|
||||||
|
|
||||||
/**
|
// list of USB scan codes for individual keys
|
||||||
* Scan codes - last N slots in the HID report (usually 6).
|
|
||||||
* 0x00 if no key pressed.
|
|
||||||
*
|
|
||||||
* If more than N keys are pressed, the HID reports
|
|
||||||
* KEY_ERR_OVF in all slots to indicate this condition.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define KEY_NONE 0x00 // No key pressed
|
#define KEY_NONE 0x00 // No key pressed
|
||||||
#define KEY_ERR_OVF 0x01 // Keyboard Error Roll Over - used for all slots if too many keys are pressed ("Phantom key")
|
#define KEY_ERR_OVF 0x01 // Keyboard Error Roll Over - used for all slots if too many keys are pressed ("Phantom key")
|
||||||
// 0x02 // Keyboard POST Fail
|
// 0x02 // Keyboard POST Fail
|
||||||
@@ -277,6 +272,7 @@ typedef struct { char * key; uint8_t val; } keycode_dict;
|
|||||||
#define KEY_MEDIA_REFRESH 0xfa
|
#define KEY_MEDIA_REFRESH 0xfa
|
||||||
#define KEY_MEDIA_CALC 0xfb
|
#define KEY_MEDIA_CALC 0xfb
|
||||||
|
|
||||||
|
// dictionary converting Javascript key code strings to USB scan codes
|
||||||
static keycode_dict keytable[] = {
|
static keycode_dict keytable[] = {
|
||||||
{"KeyA", KEY_A},
|
{"KeyA", KEY_A},
|
||||||
{"KeyB", KEY_B},
|
{"KeyB", KEY_B},
|
||||||
@@ -376,6 +372,7 @@ static keycode_dict keytable[] = {
|
|||||||
{"WakeUp", KEY_POWER}
|
{"WakeUp", KEY_POWER}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// dictionary for Javascript key code strings to USB keyboard modifier bits
|
||||||
static keycode_dict modtable[] = {
|
static keycode_dict modtable[] = {
|
||||||
{"ControlLeft", KEY_MOD_LCTRL},
|
{"ControlLeft", KEY_MOD_LCTRL},
|
||||||
{"ShiftLeft", KEY_MOD_LSHIFT},
|
{"ShiftLeft", KEY_MOD_LSHIFT},
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ static bool config_loaded = false;
|
|||||||
static bool bad_config = false;
|
static bool bad_config = false;
|
||||||
static bool reboot = false;
|
static bool reboot = false;
|
||||||
|
|
||||||
|
// list of SSI variable names for lwIP SSI handler
|
||||||
const char * __not_in_flash("httpd") ssi_tags[] = {
|
const char * __not_in_flash("httpd") ssi_tags[] = {
|
||||||
"num",
|
"num",
|
||||||
"caps",
|
"caps",
|
||||||
@@ -56,48 +57,53 @@ static const tCGI cgi_handlers[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
void run_http_server() {
|
void run_http_server() {
|
||||||
//sleep_ms(5000);
|
|
||||||
|
|
||||||
if (cyw43_arch_init_with_country(CYW43_COUNTRY_USA)) {
|
if (cyw43_arch_init_with_country(CYW43_COUNTRY_USA)) {
|
||||||
printf("failed to initialize\n");
|
printf("failed to initialize\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// fall back to AP mode unless Wi-Fi connection is successful
|
||||||
clientmode = false;
|
clientmode = false;
|
||||||
|
|
||||||
|
// read network config from flash
|
||||||
config_loaded = net_config_load(&wifi);
|
config_loaded = net_config_load(&wifi);
|
||||||
|
|
||||||
if ( config_loaded ){
|
if ( config_loaded ){
|
||||||
printf("read config file\n");
|
printf("read config file\n");
|
||||||
cyw43_arch_enable_sta_mode();
|
cyw43_arch_enable_sta_mode();
|
||||||
|
|
||||||
// set hostname
|
// set hostname if saved, otherwise use default setting
|
||||||
//cyw43_arch_lwip_begin();
|
|
||||||
struct netif *n = &cyw43_state.netif[CYW43_ITF_STA];
|
struct netif *n = &cyw43_state.netif[CYW43_ITF_STA];
|
||||||
if (wifi.host) {
|
if (wifi.host) {
|
||||||
netif_set_hostname(n, wifi.host);
|
netif_set_hostname(n, wifi.host);
|
||||||
} else {
|
} else {
|
||||||
netif_set_hostname(n, DEFAULTHOST);
|
netif_set_hostname(n, DEFAULTHOST);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// use manual IP address if configured
|
||||||
if (wifi.manual) {
|
if (wifi.manual) {
|
||||||
dhcp_release_and_stop(n);
|
dhcp_release_and_stop(n);
|
||||||
netif_set_addr(n, &(wifi.ip), &(wifi.mask), &(wifi.gw));
|
netif_set_addr(n, &(wifi.ip), &(wifi.mask), &(wifi.gw));
|
||||||
|
|
||||||
|
// inform mDNS of hostname
|
||||||
dhcp_inform(n);
|
dhcp_inform(n);
|
||||||
}
|
}
|
||||||
netif_set_up(n);
|
netif_set_up(n);
|
||||||
//cyw43_arch_lwip_end();
|
|
||||||
|
|
||||||
|
// attempt to connect to saved Wi-Fi network
|
||||||
if(cyw43_arch_wifi_connect_timeout_ms(wifi.ssid, wifi.pass, CYW43_AUTH_WPA2_AES_PSK, 10000)){
|
if(cyw43_arch_wifi_connect_timeout_ms(wifi.ssid, wifi.pass, CYW43_AUTH_WPA2_AES_PSK, 10000)){
|
||||||
printf("failed to connect to %s\n", wifi.ssid);
|
printf("failed to connect to %s\n", wifi.ssid);
|
||||||
} else{
|
} else{
|
||||||
|
// Wi-Fi client connection successful
|
||||||
clientmode = true;
|
clientmode = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!clientmode) {
|
if (!clientmode) {
|
||||||
//start AP mode
|
// did not connect to Wi-Fi, launch AP mode
|
||||||
cyw43_arch_enable_ap_mode(DEFAULTHOST, DEFAULTPASS, CYW43_AUTH_WPA2_AES_PSK);
|
cyw43_arch_enable_ap_mode(DEFAULTHOST, DEFAULTPASS, CYW43_AUTH_WPA2_AES_PSK);
|
||||||
|
|
||||||
|
// set AP address to 192.168.0.1
|
||||||
ip4_addr_t ip, mask, gw;
|
ip4_addr_t ip, mask, gw;
|
||||||
IP4_ADDR(&ip, 192, 168, 0, 1);
|
IP4_ADDR(&ip, 192, 168, 0, 1);
|
||||||
IP4_ADDR(&mask, 255, 255, 255, 0);
|
IP4_ADDR(&mask, 255, 255, 255, 0);
|
||||||
@@ -105,12 +111,13 @@ void run_http_server() {
|
|||||||
netif_set_ipaddr(netif_default, &ip);
|
netif_set_ipaddr(netif_default, &ip);
|
||||||
netif_set_up(netif_default);
|
netif_set_up(netif_default);
|
||||||
|
|
||||||
|
// init DHCP server to hand out addresses to connected clients
|
||||||
dhcp_server_t dhcp;
|
dhcp_server_t dhcp;
|
||||||
dhcp_server_init(&dhcp, &gw, &mask);
|
dhcp_server_init(&dhcp, &gw, &mask);
|
||||||
printf("launched in AP mode\n");
|
printf("launched in AP mode\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
// start the server
|
// start the HTTP web server for keyboard input and config page
|
||||||
httpd_init();
|
httpd_init();
|
||||||
http_set_cgi_handlers(cgi_handlers, 3);
|
http_set_cgi_handlers(cgi_handlers, 3);
|
||||||
for (size_t i = 0; i < LWIP_ARRAYSIZE(ssi_tags); i++) {
|
for (size_t i = 0; i < LWIP_ARRAYSIZE(ssi_tags); i++) {
|
||||||
@@ -120,14 +127,19 @@ void run_http_server() {
|
|||||||
http_set_ssi_handler(ssi_handler, ssi_tags, LWIP_ARRAYSIZE(ssi_tags));
|
http_set_ssi_handler(ssi_handler, ssi_tags, LWIP_ARRAYSIZE(ssi_tags));
|
||||||
printf("HTTP server initialized\n");
|
printf("HTTP server initialized\n");
|
||||||
|
|
||||||
|
// start a watchdog timer with 8 seconds so it can reboot if it disconnects
|
||||||
watchdog_enable(8000,1);
|
watchdog_enable(8000,1);
|
||||||
|
|
||||||
if (clientmode) {
|
if (clientmode) {
|
||||||
|
// signal that device is in client mode with solid LED on
|
||||||
cyw43_arch_gpio_put(CYW43_WL_GPIO_LED_PIN,1);
|
cyw43_arch_gpio_put(CYW43_WL_GPIO_LED_PIN,1);
|
||||||
while(true) {
|
while(true) {
|
||||||
if ( absolute_time_diff_us(lastCheck, get_absolute_time()) > 5000000) {
|
if ( absolute_time_diff_us(lastCheck, get_absolute_time()) > 5000000) {
|
||||||
|
// check if Wi-Fi is still connected every 5 seconds and
|
||||||
|
// feed the watchdog timer if it is to prevent reboot
|
||||||
if ( cyw43_tcpip_link_status(&cyw43_state, CYW43_ITF_STA) == 3 ) {
|
if ( cyw43_tcpip_link_status(&cyw43_state, CYW43_ITF_STA) == 3 ) {
|
||||||
lastCheck = get_absolute_time();
|
lastCheck = get_absolute_time();
|
||||||
|
// update watchdog if reboot has not been requested
|
||||||
if(!reboot){
|
if(!reboot){
|
||||||
watchdog_update();
|
watchdog_update();
|
||||||
}
|
}
|
||||||
@@ -139,12 +151,16 @@ void run_http_server() {
|
|||||||
static int led = 1;
|
static int led = 1;
|
||||||
while(true) {
|
while(true) {
|
||||||
if (absolute_time_diff_us(lastCheck, get_absolute_time()) > 1000000) {
|
if (absolute_time_diff_us(lastCheck, get_absolute_time()) > 1000000) {
|
||||||
|
// signal device is in AP mode with blinking LED
|
||||||
led = !led;
|
led = !led;
|
||||||
cyw43_arch_gpio_put(CYW43_WL_GPIO_LED_PIN, led);
|
cyw43_arch_gpio_put(CYW43_WL_GPIO_LED_PIN, led);
|
||||||
lastCheck = get_absolute_time();
|
lastCheck = get_absolute_time();
|
||||||
if ( config_loaded && (absolute_time_diff_us(lastActive, lastCheck) > 600000000)) {
|
if ( config_loaded && (absolute_time_diff_us(lastActive, lastCheck) > 600000000)) {
|
||||||
|
// if there is no keyboard activity for 10 minutes
|
||||||
|
// reboot to try to (re)connect to Wi-Fi
|
||||||
reboot = true;
|
reboot = true;
|
||||||
}
|
}
|
||||||
|
// update watchdog unless reboot has been requested
|
||||||
if(!reboot) {
|
if(!reboot) {
|
||||||
watchdog_update();
|
watchdog_update();
|
||||||
}
|
}
|
||||||
@@ -153,10 +169,11 @@ void run_http_server() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// lwIP cgi handler for GET requests to sendkeys.cgi
|
||||||
const char * sendkeys_cgi (int iIndex, int iNumParams, char *pcParam[], char *pcValue[]) {
|
const char * sendkeys_cgi (int iIndex, int iNumParams, char *pcParam[], char *pcValue[]) {
|
||||||
for (int i=0; i < iNumParams; i++) {
|
for (int i=0; i < iNumParams; i++) {
|
||||||
|
// search GET parameters for keys and forward for processing to USB
|
||||||
if (strcmp(pcParam[i], "keys") == 0 ) {
|
if (strcmp(pcParam[i], "keys") == 0 ) {
|
||||||
//printf("Web input: %s\n", pcValue[i]);
|
|
||||||
parse_key_list(pcValue[i]);
|
parse_key_list(pcValue[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -167,6 +184,7 @@ const char * sendkeys_cgi (int iIndex, int iNumParams, char *pcParam[], char *pc
|
|||||||
return "/success.html";
|
return "/success.html";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// lwIP cgi handler for form submission of network config to wifi.cgi
|
||||||
const char * save_wifi (int iIndex, int iNumParams, char *pcParam[], char *pcValue[]) {
|
const char * save_wifi (int iIndex, int iNumParams, char *pcParam[], char *pcValue[]) {
|
||||||
// clear all values in manual network settings
|
// clear all values in manual network settings
|
||||||
memset(ip, 0, sizeof(ip));
|
memset(ip, 0, sizeof(ip));
|
||||||
@@ -176,6 +194,7 @@ const char * save_wifi (int iIndex, int iNumParams, char *pcParam[], char *pcVal
|
|||||||
bad_config = false;
|
bad_config = false;
|
||||||
wifi.manual = true;
|
wifi.manual = true;
|
||||||
|
|
||||||
|
// read parameter values
|
||||||
for (int i=0; i < iNumParams; i++) {
|
for (int i=0; i < iNumParams; i++) {
|
||||||
if (strcmp(pcParam[i], "ssid") == 0){
|
if (strcmp(pcParam[i], "ssid") == 0){
|
||||||
if (pcValue[i][0] == "\0") {
|
if (pcValue[i][0] == "\0") {
|
||||||
@@ -217,8 +236,10 @@ const char * save_wifi (int iIndex, int iNumParams, char *pcParam[], char *pcVal
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (bad_config) {
|
if (bad_config) {
|
||||||
|
// config is invalid, so don't save and return to config page
|
||||||
return "/wifi.shtml";
|
return "/wifi.shtml";
|
||||||
} else {
|
} else {
|
||||||
|
// config is valid, prepare for saving to flash
|
||||||
IP4_ADDR(&(wifi.ip), ip[0], ip[1], ip[2], ip[3]);
|
IP4_ADDR(&(wifi.ip), ip[0], ip[1], ip[2], ip[3]);
|
||||||
if(!wifi.ip.addr) {
|
if(!wifi.ip.addr) {
|
||||||
wifi.ip.addr = IPADDR_NONE;
|
wifi.ip.addr = IPADDR_NONE;
|
||||||
@@ -237,6 +258,7 @@ const char * save_wifi (int iIndex, int iNumParams, char *pcParam[], char *pcVal
|
|||||||
|
|
||||||
watchdog_update();
|
watchdog_update();
|
||||||
|
|
||||||
|
// save configuratitons to flash
|
||||||
net_config_write(&wifi);
|
net_config_write(&wifi);
|
||||||
|
|
||||||
printf("wifi settings saved\n");
|
printf("wifi settings saved\n");
|
||||||
@@ -245,7 +267,9 @@ const char * save_wifi (int iIndex, int iNumParams, char *pcParam[], char *pcVal
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// lwIP cgi handler for reboots initiated from the web
|
||||||
const char * reboot_cgi(int iIndex, int iNumParams, char *pcParam[], char *pcValue[]) {
|
const char * reboot_cgi(int iIndex, int iNumParams, char *pcParam[], char *pcValue[]) {
|
||||||
|
// turn on reboot flag to prevent watchdog from updating
|
||||||
reboot = true;
|
reboot = true;
|
||||||
|
|
||||||
return "/success.html";
|
return "/success.html";
|
||||||
@@ -253,20 +277,28 @@ const char * reboot_cgi(int iIndex, int iNumParams, char *pcParam[], char *pcVal
|
|||||||
|
|
||||||
|
|
||||||
void net_config_write(net_config *config) {
|
void net_config_write(net_config *config) {
|
||||||
|
// core 0 must have its TinyUSB interrupts disabled to allow flash writes
|
||||||
multicore_lockout_start_blocking();
|
multicore_lockout_start_blocking();
|
||||||
|
|
||||||
|
// blank out memory for staging config save
|
||||||
uint8_t buf[FLASH_PAGE_SIZE];
|
uint8_t buf[FLASH_PAGE_SIZE];
|
||||||
memset(buf, 0x00, FLASH_PAGE_SIZE);
|
memset(buf, 0x00, FLASH_PAGE_SIZE);
|
||||||
memcpy(buf, config, sizeof(net_config));
|
memcpy(buf, config, sizeof(net_config));
|
||||||
|
|
||||||
|
// turn off core 1 web server interrupts to allow flash writes
|
||||||
uint32_t interrupts = save_and_disable_interrupts();
|
uint32_t interrupts = save_and_disable_interrupts();
|
||||||
flash_range_erase(FLASH_TARGET_OFFSET, FLASH_SECTOR_SIZE);
|
|
||||||
flash_range_program(FLASH_TARGET_OFFSET, buf, FLASH_PAGE_SIZE);
|
|
||||||
restore_interrupts(interrupts);
|
|
||||||
|
|
||||||
|
// erase page where save will go in flash
|
||||||
|
flash_range_erase(FLASH_TARGET_OFFSET, FLASH_SECTOR_SIZE);
|
||||||
|
// write new config to flash
|
||||||
|
flash_range_program(FLASH_TARGET_OFFSET, buf, FLASH_PAGE_SIZE);
|
||||||
|
|
||||||
|
// restore interrupts on both core 1 and core 0
|
||||||
|
restore_interrupts(interrupts);
|
||||||
multicore_lockout_end_blocking();
|
multicore_lockout_end_blocking();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// read network config from flash and loads to program memory
|
||||||
bool net_config_load(net_config *config) {
|
bool net_config_load(net_config *config) {
|
||||||
const uint8_t *data = (const uint8_t *) (XIP_BASE+FLASH_TARGET_OFFSET);
|
const uint8_t *data = (const uint8_t *) (XIP_BASE+FLASH_TARGET_OFFSET);
|
||||||
memcpy(config, data, sizeof(net_config));
|
memcpy(config, data, sizeof(net_config));
|
||||||
@@ -274,45 +306,46 @@ bool net_config_load(net_config *config) {
|
|||||||
return ( (config->header == STARTFILE) && (config->footer == ENDFILE) );
|
return ( (config->header == STARTFILE) && (config->footer == ENDFILE) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// lwIP SSI handler for loading variables into HTML pages
|
||||||
uint16_t __time_critical_func(ssi_handler)(int iIndex, char *pcInsert, int iInsertLen) {
|
uint16_t __time_critical_func(ssi_handler)(int iIndex, char *pcInsert, int iInsertLen) {
|
||||||
size_t printed;
|
size_t printed;
|
||||||
switch (iIndex) {
|
switch (iIndex) {
|
||||||
case 0: //num
|
case 0: //num - numlock status
|
||||||
if (led_code & 1) {
|
if (led_code & 1) {
|
||||||
printed = snprintf(pcInsert, iInsertLen, "on");
|
printed = snprintf(pcInsert, iInsertLen, "on");
|
||||||
} else {
|
} else {
|
||||||
printed = snprintf(pcInsert, iInsertLen, "off");
|
printed = snprintf(pcInsert, iInsertLen, "off");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 1: //caps
|
case 1: //caps - capslock status
|
||||||
if (led_code & 2) {
|
if (led_code & 2) {
|
||||||
printed = snprintf(pcInsert, iInsertLen, "on");
|
printed = snprintf(pcInsert, iInsertLen, "on");
|
||||||
} else {
|
} else {
|
||||||
printed = snprintf(pcInsert, iInsertLen, "off");
|
printed = snprintf(pcInsert, iInsertLen, "off");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 2: //scroll
|
case 2: //scroll - scrollock status
|
||||||
if (led_code & 4) {
|
if (led_code & 4) {
|
||||||
printed = snprintf(pcInsert, iInsertLen, "on");
|
printed = snprintf(pcInsert, iInsertLen, "on");
|
||||||
} else {
|
} else {
|
||||||
printed = snprintf(pcInsert, iInsertLen, "off");
|
printed = snprintf(pcInsert, iInsertLen, "off");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 3: //ssid
|
case 3: //ssid - network config SSID
|
||||||
if (config_loaded && wifi.ssid) {
|
if (config_loaded && wifi.ssid) {
|
||||||
printed = snprintf(pcInsert, iInsertLen, "value=\"%s\"", wifi.ssid);
|
printed = snprintf(pcInsert, iInsertLen, "value=\"%s\"", wifi.ssid);
|
||||||
} else {
|
} else {
|
||||||
printed = 0;
|
printed = 0;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 4: //pass
|
case 4: //pass - network config password
|
||||||
if (config_loaded && wifi.pass) {
|
if (config_loaded && wifi.pass) {
|
||||||
printed = snprintf(pcInsert, iInsertLen, "value=\"%s\"", wifi.pass);
|
printed = snprintf(pcInsert, iInsertLen, "value=\"%s\"", wifi.pass);
|
||||||
} else {
|
} else {
|
||||||
printed = 0;
|
printed = 0;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 5: //host
|
case 5: //host - network config hostname
|
||||||
if (config_loaded && wifi.host) {
|
if (config_loaded && wifi.host) {
|
||||||
printed = snprintf(pcInsert, iInsertLen, "value=\"%s\"", wifi.host);
|
printed = snprintf(pcInsert, iInsertLen, "value=\"%s\"", wifi.host);
|
||||||
} else {
|
} else {
|
||||||
@@ -322,7 +355,7 @@ uint16_t __time_critical_func(ssi_handler)(int iIndex, char *pcInsert, int iInse
|
|||||||
case 6:
|
case 6:
|
||||||
case 7:
|
case 7:
|
||||||
case 8:
|
case 8:
|
||||||
case 9: //ip0-3
|
case 9: //ip0-3 - network config manual IP address parts
|
||||||
if (config_loaded && wifi.ip.addr) {
|
if (config_loaded && wifi.ip.addr) {
|
||||||
printed = snprintf(pcInsert, iInsertLen, "value=\"%d\"", ip4_addr_get_byte(&(wifi.ip), iIndex-6));
|
printed = snprintf(pcInsert, iInsertLen, "value=\"%d\"", ip4_addr_get_byte(&(wifi.ip), iIndex-6));
|
||||||
} else {
|
} else {
|
||||||
@@ -332,7 +365,7 @@ uint16_t __time_critical_func(ssi_handler)(int iIndex, char *pcInsert, int iInse
|
|||||||
case 10:
|
case 10:
|
||||||
case 11:
|
case 11:
|
||||||
case 12:
|
case 12:
|
||||||
case 13: //mask0-3
|
case 13: //mask0-3 - network config manual netmask parts
|
||||||
if (config_loaded && wifi.mask.addr) {
|
if (config_loaded && wifi.mask.addr) {
|
||||||
printed = snprintf(pcInsert, iInsertLen, "value=\"%d\"", ip4_addr_get_byte(&(wifi.mask), iIndex-10));
|
printed = snprintf(pcInsert, iInsertLen, "value=\"%d\"", ip4_addr_get_byte(&(wifi.mask), iIndex-10));
|
||||||
} else {
|
} else {
|
||||||
@@ -342,14 +375,14 @@ uint16_t __time_critical_func(ssi_handler)(int iIndex, char *pcInsert, int iInse
|
|||||||
case 14:
|
case 14:
|
||||||
case 15:
|
case 15:
|
||||||
case 16:
|
case 16:
|
||||||
case 17: //gw0-3
|
case 17: //gw0-3 - network config manual gateway parts
|
||||||
if (config_loaded && wifi.gw.addr) {
|
if (config_loaded && wifi.gw.addr) {
|
||||||
printed = snprintf(pcInsert, iInsertLen, "value=\"%d\"", ip4_addr_get_byte(&(wifi.gw), iIndex-14));
|
printed = snprintf(pcInsert, iInsertLen, "value=\"%d\"", ip4_addr_get_byte(&(wifi.gw), iIndex-14));
|
||||||
} else {
|
} else {
|
||||||
printed = 0;
|
printed = 0;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 18: // dhcp
|
case 18: // dhcp - network config DHCP client enabled/disabled
|
||||||
if ((!config_loaded) || !(wifi.manual) ){
|
if ((!config_loaded) || !(wifi.manual) ){
|
||||||
printed = snprintf(pcInsert, iInsertLen, "checked");
|
printed = snprintf(pcInsert, iInsertLen, "checked");
|
||||||
} else {
|
} else {
|
||||||
@@ -364,10 +397,12 @@ uint16_t __time_critical_func(ssi_handler)(int iIndex, char *pcInsert, int iInse
|
|||||||
return (uint16_t)printed;
|
return (uint16_t)printed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// save keyboard's LED indicator status to memory
|
||||||
void set_indicator(uint8_t const* buffer) {
|
void set_indicator(uint8_t const* buffer) {
|
||||||
led_code = *buffer;
|
led_code = *buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// turn URL-formatted string from GET request and turn into regular string
|
||||||
void urldecode(char *urlstring, char *decoded) {
|
void urldecode(char *urlstring, char *decoded) {
|
||||||
uint8_t conv;
|
uint8_t conv;
|
||||||
while(*urlstring) {
|
while(*urlstring) {
|
||||||
|
|||||||
+1
-10
@@ -126,7 +126,7 @@ char const* string_desc_arr [] =
|
|||||||
"Raspberry Pi", // 1: Manufacturer
|
"Raspberry Pi", // 1: Manufacturer
|
||||||
"Pico Web Keyboard", // 2: Product
|
"Pico Web Keyboard", // 2: Product
|
||||||
"1234567890123456789", // 3: Serials, should use chip ID
|
"1234567890123456789", // 3: Serials, should use chip ID
|
||||||
"Pico Web Keyboard CDC", // 4: CC Interface
|
"Pico Web Keyboard CDC", // 4: CDC Interface
|
||||||
"TinyUSB Keyboard", // 5: HID Keyboard Interface
|
"TinyUSB Keyboard", // 5: HID Keyboard Interface
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -181,15 +181,6 @@ uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid)
|
|||||||
uint8_t const * tud_hid_descriptor_report_cb(uint8_t itf)
|
uint8_t const * tud_hid_descriptor_report_cb(uint8_t itf)
|
||||||
{
|
{
|
||||||
(void) itf;
|
(void) itf;
|
||||||
//switch(itf) {
|
|
||||||
// case 0:
|
|
||||||
return desc_hid_report;
|
return desc_hid_report;
|
||||||
// case 1:
|
|
||||||
// return desc_nkro_report;
|
|
||||||
// case 2:
|
|
||||||
// return desc_media_report;
|
|
||||||
// default:
|
|
||||||
// return 0;
|
|
||||||
//}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user