Merge pull request #437 from ourairquality/oaq-merge-1
* bmp180: comment typo * ds3231: minor code style fixes. Comment, on the week day start. * Reverse engineered ets_timers.o Switch from FreeRTOS queue to task notification. Removed unknown/unused code. Rename sdk_ets_handler_isr to process_pending_timers. Add function for microseconds Simplify time to ticks conversion * ets_timer: code for using the FreeRTOS timers, and remove from libs. * libc: update to a recent newlib version. * LwIP v2 support * spi_write: use uint32_t for the page iteration counter. The page counter was using an uint8_t which seems unnecessary and might wrap. * sysparam_get_bool: memcpy the binary values out. * FreeRTOS 9.0.1 * Add an argument to ISRs. Disable interrupts while masking them. * sysparam: reserve one more flash sector before placing the sysparams. This is to help work with recent SDKs that add a RF cal sector by default in the fifth last sector - just so the sysparam sectors do not jump around when using different SDK versions. * upnp example: strip down the lwipopts.h file * sysparam editor: accept newline to end a line of input. * Add Wificfg. Uses the sysparam store to save the wifi configuration. Adds a basic http server for configuration. * lwip: disable the tcpip_core_locking_input option. With this option enabled some lwip input processing occurs in the pp task which works well for some uses but some code uses a lot of stack (e.g. mdns) and will overflow the pp task stask, or might unnecessarily slow the critical pp task, so disable this by default and if not already defined. * sdk_cnx_add_rc: fix overflow of the table, when no match is found. Also adds source code for sdk_cnx_rc_search, adding a null pointer dereference. Check (that is not expected to be seen), and source code for sdk_cnx_remove_rc. * http_get example: fix compilation with ipv6 disabled. * lwip: update to master branch. * wificfg: allow the AP channel to be 1. * lwip: rework the tcp ooseq handling. It now accounts for the number of rx pool buffers used and the available memory when deciding the number of ooseq buffers to retain. Enable the TCP Selective ACK support which appears to help a lot on lossy wifi when using the OOSEQ option. * Update lwip, fixes losses of pcbs and associated problems. * lwip: revise the tcp ooseq limit calulations. Was making a mess of the calculation sign. Also added a COPY_PP_RX_PBUFS define to include appropriate limits for this option. * lwip: ooseq_max_bytes() - set a practical target memory size. * lwip: revise ooseq handling. Modified for lwip backwards compatibility based on upstream feedback. * lwip: update to the 2.0.3 release * lwip: merge upstream master. * libc: update to upstream master. * lwip: fix building without TCP_QUEUE_OOSEQ
This commit is contained in:
commit
546cc47121
183 changed files with 10793 additions and 11817 deletions
|
|
@ -152,7 +152,7 @@ bool bmp180_measure(i2c_dev_t *dev, bmp180_constants_t *c, int32_t *temperature,
|
|||
if (!temperature && !pressure)
|
||||
return false;
|
||||
|
||||
// Temperature is always needed, allso required for pressure only.
|
||||
// Temperature is always needed, also required for pressure only.
|
||||
//
|
||||
// Calculation taken from BMP180 Datasheet
|
||||
int32_t UT, X1, X2, B5;
|
||||
|
|
|
|||
|
|
@ -14,18 +14,22 @@
|
|||
* BSD Licensed as described in the file LICENSE
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
|
||||
#include <FreeRTOS.h>
|
||||
#include <task.h>
|
||||
#include <lwip/netif.h>
|
||||
#include <lwip/api.h>
|
||||
#include "esplibs/libmain.h"
|
||||
|
||||
/* Grow the size of the lwip dhcp_msg struct's options field, as LWIP
|
||||
defaults to a 68 octet options field for its DHCP client, and most
|
||||
full-sized clients send us more than this. */
|
||||
#define DHCP_OPTIONS_LEN 312
|
||||
|
||||
#include <lwip/dhcp.h>
|
||||
#include <lwip/ip.h>
|
||||
#include <lwip/prot/dhcp.h>
|
||||
#include <lwip/prot/iana.h>
|
||||
|
||||
_Static_assert(sizeof(struct dhcp_msg) == offsetof(struct dhcp_msg, options) + 312, "dhcp_msg_t should have extended options size");
|
||||
|
||||
|
|
@ -35,15 +39,20 @@ _Static_assert(sizeof(struct dhcp_msg) == offsetof(struct dhcp_msg, options) + 3
|
|||
|
||||
typedef struct {
|
||||
uint8_t hwaddr[NETIF_MAX_HWADDR_LEN];
|
||||
uint8_t active;
|
||||
uint32_t expires;
|
||||
} dhcp_lease_t;
|
||||
|
||||
typedef struct {
|
||||
struct netconn *nc;
|
||||
uint8_t max_leases;
|
||||
ip_addr_t first_client_addr;
|
||||
ip4_addr_t first_client_addr;
|
||||
struct netif *server_if;
|
||||
dhcp_lease_t *leases; /* length max_leases */
|
||||
/* Optional router */
|
||||
ip4_addr_t router;
|
||||
/* Optional DNS server */
|
||||
ip4_addr_t dns;
|
||||
} server_state_t;
|
||||
|
||||
/* Only one DHCP server task can run at once, so we have global state
|
||||
|
|
@ -68,51 +77,67 @@ static uint8_t *add_dhcp_option_bytes(uint8_t *opt, uint8_t type, void *value, u
|
|||
static dhcp_lease_t *find_lease_slot(uint8_t *hwaddr);
|
||||
|
||||
/* Copy IP address as dotted decimal to 'dest', must be at least 16 bytes long */
|
||||
inline static void sprintf_ipaddr(const ip_addr_t *addr, char *dest)
|
||||
inline static void sprintf_ipaddr(const ip4_addr_t *addr, char *dest)
|
||||
{
|
||||
if(addr == NULL)
|
||||
if (addr == NULL)
|
||||
sprintf(dest, "NULL");
|
||||
else
|
||||
sprintf(dest, "%d.%d.%d.%d", ip4_addr1(addr),
|
||||
ip4_addr2(addr), ip4_addr3(addr), ip4_addr4(addr));
|
||||
}
|
||||
|
||||
void dhcpserver_start(const ip_addr_t *first_client_addr, uint8_t max_leases)
|
||||
void dhcpserver_start(const ip4_addr_t *first_client_addr, uint8_t max_leases)
|
||||
{
|
||||
/* Stop any existing running dhcpserver */
|
||||
if(dhcpserver_task_handle)
|
||||
if (dhcpserver_task_handle)
|
||||
dhcpserver_stop();
|
||||
|
||||
state = malloc(sizeof(server_state_t));
|
||||
state->max_leases = max_leases;
|
||||
state->leases = calloc(max_leases, sizeof(dhcp_lease_t));
|
||||
bzero(state->leases, max_leases * sizeof(dhcp_lease_t));
|
||||
// state->server_if is assigned once the task is running - see comment in dhcpserver_task()
|
||||
ip_addr_copy(state->first_client_addr, *first_client_addr);
|
||||
ip4_addr_copy(state->first_client_addr, *first_client_addr);
|
||||
|
||||
xTaskCreate(dhcpserver_task, "DHCPServer", 768, NULL, 8, &dhcpserver_task_handle);
|
||||
/* Clear options */
|
||||
ip4_addr_set_zero(&state->router);
|
||||
ip4_addr_set_zero(&state->dns);
|
||||
|
||||
xTaskCreate(dhcpserver_task, "DHCP Server", 448, NULL, 2, &dhcpserver_task_handle);
|
||||
}
|
||||
|
||||
void dhcpserver_stop(void)
|
||||
{
|
||||
if(dhcpserver_task_handle) {
|
||||
if (dhcpserver_task_handle) {
|
||||
vTaskDelete(dhcpserver_task_handle);
|
||||
free(state);
|
||||
dhcpserver_task_handle = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void dhcpserver_set_router(const ip4_addr_t *router)
|
||||
{
|
||||
ip4_addr_copy(state->router, *router);
|
||||
}
|
||||
|
||||
void dhcpserver_set_dns(const ip4_addr_t *dns)
|
||||
{
|
||||
ip4_addr_copy(state->dns, *dns);
|
||||
}
|
||||
|
||||
static void dhcpserver_task(void *pxParameter)
|
||||
{
|
||||
/* netif_list isn't assigned until after user_init completes, which is why we do it inside the task */
|
||||
state->server_if = netif_list; /* TODO: Make this configurable */
|
||||
|
||||
state->nc = netconn_new (NETCONN_UDP);
|
||||
if(!state->nc) {
|
||||
if (!state->nc) {
|
||||
printf("DHCP Server Error: Failed to allocate socket.\r\n");
|
||||
return;
|
||||
}
|
||||
|
||||
netconn_bind(state->nc, IP_ADDR_ANY, DHCP_SERVER_PORT);
|
||||
netconn_bind(state->nc, IP4_ADDR_ANY, LWIP_IANA_PORT_DHCP_SERVER);
|
||||
netconn_bind_if (state->nc, netif_get_index(state->server_if));
|
||||
|
||||
while(1)
|
||||
{
|
||||
|
|
@ -121,29 +146,32 @@ static void dhcpserver_task(void *pxParameter)
|
|||
|
||||
/* Receive a DHCP packet */
|
||||
err_t err = netconn_recv(state->nc, &netbuf);
|
||||
if(err != ERR_OK) {
|
||||
if (err != ERR_OK) {
|
||||
printf("DHCP Server Error: Failed to receive DHCP packet. err=%d\r\n", err);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* expire any leases that have passed */
|
||||
uint32_t now = xTaskGetTickCount();
|
||||
for(int i = 0; i < state->max_leases; i++) {
|
||||
uint32_t expires = state->leases[i].expires;
|
||||
if(expires && expires < now)
|
||||
state->leases[i].expires = 0;
|
||||
for (int i = 0; i < state->max_leases; i++) {
|
||||
if (state->leases[i].active) {
|
||||
uint32_t expires = state->leases[i].expires - now;
|
||||
if (expires >= 0x80000000) {
|
||||
state->leases[i].active = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ip_addr_t received_ip;
|
||||
u16_t port;
|
||||
netconn_addr(state->nc, &received_ip, &port);
|
||||
|
||||
if(netbuf_len(netbuf) < offsetof(struct dhcp_msg, options)) {
|
||||
if (netbuf_len(netbuf) < offsetof(struct dhcp_msg, options)) {
|
||||
/* too short to be a valid DHCP client message */
|
||||
netbuf_delete(netbuf);
|
||||
continue;
|
||||
}
|
||||
if(netbuf_len(netbuf) >= sizeof(struct dhcp_msg)) {
|
||||
if (netbuf_len(netbuf) >= sizeof(struct dhcp_msg)) {
|
||||
printf("DHCP Server Warning: Client sent more options than we know how to parse. len=%d\r\n", netbuf_len(netbuf));
|
||||
}
|
||||
|
||||
|
|
@ -152,18 +180,18 @@ static void dhcpserver_task(void *pxParameter)
|
|||
|
||||
uint8_t *message_type = find_dhcp_option(&received, DHCP_OPTION_MESSAGE_TYPE,
|
||||
DHCP_OPTION_MESSAGE_TYPE_LEN, NULL);
|
||||
if(!message_type) {
|
||||
if (!message_type) {
|
||||
printf("DHCP Server Error: No message type field found");
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
printf("State dump. Message type %d\n", *message_type);
|
||||
for(int i = 0; i < state->max_leases; i++) {
|
||||
for (int i = 0; i < state->max_leases; i++) {
|
||||
dhcp_lease_t *lease = &state->leases[i];
|
||||
printf("lease slot %d expiry %d hwaddr %02x:%02x:%02x:%02x:%02x:%02x\r\n", i, lease->expires, lease->hwaddr[0],
|
||||
lease->hwaddr[1], lease->hwaddr[2], lease->hwaddr[3], lease->hwaddr[4],
|
||||
lease->hwaddr[5]);
|
||||
printf("lease slot %d active %d expiry %d hwaddr %02x:%02x:%02x:%02x:%02x:%02x\r\n", i,
|
||||
lease->active, lease->expires - now,
|
||||
lease->hwaddr[0], lease->hwaddr[1], lease->hwaddr[2],
|
||||
lease->hwaddr[3], lease->hwaddr[4], lease->hwaddr[5]);
|
||||
}
|
||||
|
||||
switch(*message_type) {
|
||||
|
|
@ -184,13 +212,13 @@ static void dhcpserver_task(void *pxParameter)
|
|||
|
||||
static void handle_dhcp_discover(struct dhcp_msg *dhcpmsg)
|
||||
{
|
||||
if(dhcpmsg->htype != DHCP_HTYPE_ETH)
|
||||
if (dhcpmsg->htype != LWIP_IANA_HWTYPE_ETHERNET)
|
||||
return;
|
||||
if(dhcpmsg->hlen > NETIF_MAX_HWADDR_LEN)
|
||||
if (dhcpmsg->hlen > NETIF_MAX_HWADDR_LEN)
|
||||
return;
|
||||
|
||||
dhcp_lease_t *freelease = find_lease_slot(dhcpmsg->chaddr);
|
||||
if(!freelease) {
|
||||
if (!freelease) {
|
||||
printf("DHCP Server: All leases taken.\r\n");
|
||||
return; /* Nothing available, so do nothing */
|
||||
}
|
||||
|
|
@ -199,13 +227,19 @@ static void handle_dhcp_discover(struct dhcp_msg *dhcpmsg)
|
|||
dhcpmsg->op = DHCP_BOOTREPLY;
|
||||
bzero(dhcpmsg->options, DHCP_OPTIONS_LEN);
|
||||
|
||||
ip_addr_copy(dhcpmsg->yiaddr, state->first_client_addr);
|
||||
ip4_addr4(&(dhcpmsg->yiaddr)) += (freelease - state->leases);
|
||||
dhcpmsg->yiaddr.addr = lwip_htonl(lwip_ntohl(state->first_client_addr.addr) + (freelease - state->leases));
|
||||
|
||||
uint8_t *opt = (uint8_t *)&dhcpmsg->options;
|
||||
opt = add_dhcp_option_byte(opt, DHCP_OPTION_MESSAGE_TYPE, DHCP_OFFER);
|
||||
opt = add_dhcp_option_bytes(opt, DHCP_OPTION_SERVER_ID, &state->server_if->ip_addr, 4);
|
||||
opt = add_dhcp_option_bytes(opt, DHCP_OPTION_SUBNET_MASK, &state->server_if->netmask, 4);
|
||||
if (!ip4_addr_isany_val(state->router)) {
|
||||
opt = add_dhcp_option_bytes(opt, DHCP_OPTION_ROUTER, &state->router, 4);
|
||||
}
|
||||
if (!ip4_addr_isany_val(state->dns)) {
|
||||
opt = add_dhcp_option_bytes(opt, DHCP_OPTION_DNS_SERVER, &state->dns, 4);
|
||||
}
|
||||
|
||||
opt = add_dhcp_option_bytes(opt, DHCP_OPTION_END, NULL, 0);
|
||||
|
||||
struct netbuf *netbuf = netbuf_new();
|
||||
|
|
@ -218,17 +252,17 @@ static void handle_dhcp_discover(struct dhcp_msg *dhcpmsg)
|
|||
static void handle_dhcp_request(struct dhcp_msg *dhcpmsg)
|
||||
{
|
||||
static char ipbuf[16];
|
||||
if(dhcpmsg->htype != DHCP_HTYPE_ETH)
|
||||
if (dhcpmsg->htype != LWIP_IANA_HWTYPE_ETHERNET)
|
||||
return;
|
||||
if(dhcpmsg->hlen > NETIF_MAX_HWADDR_LEN)
|
||||
if (dhcpmsg->hlen > NETIF_MAX_HWADDR_LEN)
|
||||
return;
|
||||
|
||||
ip_addr_t requested_ip;
|
||||
ip4_addr_t requested_ip;
|
||||
uint8_t *requested_ip_opt = find_dhcp_option(dhcpmsg, DHCP_OPTION_REQUESTED_IP, 4, NULL);
|
||||
if(requested_ip_opt) {
|
||||
memcpy(&requested_ip.addr, requested_ip_opt, 4);
|
||||
} else if(ip_addr_cmp(&requested_ip, IP_ADDR_ANY)) {
|
||||
ip_addr_copy(requested_ip, dhcpmsg->ciaddr);
|
||||
if (requested_ip_opt) {
|
||||
memcpy(&requested_ip.addr, requested_ip_opt, 4);
|
||||
} else if (ip4_addr_cmp(&requested_ip, IP4_ADDR_ANY4)) {
|
||||
ip4_addr_copy(requested_ip, dhcpmsg->ciaddr);
|
||||
} else {
|
||||
printf("DHCP Server Error: No requested IP\r\n");
|
||||
send_dhcp_nak(dhcpmsg);
|
||||
|
|
@ -236,7 +270,7 @@ static void handle_dhcp_request(struct dhcp_msg *dhcpmsg)
|
|||
}
|
||||
|
||||
/* Test the first 4 octets match */
|
||||
if(ip4_addr1(&requested_ip) != ip4_addr1(&state->first_client_addr)
|
||||
if (ip4_addr1(&requested_ip) != ip4_addr1(&state->first_client_addr)
|
||||
|| ip4_addr2(&requested_ip) != ip4_addr2(&state->first_client_addr)
|
||||
|| ip4_addr3(&requested_ip) != ip4_addr3(&state->first_client_addr)) {
|
||||
sprintf_ipaddr(&requested_ip, ipbuf);
|
||||
|
|
@ -246,14 +280,14 @@ static void handle_dhcp_request(struct dhcp_msg *dhcpmsg)
|
|||
}
|
||||
/* Test the last octet is in the MAXCLIENTS range */
|
||||
int16_t octet_offs = ip4_addr4(&requested_ip) - ip4_addr4(&state->first_client_addr);
|
||||
if(octet_offs < 0 || octet_offs >= state->max_leases) {
|
||||
if (octet_offs < 0 || octet_offs >= state->max_leases) {
|
||||
printf("DHCP Server Error: Address out of range\r\n");
|
||||
send_dhcp_nak(dhcpmsg);
|
||||
return;
|
||||
}
|
||||
|
||||
dhcp_lease_t *requested_lease = state->leases + octet_offs;
|
||||
if(requested_lease->expires != 0 && memcmp(requested_lease->hwaddr, dhcpmsg->chaddr,dhcpmsg->hlen))
|
||||
if (requested_lease->active && memcmp(requested_lease->hwaddr, dhcpmsg->chaddr,dhcpmsg->hlen))
|
||||
{
|
||||
printf("DHCP Server Error: Lease for address already taken\r\n");
|
||||
send_dhcp_nak(dhcpmsg);
|
||||
|
|
@ -265,13 +299,17 @@ static void handle_dhcp_request(struct dhcp_msg *dhcpmsg)
|
|||
printf("DHCP lease addr %s assigned to MAC %02x:%02x:%02x:%02x:%02x:%02x\r\n", ipbuf, requested_lease->hwaddr[0],
|
||||
requested_lease->hwaddr[1], requested_lease->hwaddr[2], requested_lease->hwaddr[3], requested_lease->hwaddr[4],
|
||||
requested_lease->hwaddr[5]);
|
||||
requested_lease->expires = DHCPSERVER_LEASE_TIME * configTICK_RATE_HZ;
|
||||
uint32_t now = xTaskGetTickCount();
|
||||
requested_lease->expires = now + DHCPSERVER_LEASE_TIME * configTICK_RATE_HZ;
|
||||
requested_lease->active = 1;
|
||||
|
||||
sdk_wifi_softap_set_station_info(requested_lease->hwaddr, &requested_ip);
|
||||
|
||||
/* Reuse the REQUEST message as the ACK message */
|
||||
dhcpmsg->op = DHCP_BOOTREPLY;
|
||||
bzero(dhcpmsg->options, DHCP_OPTIONS_LEN);
|
||||
|
||||
ip_addr_copy(dhcpmsg->yiaddr, requested_ip);
|
||||
ip4_addr_copy(dhcpmsg->yiaddr, requested_ip);
|
||||
|
||||
uint8_t *opt = (uint8_t *)&dhcpmsg->options;
|
||||
opt = add_dhcp_option_byte(opt, DHCP_OPTION_MESSAGE_TYPE, DHCP_ACK);
|
||||
|
|
@ -279,6 +317,13 @@ static void handle_dhcp_request(struct dhcp_msg *dhcpmsg)
|
|||
opt = add_dhcp_option_bytes(opt, DHCP_OPTION_LEASE_TIME, &expiry, 4);
|
||||
opt = add_dhcp_option_bytes(opt, DHCP_OPTION_SERVER_ID, &state->server_if->ip_addr, 4);
|
||||
opt = add_dhcp_option_bytes(opt, DHCP_OPTION_SUBNET_MASK, &state->server_if->netmask, 4);
|
||||
if (!ip4_addr_isany_val(state->router)) {
|
||||
opt = add_dhcp_option_bytes(opt, DHCP_OPTION_ROUTER, &state->router, 4);
|
||||
}
|
||||
if (!ip4_addr_isany_val(state->dns)) {
|
||||
opt = add_dhcp_option_bytes(opt, DHCP_OPTION_DNS_SERVER, &state->dns, 4);
|
||||
}
|
||||
|
||||
opt = add_dhcp_option_bytes(opt, DHCP_OPTION_END, NULL, 0);
|
||||
|
||||
struct netbuf *netbuf = netbuf_new();
|
||||
|
|
@ -291,7 +336,8 @@ static void handle_dhcp_request(struct dhcp_msg *dhcpmsg)
|
|||
static void handle_dhcp_release(struct dhcp_msg *dhcpmsg)
|
||||
{
|
||||
dhcp_lease_t *lease = find_lease_slot(dhcpmsg->chaddr);
|
||||
if(lease) {
|
||||
if (lease) {
|
||||
lease->active = 0;
|
||||
lease->expires = 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -319,17 +365,17 @@ static uint8_t *find_dhcp_option(struct dhcp_msg *msg, uint8_t option_num, uint8
|
|||
uint8_t *start = (uint8_t *)&msg->options;
|
||||
uint8_t *msg_end = (uint8_t *)msg + sizeof(struct dhcp_msg);
|
||||
|
||||
for(uint8_t *p = start; p < msg_end-2;) {
|
||||
for (uint8_t *p = start; p < msg_end-2;) {
|
||||
uint8_t type = *p++;
|
||||
uint8_t len = *p++;
|
||||
if(type == DHCP_OPTION_END)
|
||||
if (type == DHCP_OPTION_END)
|
||||
return NULL;
|
||||
if(p+len >= msg_end)
|
||||
if (p+len >= msg_end)
|
||||
break; /* We've overrun our valid DHCP message size, or this isn't a valid option */
|
||||
if(type == option_num) {
|
||||
if(len < min_length)
|
||||
if (type == option_num) {
|
||||
if (len < min_length)
|
||||
break;
|
||||
if(length)
|
||||
if (length)
|
||||
*length = len;
|
||||
return p; /* start of actual option data */
|
||||
}
|
||||
|
|
@ -349,7 +395,7 @@ static uint8_t *add_dhcp_option_byte(uint8_t *opt, uint8_t type, uint8_t value)
|
|||
static uint8_t *add_dhcp_option_bytes(uint8_t *opt, uint8_t type, void *value, uint8_t len)
|
||||
{
|
||||
*opt++ = type;
|
||||
if(len) {
|
||||
if (len) {
|
||||
*opt++ = len;
|
||||
memcpy(opt, value, len);
|
||||
}
|
||||
|
|
@ -360,8 +406,8 @@ static uint8_t *add_dhcp_option_bytes(uint8_t *opt, uint8_t type, void *value, u
|
|||
static dhcp_lease_t *find_lease_slot(uint8_t *hwaddr)
|
||||
{
|
||||
dhcp_lease_t *empty_lease = NULL;
|
||||
for(int i = 0; i < state->max_leases; i++) {
|
||||
if(state->leases[i].expires == 0 && !empty_lease)
|
||||
for (int i = 0; i < state->max_leases; i++) {
|
||||
if (!state->leases[i].active && !empty_lease)
|
||||
empty_lease = &state->leases[i];
|
||||
else if (memcmp(hwaddr, state->leases[i].hwaddr, 6) == 0)
|
||||
return &state->leases[i];
|
||||
|
|
|
|||
|
|
@ -26,14 +26,20 @@ extern "C" {
|
|||
to a client. Subsequent lease addresses are calculated by
|
||||
incrementing the final octet of the IPv4 address, up to max_leases.
|
||||
*/
|
||||
void dhcpserver_start(const ip_addr_t *first_client_addr, uint8_t max_leases);
|
||||
void dhcpserver_start(const ip4_addr_t *first_client_addr, uint8_t max_leases);
|
||||
|
||||
void dhcpserver_get_lease(const ip_addr_t *first_client_addr, uint8_t max_leases);
|
||||
void dhcpserver_get_lease(const ip4_addr_t *first_client_addr, uint8_t max_leases);
|
||||
|
||||
/* Stop DHCP server.
|
||||
*/
|
||||
void dhcpserver_stop(void);
|
||||
|
||||
/* Set a router address to send as an option. */
|
||||
void dhcpserver_set_router(const ip4_addr_t *router);
|
||||
|
||||
/* Set a DNS address to send as an option. */
|
||||
void dhcpserver_set_dns(const ip4_addr_t *dns);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -15,13 +15,13 @@
|
|||
/* Convert normal decimal to binary coded decimal */
|
||||
static inline uint8_t decToBcd(uint8_t dec)
|
||||
{
|
||||
return(((dec / 10) * 16) + (dec % 10));
|
||||
return (dec / 10) * 16 + dec % 10;
|
||||
}
|
||||
|
||||
/* Convert binary coded decimal to normal decimal */
|
||||
static inline uint8_t bcdToDec(uint8_t bcd)
|
||||
{
|
||||
return(((bcd / 16) * 10) + (bcd % 16));
|
||||
return (bcd / 16) * 10 + bcd % 16;
|
||||
}
|
||||
|
||||
/* Send a number of bytes to the rtc over i2c
|
||||
|
|
@ -48,6 +48,8 @@ int ds3231_setTime(i2c_dev_t *dev, struct tm *time)
|
|||
data[0] = decToBcd(time->tm_sec);
|
||||
data[1] = decToBcd(time->tm_min);
|
||||
data[2] = decToBcd(time->tm_hour);
|
||||
/* The week data must be in the range 1 to 7, and to keep the start on the
|
||||
* same day as for tm_wday have it start at 1 on Sunday. */
|
||||
data[3] = decToBcd(time->tm_wday + 1);
|
||||
data[4] = decToBcd(time->tm_mday);
|
||||
data[5] = decToBcd(time->tm_mon + 1);
|
||||
|
|
|
|||
|
|
@ -139,7 +139,7 @@
|
|||
|
||||
/** Set this to 1 on platforms where strnstr is not available */
|
||||
#ifndef LWIP_HTTPD_STRNSTR_PRIVATE
|
||||
#define LWIP_HTTPD_STRNSTR_PRIVATE 1
|
||||
#define LWIP_HTTPD_STRNSTR_PRIVATE 0
|
||||
#endif
|
||||
|
||||
/** Set this to one to show error pages when parsing a request fails instead
|
||||
|
|
@ -2675,7 +2675,7 @@ http_accept(void *arg, struct tcp_pcb *pcb, err_t err)
|
|||
* Initialize the httpd with the specified local address.
|
||||
*/
|
||||
static void
|
||||
httpd_init_addr(ip_addr_t *local_addr)
|
||||
httpd_init_addr(const ip_addr_t *local_addr)
|
||||
{
|
||||
struct tcp_pcb *pcb;
|
||||
err_t err;
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ void sdk_rom_i2c_writeReg_Mask(uint32_t block, uint32_t host_id,
|
|||
reg_add##_lsb, indata)
|
||||
|
||||
|
||||
void i2s_dma_init(i2s_dma_isr_t isr, i2s_clock_div_t clock_div, i2s_pins_t pins)
|
||||
void i2s_dma_init(i2s_dma_isr_t isr, void *arg, i2s_clock_div_t clock_div, i2s_pins_t pins)
|
||||
{
|
||||
// reset DMA
|
||||
SET_MASK_BITS(SLC.CONF0, SLC_CONF0_RX_LINK_RESET);
|
||||
|
|
@ -83,7 +83,7 @@ void i2s_dma_init(i2s_dma_isr_t isr, i2s_clock_div_t clock_div, i2s_pins_t pins)
|
|||
SLC_RX_DESCRIPTOR_CONF_RX_EOF_MODE | SLC_RX_DESCRIPTOR_CONF_RX_FILL_MODE);
|
||||
|
||||
if (isr) {
|
||||
_xt_isr_attach(INUM_SLC, isr);
|
||||
_xt_isr_attach(INUM_SLC, isr, arg);
|
||||
SET_MASK_BITS(SLC.INT_ENABLE, SLC_INT_ENABLE_RX_EOF);
|
||||
SLC.INT_CLEAR = 0xFFFFFFFF;
|
||||
_xt_isr_unmask(1<<INUM_SLC);
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef void (*i2s_dma_isr_t)(void);
|
||||
typedef void (*i2s_dma_isr_t)(void *);
|
||||
|
||||
typedef struct dma_descriptor {
|
||||
uint32_t blocksize:12;
|
||||
|
|
@ -61,10 +61,11 @@ typedef struct {
|
|||
* Initialize I2S and DMA subsystems.
|
||||
*
|
||||
* @param isr ISR handler. Can be NULL if interrupt handling is not needed.
|
||||
* @param arg ISR handler arg.
|
||||
* @param clock_div I2S clock configuration.
|
||||
* @param pins I2S pin configuration. Specifies which pins are enabled in I2S.
|
||||
*/
|
||||
void i2s_dma_init(i2s_dma_isr_t isr, i2s_clock_div_t clock_div, i2s_pins_t pins);
|
||||
void i2s_dma_init(i2s_dma_isr_t isr, void *arg, i2s_clock_div_t clock_div, i2s_pins_t pins);
|
||||
|
||||
/**
|
||||
* Calculate I2S dividers for the specified frequency.
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ typedef struct pwmInfoDefinition
|
|||
|
||||
static PWMInfo pwmInfo;
|
||||
|
||||
static void frc1_interrupt_handler(void)
|
||||
static void frc1_interrupt_handler(void *arg)
|
||||
{
|
||||
uint8_t i = 0;
|
||||
bool out = true;
|
||||
|
|
@ -97,7 +97,7 @@ void pwm_init(uint8_t npins, const uint8_t* pins)
|
|||
pwm_stop();
|
||||
|
||||
/* set up ISRs */
|
||||
_xt_isr_attach(INUM_TIMER_FRC1, frc1_interrupt_handler);
|
||||
_xt_isr_attach(INUM_TIMER_FRC1, frc1_interrupt_handler, NULL);
|
||||
|
||||
/* Flag not running */
|
||||
pwmInfo.running = 0;
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@
|
|||
|
||||
#include "sntp.h"
|
||||
|
||||
#include "lwip/timers.h"
|
||||
#include "lwip/timeouts.h"
|
||||
#include "lwip/udp.h"
|
||||
#include "lwip/dns.h"
|
||||
#include "lwip/ip_addr.h"
|
||||
|
|
@ -136,12 +136,12 @@
|
|||
#define SNTP_STARTUP_DELAY 0
|
||||
#endif
|
||||
|
||||
/** SNTP receive timeout - in milliseconds
|
||||
/** SNTP receive timeout - in seconds
|
||||
* Also used as retry timeout - this shouldn't be too low.
|
||||
* Default is 3 seconds.
|
||||
*/
|
||||
#ifndef SNTP_RECV_TIMEOUT
|
||||
#define SNTP_RECV_TIMEOUT 3000
|
||||
#define SNTP_RECV_TIMEOUT 3
|
||||
#endif
|
||||
|
||||
/** SNTP update delay - in milliseconds
|
||||
|
|
@ -384,8 +384,8 @@ sntp_request(void *arg)
|
|||
/* bind to local address */
|
||||
if (lwip_bind(sock, (struct sockaddr *)&local, sizeof(local)) == 0) {
|
||||
/* set recv timeout */
|
||||
timeout = SNTP_RECV_TIMEOUT;
|
||||
lwip_setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout));
|
||||
const struct timeval timeout = { SNTP_RECV_TIMEOUT, 0 };
|
||||
setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
|
||||
|
||||
/* prepare SNTP request */
|
||||
sntp_initialize_request(&sntpmsg);
|
||||
|
|
@ -511,7 +511,7 @@ sntp_try_next_server(void* arg)
|
|||
|
||||
/** UDP recv callback for the sntp pcb */
|
||||
static void
|
||||
sntp_recv(void *arg, struct udp_pcb* pcb, struct pbuf *p, ip_addr_t *addr, u16_t port)
|
||||
sntp_recv(void *arg, struct udp_pcb* pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port)
|
||||
{
|
||||
u8_t mode;
|
||||
u8_t stratum;
|
||||
|
|
@ -597,7 +597,7 @@ sntp_recv(void *arg, struct udp_pcb* pcb, struct pbuf *p, ip_addr_t *addr, u16_t
|
|||
* @param server_addr resolved IP address of the SNTP server
|
||||
*/
|
||||
static void
|
||||
sntp_send_request(ip_addr_t *server_addr)
|
||||
sntp_send_request(const ip_addr_t *server_addr)
|
||||
{
|
||||
struct pbuf* p;
|
||||
p = pbuf_alloc(PBUF_TRANSPORT, SNTP_MSG_LEN, PBUF_RAM);
|
||||
|
|
@ -611,7 +611,7 @@ sntp_send_request(ip_addr_t *server_addr)
|
|||
pbuf_free(p);
|
||||
|
||||
/* set up receive timeout: try next server or retry on timeout */
|
||||
sys_timeout((u32_t)SNTP_RECV_TIMEOUT, sntp_try_next_server, NULL);
|
||||
sys_timeout((u32_t)SNTP_RECV_TIMEOUT * 1000, sntp_try_next_server, NULL);
|
||||
#if SNTP_CHECK_RESPONSE >= 1
|
||||
/* save server address to verify it in sntp_recv */
|
||||
ip_addr_set(&sntp_last_server_address, server_addr);
|
||||
|
|
@ -629,7 +629,7 @@ sntp_send_request(ip_addr_t *server_addr)
|
|||
* DNS found callback when using DNS names as server address.
|
||||
*/
|
||||
static void
|
||||
sntp_dns_found(const char* hostname, ip_addr_t *ipaddr, void *arg)
|
||||
sntp_dns_found(const char* hostname, const ip_addr_t *ipaddr, void *arg)
|
||||
{
|
||||
LWIP_UNUSED_ARG(hostname);
|
||||
LWIP_UNUSED_ARG(arg);
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ void sntp_update_rtc(time_t t, uint32_t us) {
|
|||
// DEBUG: Compute and print drift
|
||||
int64_t sntp_current = sntp_base + TIMER_COUNT - tim_ref;
|
||||
int64_t sntp_correct = (((uint64_t)us + (uint64_t)t * 1000000U)<<12) / cal;
|
||||
printf("\nRTC Adjust: drift = %ld ticks, cal = %d\n", (time_t)(sntp_correct - sntp_current), cal);
|
||||
printf("\nRTC Adjust: drift = %lld ticks, cal = %d\n", (time_t)(sntp_correct - sntp_current), (uint32_t)cal);
|
||||
|
||||
tim_ref = TIMER_COUNT;
|
||||
cal = sdk_system_rtc_clock_cali_proc();
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ static SemaphoreHandle_t uart0_sem = NULL;
|
|||
static bool inited = false;
|
||||
static void uart0_rx_init(void);
|
||||
|
||||
IRAM void uart0_rx_handler(void)
|
||||
IRAM void uart0_rx_handler(void *arg)
|
||||
{
|
||||
// TODO: Handle UART1, see reg 0x3ff20020, bit2, bit0 represents uart1 and uart0 respectively
|
||||
if (!UART(UART0).INT_STATUS & UART_INT_STATUS_RXFIFO_FULL) {
|
||||
|
|
@ -97,7 +97,7 @@ static void uart0_rx_init(void)
|
|||
int trig_lvl = 1;
|
||||
uart0_sem = xSemaphoreCreateCounting(UART0_RX_SIZE, 0);
|
||||
|
||||
_xt_isr_attach(INUM_UART, uart0_rx_handler);
|
||||
_xt_isr_attach(INUM_UART, uart0_rx_handler, NULL);
|
||||
_xt_isr_unmask(1 << INUM_UART);
|
||||
|
||||
// reset the rx fifo
|
||||
|
|
|
|||
10
extras/wificfg/component.mk
Normal file
10
extras/wificfg/component.mk
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
# Component makefile for extras/wificfg
|
||||
|
||||
# Expected anyone using wificfg includes it as 'wificfg/wificfg.h'
|
||||
INC_DIRS += $(wificfg_ROOT)..
|
||||
|
||||
# args for passing into compile rule generation
|
||||
wificfg_INC_DIR =
|
||||
wificfg_SRC_DIR = $(wificfg_ROOT)
|
||||
|
||||
$(eval $(call component_compile_rules,wificfg))
|
||||
30
extras/wificfg/content/challenge.html
Normal file
30
extras/wificfg/content/challenge.html
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
"<!DOCTYPE html><html lang=\"en\">"
|
||||
"<head>"
|
||||
"<link rel=\"stylesheet\" type=\"text/css\" href=\"/style.css\">"
|
||||
"<script src=\"/script.js\"></script>"
|
||||
"<title>",
|
||||
"</title>"
|
||||
"<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">"
|
||||
"</head>"
|
||||
"<body>"
|
||||
"<ul class=\"topnav\" id=\"myTopnav\">"
|
||||
"<li><a href=\"/\">Home</a></li>"
|
||||
"<li class=\"active\"><a href=\"/wificfg/\">WiFi Config</a></li>"
|
||||
"<li><a href=\"/wificfg/sta.html\">WiFi Station</a></li>"
|
||||
"<li><a href=\"/wificfg/ap.html\">WiFi Access Point</a></li>"
|
||||
"<li class=\"icon\">"
|
||||
"<a href=\"javascript:void(0);\" onclick=\"myFunction()\">☰</a>"
|
||||
"</li>"
|
||||
"</ul>"
|
||||
"<form action=\"/challenge.html\" method=\"post\">"
|
||||
"<fieldset>"
|
||||
"<legend>Unlock the configuration interface</legend>"
|
||||
"<dl class=\"dlh\">"
|
||||
"<dt><label for=\"pw\">Password</label></dt>"
|
||||
"<dd><input id=\"pw\" type=\"text\" maxlength=\"32\" name=\"cfg_password\" "
|
||||
"placeholder=\"unlock-password\" value=\"\"></dd>"
|
||||
"</dl>"
|
||||
"<center><input type=\"submit\" value=\"Unlock\"></center>"
|
||||
"</fieldset>"
|
||||
"</form>"
|
||||
"</body></html>"
|
||||
11
extras/wificfg/content/favicon.ico
Normal file
11
extras/wificfg/content/favicon.ico
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
"HTTP/1.1 200 \r\n"
|
||||
"Content-Type: image/svg+xml\r\n"
|
||||
"Cache-Control: max-age=900\r\n"
|
||||
"Transfer-Encoding: chunked\r\n"
|
||||
"Connection: close\r\n"
|
||||
"\r\n",
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>"
|
||||
"<svg xmlns:svg=\"http://www.w3.org/2000/svg\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 48 48\" version=\"1.1\">"
|
||||
"<defs><linearGradient id=\"g1\" y2=\"248.63\" gradientUnits=\"userSpaceOnUse\" x2=\"153\" gradientTransform=\"matrix(.20068 0 0 .20068 -54.336 -1.0508)\" y1=\"15.424\" x1=\"99.777\"><stop style=\"stop-color:#0088FF\" offset=\"0\"/><stop style=\"stop-color:#b2dbff\" offset=\"1\"/></linearGradient></defs>"
|
||||
"<path style=\"stroke-linejoin:round;color:#000000;stroke:#aaaaaa;stroke-linecap:round;fill:url(#g1)\" d=\"m22.7 0.94747c-0.474 0.03238-0.934 0.10563-1.398 0.15883h-0.032l-1.112 6.068c-1.812 0.4127-3.517 1.1132-5.051 2.065l-4.988-3.59c-1.3485 1.0468-2.5754 2.2677-3.6536 3.59l3.4628 5.0517c-1.0514 1.606-1.842 3.441-2.2874 5.369v0.031l-6.0361 0.953c-0.1104 0.902-0.1589 1.833-0.1589 2.764 0 0.762 0.021 1.514 0.0953 2.256l6.0362 1.08c0.4293 2.096 1.2448 4.054 2.3827 5.782l-3.5899 4.924c1.0281 1.277 2.2151 2.439 3.4946 3.463l5.0833-3.494c1.776 1.133 3.759 1.928 5.909 2.319l0.953 6.004c0.677 0.062 1.372 0.064 2.065 0.064 0.979 0 1.914-0.037 2.859-0.159l1.144-6.132c2.041-0.507 3.958-1.389 5.623-2.573l4.893 3.558c1.268-1.079 2.429-2.32 3.431-3.653l-3.558-5.147c0.963-1.664 1.631-3.5 1.969-5.464l6.005-0.953c0.052-0.627 0.063-1.234 0.063-1.875 0-1.112-0.129-2.203-0.286-3.272l-6.099-1.112c-0.478-1.765-1.263-3.412-2.256-4.892l3.59-4.9245c-1.113-1.3608-2.382-2.618-3.781-3.6852l-5.178 3.5581c-1.488-0.8802-3.09-1.5556-4.829-1.9379l-0.953-6.0362c-0.868-0.102-1.742-0.15883-2.637-0.15883-0.242 0-0.491-0.00761-0.731 0-0.117 0.00371-0.232-0.00681-0.349 0-0.032 0.00184-0.064-0.00216-0.095 0zm0.826 15.44c0.116-0.006 0.231 0 0.349 0 3.761 0 6.83 3.07 6.83 6.831 0 3.76-3.069 6.798-6.83 6.798s-6.799-3.038-6.799-6.798c0-3.643 2.852-6.648 6.45-6.831z\"/>"
|
||||
"</svg>"
|
||||
8
extras/wificfg/content/script.js
Normal file
8
extras/wificfg/content/script.js
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
"HTTP/1.1 200 \r\n"
|
||||
"Content-Type: text/javascript\r\n"
|
||||
"Cache-Control: max-age=900\r\n"
|
||||
"Transfer-Encoding: chunked\r\n"
|
||||
"Connection: close\r\n"
|
||||
"\r\n",
|
||||
"function myFunction() { var x = document.getElementById(\"myTopnav\");"
|
||||
"if (x.className === \"topnav\") { x.className += \" responsive\"; } else { x.className = \"topnav\"; } }"
|
||||
19
extras/wificfg/content/style.css
Normal file
19
extras/wificfg/content/style.css
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
"HTTP/1.1 200 \r\n"
|
||||
"Content-Type: text/css\r\n"
|
||||
"Cache-Control: max-age=900\r\n"
|
||||
"Transfer-Encoding: chunked\r\n"
|
||||
"\r\n",
|
||||
".dlh dd,h1{font-weight:300}.dlh{font-size:0;text-align:center}"
|
||||
".dlh dd,.dlh dt{width:48%;width:calc(50% - 10px);margin:8px 0;display:inline-block;font-size:16px;vertical-align:middle}"
|
||||
".dlh dt{text-align:right;padding-right:10px}"
|
||||
".dlh dd{font-size:18px;text-align:left;padding-left:10px}"
|
||||
"ul.topnav{list-style-type:none;margin:0;padding:0;overflow:hidden;background-color:#bbb}"
|
||||
"ul.topnav li{float:left}"
|
||||
"ul.topnav li a{display:inline-block;color:#444;text-align:center;padding:14px 16px;text-decoration:none;transition:.3s;font-size:17px}"
|
||||
"ul.topnav li a:hover{background-color:#ddd}ul.topnav li.icon{display:none}"
|
||||
"@media screen and (max-width:680px){ul.topnav li:not(.active){display:none}ul.topnav li.icon{float:right;display:inline-block}ul.topnav.responsive{position:relative}ul.topnav.responsive li.icon{position:absolute;right:0;top:0}ul.topnav.responsive li{float:none;display:inline}ul.topnav.responsive li a{display:block;text-align:left}}"
|
||||
"html{min-height:100%}"
|
||||
"body{background:#d0e4f7;background:-moz-linear-gradient(top, #d0e4f7 0%, #73b1e7 24%, #0a77d5 50%, #539fe1 79%, #87bcea 100%);background:-webkit-linear-gradient(top, #d0e4f7 0%,#73b1e7 24%,#0a77d5 50%,#539fe1 79%,#87bcea 100%);background:linear-gradient(to bottom, #d0e4f7 0%,#73b1e7 24%,#0a77d5 50%,#539fe1 79%,#87bcea 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#d0e4f7', endColorstr='#87bcea',GradientType=0)}"
|
||||
"body{font-family:helvetica,arial,sans-serif;font-size:16px}"
|
||||
"h1{font-size:26px}"
|
||||
"p{font-size:14px}"
|
||||
18
extras/wificfg/content/tasks.html
Normal file
18
extras/wificfg/content/tasks.html
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
"<!DOCTYPE html><html lang=\"en\">"
|
||||
"<head>"
|
||||
"<link rel=\"stylesheet\" type=\"text/css\" href=\"/style.css\">"
|
||||
"<script src=\"/script.js\"></script>"
|
||||
"<title>",
|
||||
"</title>"
|
||||
"<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">"
|
||||
"</head>"
|
||||
"<body>"
|
||||
"<ul class=\"topnav\" id=\"myTopnav\">"
|
||||
"<li><a href=\"/\">Home</a></li>"
|
||||
"<li><a href=\"/wificfg/\">WiFi Config</a></li>"
|
||||
"<li class=\"active\"><a href=\"/tasks.html\">Tasks</a></li>"
|
||||
"<li class=\"icon\">"
|
||||
"<a href=\"javascript:void(0);\" onclick=\"myFunction()\">☰</a>"
|
||||
"</li>"
|
||||
"</ul>",
|
||||
"</body></html>"
|
||||
90
extras/wificfg/content/wificfg/ap.html
Normal file
90
extras/wificfg/content/wificfg/ap.html
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
"<!DOCTYPE html><html lang=\"en\">"
|
||||
"<head>"
|
||||
"<link rel=\"stylesheet\" type=\"text/css\" href=\"/style.css\">"
|
||||
"<script src=\"/script.js\"></script>"
|
||||
"<title>",
|
||||
"</title>"
|
||||
"<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">"
|
||||
"</head>"
|
||||
"<body>"
|
||||
"<ul class=\"topnav\" id=\"myTopnav\">"
|
||||
"<li><a href=\"/\">Home</a></li>"
|
||||
"<li><a href=\"/wificfg/\">WiFi Config</a></li>"
|
||||
"<li><a href=\"/wificfg/sta.html\">WiFi Station</a></li>"
|
||||
"<li class=\"active\"><a href=\"/wificfg/ap.html\">WiFi Access Point</a></li>"
|
||||
"<li class=\"icon\">"
|
||||
"<a href=\"javascript:void(0);\" onclick=\"myFunction()\">☰</a>"
|
||||
"</li>"
|
||||
"</ul>"
|
||||
"<form action=\"/wificfg/ap.html\" method=\"post\">"
|
||||
"<fieldset>"
|
||||
"<legend>WiFi Access Point configuration</legend>"
|
||||
"<dl class=\"dlh\">"
|
||||
"<dt><label for=\"enable\">Enable AP mode</label></dt>"
|
||||
"<dd><input id=\"enable\" type=\"checkbox\" name=\"ap_enable\" value=\"1\" ",
|
||||
" /></dd>"
|
||||
"<dt><label for=\"disable_if_sta\">Auto disable if station connection</label></dt>"
|
||||
"<dd><input id=\"hidden\" type=\"checkbox\" name=\"ap_disable_if_sta\" value=\"1\" ",
|
||||
" /></dd>"
|
||||
"<dt><label for=\"disabled_restarts\">Disabled restarts</label></dt>"
|
||||
"<dd><input id=\"disabled_restarts\" type=\"number\" size=\"2\" min=\"0\" step=\"1\" "
|
||||
"name=\"ap_disabled_restarts\" placeholder=\"0\" value=\"",
|
||||
"\"/></dd>"
|
||||
"<dt><label for=\"ssid\">SSID</label></dt>"
|
||||
"<dd><input id=\"ssid\" type=\"text\" minlength=\"1\" maxlength=\"31\" name=\"ap_ssid\" "
|
||||
"placeholder=\"my access point\" value=\"",
|
||||
"\"></dd>"
|
||||
"<dt><label for=\"ap\">Password</label></dt>"
|
||||
"<dd><input id=\"ap\" type=\"text\" minlength=\"8\" maxlength=\"63\" name=\"ap_password\" "
|
||||
"placeholder=\"password\" value=\"",
|
||||
"\"></dd>"
|
||||
"<dt><label for=\"hidden\">SSID Hidden</label></dt>"
|
||||
"<dd><input id=\"hidden\" type=\"checkbox\" name=\"ap_ssid_hidden\" value=\"1\" ",
|
||||
" /></dd>"
|
||||
"<dt><label for=\"ch\">Channel</label></dt>"
|
||||
"<dd><input id=\"ch\" type=\"number\" size=\"2\" min=\"1\" max=\"14\" step=\"1\" "
|
||||
"name=\"ap_channel\" placeholder=\"6\" value=\"",
|
||||
"\"></dd>"
|
||||
"<dt><label for=\"am\">Authentication Mode</label></dt>"
|
||||
"<dd><select id=\"am\" name=\"ap_authmode\">"
|
||||
"<option value=\"0\"",
|
||||
">Open</option>"
|
||||
"<option value=\"1\"",
|
||||
">WEP</option>"
|
||||
"<option value=\"2\"",
|
||||
">WPA_PSK</option>"
|
||||
"<option value=\"3\"",
|
||||
">WPA2_PSK</option>"
|
||||
"<option value=\"4\"",
|
||||
">WPA_WPA2_PSK</option></select></dd>"
|
||||
"<dt><label for=\"mc\">Max connections</label></dt>"
|
||||
"<dd><input id=\"mc\" type=\"number\" size=\"2\" min=\"1\" max=\"8\" step=\"1\" "
|
||||
"name=\"ap_max_conn\" placeholder=\"3\" value=\"",
|
||||
"\"></dd>"
|
||||
"<dt><label for=\"bi\">Beacon interval</label></dt>"
|
||||
"<dd><input id=\"bi\" type=\"number\" size=\"6\" min=\"0\" max=\"10000\" step=\"1\" "
|
||||
"name=\"ap_beacon_interval\" placeholder=\"100\" value=\"",
|
||||
"\"></dd>"
|
||||
"<dt><label for=\"ip\">IP Address</label></dt>"
|
||||
"<dd><input id=\"ip\" type=\"text\" maxlength=\"15\" size=\"15\" "
|
||||
"pattern=\"(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)_*(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)_*){3}\" "
|
||||
"name=\"ap_ip_addr\" placeholder=\"192.168.4.1\" value=\"",
|
||||
"\"></dd>"
|
||||
"<dt><label for=\"nm\">Netmask</label></dt>"
|
||||
"<dd><input id=\"nm\" type=\"text\" maxlength=\"15\" size=\"15\" "
|
||||
"pattern=\"(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)_*(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)_*){3}\" "
|
||||
"name=\"ap_netmask\" placeholder=\"255.255.255.0\" value=\"",
|
||||
"\"></dd>"
|
||||
"<dt><label for=\"dhcp\">DHCP Server Max Leases</label></dt>"
|
||||
"<dd><input id=\"dhcp\" type=\"number\" size=\"2\" min=\"0\" max=\"16\" step=\"1\" "
|
||||
"name=\"ap_dhcp_leases\" placeholder=\"4\" value=\"",
|
||||
"\"></dd>"
|
||||
"<dt><label for=\"dns_en\">DNS enabled</label></dt>"
|
||||
"<dd><input id=\"dns_en\" type=\"checkbox\" name=\"ap_dns\" value=\"1\" ",
|
||||
" /></dd>"
|
||||
"</dl>"
|
||||
"<center><input type=\"reset\"> <input type=\"submit\" value=\"Save\"></center>"
|
||||
"</fieldset>"
|
||||
"<input type=\"hidden\" name=\"done\">"
|
||||
"</form>"
|
||||
"</body></html>"
|
||||
52
extras/wificfg/content/wificfg/index.html
Normal file
52
extras/wificfg/content/wificfg/index.html
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
"<!DOCTYPE html><html lang=\"en\">"
|
||||
"<head>"
|
||||
"<link rel=\"stylesheet\" type=\"text/css\" href=\"/style.css\">"
|
||||
"<script src=\"/script.js\"></script>"
|
||||
"<title>",
|
||||
"</title>"
|
||||
"<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">"
|
||||
"</head>"
|
||||
"<body>"
|
||||
"<ul class=\"topnav\" id=\"myTopnav\">"
|
||||
"<li><a href=\"/\">Home</a></li>"
|
||||
"<li class=\"active\"><a href=\"/wificfg/\">WiFi Config</a></li>"
|
||||
"<li><a href=\"/wificfg/sta.html\">WiFi Station</a></li>"
|
||||
"<li><a href=\"/wificfg/ap.html\">WiFi Access Point</a></li>"
|
||||
"<li class=\"icon\">"
|
||||
"<a href=\"javascript:void(0);\" onclick=\"myFunction()\">☰</a>"
|
||||
"</li>"
|
||||
"</ul>"
|
||||
"<h1>WiFi Status</h1>"
|
||||
"<dl class=\"dlh\">",
|
||||
"</dl>"
|
||||
"<br>"
|
||||
"<form action=\"/wificfg/\" method=\"post\" onsubmit=\"return confirm('Are you sure you want to lock the configuration interface, and have you noted the password?');\">"
|
||||
"<fieldset>"
|
||||
"<legend>Lock the configuration interface</legend>"
|
||||
"<p>These WiFi configuration pages can be disabled for security on a shared network. If a password is supplied then they can be unlocked. Warning: if no password is supplied then it will not be possible to unlock these pages via this interface.</p>"
|
||||
"<dl class=\"dlh\">"
|
||||
"<dt><label for=\"pw\">Password</label></dt>"
|
||||
"<dd><input id=\"pw\" type=\"text\" maxlength=\"32\" name=\"cfg_password\" "
|
||||
"placeholder=\"unlock-password\" value=\"",
|
||||
"\"></dd>"
|
||||
"</dl>"
|
||||
"<input type=\"hidden\" name=\"cfg_enable\" value=\"0\">"
|
||||
"<center><input type=\"submit\" value=\"Lock\"></center>"
|
||||
"</fieldset>"
|
||||
"</form>"
|
||||
"<form action=\"/wificfg/restart.html\" method=\"post\" onsubmit=\"return confirm('Are you sure you want to restart the device?');\">"
|
||||
"<fieldset>"
|
||||
"<legend>Restart device</legend>"
|
||||
"<p>A restart is necessary for some changes to take effect.</p>"
|
||||
"<center><button>Restart</button></center>"
|
||||
"</fieldset></form>"
|
||||
"<form action=\"/wificfg/erase.html\" method=\"post\" onsubmit=\"return confirm('Are you sure you want to erase the configuration?');\">"
|
||||
"<fieldset>"
|
||||
"<legend>Erase configuration</legend>"
|
||||
"<p>Erases the device configuration stored in the flash memory and restarts the device. "
|
||||
"This might be useful to clear stored passwords and private configuration information."
|
||||
"</p>"
|
||||
"<center><button>Erase Configuration</button></center>"
|
||||
"</fieldset>"
|
||||
"</form>",
|
||||
"</body></html>"
|
||||
68
extras/wificfg/content/wificfg/sta.html
Normal file
68
extras/wificfg/content/wificfg/sta.html
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
"<!DOCTYPE html><html lang=\"en\">"
|
||||
"<head>"
|
||||
"<link rel=\"stylesheet\" type=\"text/css\" href=\"/style.css\">"
|
||||
"<script src=\"/script.js\"></script>"
|
||||
"<title>",
|
||||
"</title>"
|
||||
"<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">"
|
||||
"</head>"
|
||||
"<body>"
|
||||
"<ul class=\"topnav\" id=\"myTopnav\">"
|
||||
"<li><a href=\"/\">Home</a></li>"
|
||||
"<li><a href=\"/wificfg/\">WiFi Config</a></li>"
|
||||
"<li class=\"active\"><a href=\"/wificfg/sta.html\">WiFi Station</a></li>"
|
||||
"<li><a href=\"/wificfg/ap.html\">WiFi Access Point</a></li>"
|
||||
"<li class=\"icon\">"
|
||||
"<a href=\"javascript:void(0);\" onclick=\"myFunction()\">☰</a>"
|
||||
"</li>"
|
||||
"</ul>"
|
||||
"<form action=\"/wificfg/sta.html\" method=\"post\">"
|
||||
"<fieldset>"
|
||||
"<legend>WiFi Station configuration</legend>"
|
||||
"<dl class=\"dlh\">"
|
||||
"<dt><label for=\"enable\">Enable Station mode</label></dt>"
|
||||
"<dd><input id=\"enable\" type=\"checkbox\" name=\"sta_enable\" value=\"1\" ",
|
||||
" /></dd>"
|
||||
"<dt><label for=\"disabled_restarts\">Disabled restarts</label></dt>"
|
||||
"<dd><input id=\"disabled_restarts\" type=\"number\" size=\"2\" min=\"0\" step=\"1\" "
|
||||
"name=\"sta_disabled_restarts\" placeholder=\"0\" value=\"",
|
||||
"\" /></dd>"
|
||||
"<dt><label for=\"ssid\">SSID</label></dt>"
|
||||
"<dd><input id=\"ssid\" minlength=\"1\" maxlength=\"31\" type=\"text\" name=\"sta_ssid\" "
|
||||
"placeholder=\"my access point\" value=\"",
|
||||
"\"></dd>"
|
||||
"<dt><label for=\"pw\">Password</label></dt>"
|
||||
"<dd><input id=\"pw\" type=\"text\" minlength=\"8\" maxlength=\"63\" name=\"sta_password\" "
|
||||
"placeholder=\"password\" value=\"",
|
||||
"\"></dd>"
|
||||
"<dt><label for=\"hostname\">Hostname</label></dt>"
|
||||
"<dd><input id=\"hostname\" type=\"text\" maxlength=\"63\" name=\"hostname\" "
|
||||
"placeholder=\"device-hostname\" value=\"",
|
||||
"\"></dd>"
|
||||
"<dt><label for=\"dhcp\">Enable DHCP</label></dt>"
|
||||
"<dd><input id=\"dhcp\" type=\"radio\" name=\"sta_dhcp\" value=\"1\" ",
|
||||
" /></dd>"
|
||||
"<dt><label for=\"static\">Disable DHCP (static address below)</label></dt>"
|
||||
"<dd><input id=\"static\" type=\"radio\" name=\"sta_dhcp\" value=\"0\" ",
|
||||
" /></dd>"
|
||||
"<dt><label for=\"ip\">Static IP Address</label></dt>"
|
||||
"<dd><input id=\"ip\" type=\"text\" maxlength=\"15\" size=\"15\" "
|
||||
"pattern=\"(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)_*(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)_*){3}\" "
|
||||
"name=\"sta_ip_addr\" placeholder=\"192.168.1.50\" value=\"",
|
||||
"\"></dd>"
|
||||
"<dt><label for=\"nm\">Static Netmask</label></dt>"
|
||||
"<dd><input id=\"nm\" type=\"text\" maxlength=\"15\" size=\"15\" "
|
||||
"pattern=\"(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)_*(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)_*){3}\" "
|
||||
"name=\"sta_netmask\" placeholder=\"255.255.255.0\" value=\"",
|
||||
"\"></dd>"
|
||||
"<dt><label for=\"gw\">Static Gateway</label></dt>"
|
||||
"<dd><input id=\"gw\" type=\"text\" maxlength=\"15\" size=\"15\" "
|
||||
"pattern=\"(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)_*(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)_*){3}\" "
|
||||
"name=\"sta_gateway\" placeholder=\"192.168.1.1\" value=\"",
|
||||
"\"></dd>"
|
||||
"</dl>"
|
||||
"<center><input type=\"reset\"> <input type=\"submit\" value=\"Save\"></center>"
|
||||
"</fieldset>"
|
||||
"<input type=\"hidden\" name=\"done\">"
|
||||
"</form>"
|
||||
"</body></html>"
|
||||
2022
extras/wificfg/wificfg.c
Normal file
2022
extras/wificfg/wificfg.c
Normal file
File diff suppressed because it is too large
Load diff
137
extras/wificfg/wificfg.h
Normal file
137
extras/wificfg/wificfg.h
Normal file
|
|
@ -0,0 +1,137 @@
|
|||
/*
|
||||
* WiFi configuration via a simple web server.
|
||||
*
|
||||
* Copyright (C) 2016 OurAirQuality.org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0, January 2004 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE CONTRIBUTORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS WITH THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __WIFICFG_H__
|
||||
#define __WIFICFG_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Printf format used to initialize a default AP ssid. It is passed the last
|
||||
* three bytes of the mac address. This may be NULL to not default the ssid,
|
||||
* but the AP network will not run without a ssid.
|
||||
*/
|
||||
extern char *wificfg_default_ssid;
|
||||
|
||||
/*
|
||||
* A default password for the AP interface. This may be NULL to not default the
|
||||
* password, but the AP network will not run without a password. The minimum
|
||||
* length is 8 characters.
|
||||
*/
|
||||
extern char *wificfg_default_password;
|
||||
|
||||
/*
|
||||
* A default hostname printf format string. This may be NULL to not default the
|
||||
* hostname.
|
||||
*/
|
||||
extern char *wificfg_default_hostname;
|
||||
|
||||
/*
|
||||
* The web server parses the http method string in these enums. The ANY method
|
||||
* is only use for dispatch. The method enum is passed to the handler functions.
|
||||
*/
|
||||
typedef enum {
|
||||
HTTP_METHOD_GET,
|
||||
HTTP_METHOD_POST,
|
||||
HTTP_METHOD_HEAD,
|
||||
HTTP_METHOD_OTHER,
|
||||
HTTP_METHOD_ANY,
|
||||
} wificfg_method;
|
||||
|
||||
/*
|
||||
* The web server parses these content-type header values. This is passed to the
|
||||
* dispatch function.
|
||||
*/
|
||||
typedef enum {
|
||||
HTTP_CONTENT_TYPE_WWW_FORM_URLENCODED,
|
||||
HTTP_CONTENT_TYPE_OTHER
|
||||
} wificfg_content_type;
|
||||
|
||||
/*
|
||||
* The function signature for the http server request handler functions.
|
||||
*
|
||||
* The buffer, with its length, is usable by the handler.
|
||||
*/
|
||||
typedef int (* wificfg_handler)(int s, wificfg_method method,
|
||||
uint32_t content_length,
|
||||
wificfg_content_type content_type,
|
||||
char *buf, size_t len);
|
||||
|
||||
typedef struct {
|
||||
const char *path;
|
||||
wificfg_method method;
|
||||
wificfg_handler handler;
|
||||
bool secure;
|
||||
} wificfg_dispatch;
|
||||
|
||||
|
||||
/*
|
||||
* Start the Wifi Configuration http server task. The IP port number
|
||||
* and a path dispatch list are needed. The dispatch list can not be
|
||||
* stack allocated as it is passed to another task.
|
||||
*/
|
||||
void wificfg_init(uint32_t port, const wificfg_dispatch *dispatch);
|
||||
|
||||
/*
|
||||
* Support for reading a form name or value from the socket. The name or value
|
||||
* is truncated to the buffer length. The number of characters read is limited
|
||||
* to the remainder which is updated. The 'valp' flag is set if a value follows.
|
||||
*/
|
||||
int wificfg_form_name_value(int s, bool *valp, size_t *rem, char *buf, size_t len);
|
||||
|
||||
/* Support for form url-encoding decoder. */
|
||||
void wificfg_form_url_decode(char *string);
|
||||
|
||||
/* Support for html-escaping of form values. */
|
||||
void wificfg_html_escape(char *string, char *buf, size_t len);
|
||||
|
||||
/* Support for writing a string in a response. */
|
||||
int wificfg_write_string(int s, const char *str);
|
||||
|
||||
/* Support for writing a string in a response, with chunk transfer encoding.
|
||||
* An optional buffer may be supplied to use to construct a chunk with the
|
||||
* header and trailer, reducing the number of write() calls, and the str may be
|
||||
* at the start of this buffer.
|
||||
*/
|
||||
int wificfg_write_string_chunk(int s, const char *str, char *buf, size_t len);
|
||||
|
||||
/* Write a chunk transfer encoding end marker. */
|
||||
int wificfg_write_chunk_end(int s);
|
||||
|
||||
/* Write a chunk offset 4 bytes into the buffer. */
|
||||
int wificfg_write_buffer_chunk(int s, char *buf);
|
||||
|
||||
/* Write a html title meta data, using the hostname or AP SSI. */
|
||||
int wificfg_write_html_title(int s, char *buf, size_t len, const char *str);
|
||||
|
||||
/* Callback to notify the wificfg logic that a station connection has been
|
||||
* successfully established. It might use this to disable the AP interface after
|
||||
* a restart.
|
||||
*/
|
||||
void wificfg_got_sta_connect(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __WIFICFG_H__
|
||||
|
|
@ -60,7 +60,7 @@ volatile uint32_t dma_isr_counter = 0;
|
|||
|
||||
static volatile bool i2s_dma_processing = false;
|
||||
|
||||
static void dma_isr_handler(void)
|
||||
static void dma_isr_handler(void *arg)
|
||||
{
|
||||
if (i2s_dma_is_eof_interrupt()) {
|
||||
#ifdef WS2812_I2S_DEBUG
|
||||
|
|
@ -145,7 +145,7 @@ void ws2812_i2s_init(uint32_t pixels_number)
|
|||
debug("i2s clock dividers, bclk=%d, clkm=%d\n",
|
||||
clock_div.bclk_div, clock_div.clkm_div);
|
||||
|
||||
i2s_dma_init(dma_isr_handler, clock_div, i2s_pins);
|
||||
i2s_dma_init(dma_isr_handler, NULL, clock_div, i2s_pins);
|
||||
}
|
||||
|
||||
const IRAM_DATA int16_t bitpatterns[16] =
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue