181 lines
4.8 KiB
C
181 lines
4.8 KiB
C
/**
|
|
* Copyright (c) 2022 Raspberry Pi (Trading) Ltd.
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
|
|
#include <string.h>
|
|
|
|
#include "pico/stdlib.h"
|
|
#include "pico/cyw43_arch.h"
|
|
|
|
#include "lwip/pbuf.h"
|
|
#include "lwip/tcp.h"
|
|
|
|
#include "dhcpserver.h"
|
|
|
|
#ifndef USE_LED
|
|
#define USE_LED 1
|
|
#endif
|
|
|
|
#define TCP_PORT 80
|
|
#define DEBUG_printf printf
|
|
|
|
typedef struct TCP_ASERVER_T_ {
|
|
struct tcp_pcb *server_pcb;
|
|
struct tcp_pcb *client_pcb;
|
|
bool complete;
|
|
} TCP_SERVER_T;
|
|
|
|
static err_t tcp_server_close(void *arg) {
|
|
TCP_SERVER_T *state = (TCP_SERVER_T*)arg;
|
|
err_t err = ERR_OK;
|
|
if (state->client_pcb != NULL) {
|
|
tcp_arg(state->client_pcb, NULL);
|
|
tcp_poll(state->client_pcb, NULL, 0);
|
|
tcp_sent(state->client_pcb, NULL);
|
|
tcp_recv(state->client_pcb, NULL);
|
|
tcp_err(state->client_pcb, NULL);
|
|
err = tcp_close(state->client_pcb);
|
|
if (err != ERR_OK) {
|
|
DEBUG_printf("close failed %d, calling abort\n", err);
|
|
tcp_abort(state->client_pcb);
|
|
err = ERR_ABRT;
|
|
}
|
|
state->client_pcb = NULL;
|
|
}
|
|
if (state->server_pcb) {
|
|
tcp_arg(state->server_pcb, NULL);
|
|
tcp_close(state->server_pcb);
|
|
state->server_pcb = NULL;
|
|
}
|
|
return err;
|
|
}
|
|
|
|
static err_t tcp_ap_result(void *arg, int status) {
|
|
TCP_SERVER_T *state = (TCP_SERVER_T*)arg;
|
|
if (status == 0) {
|
|
DEBUG_printf("test success\n");
|
|
} else {
|
|
DEBUG_printf("test failed %d\n", status);
|
|
}
|
|
state->complete = true;
|
|
return tcp_server_close(arg);
|
|
}
|
|
|
|
static err_t tcp_server_accept(void *arg, struct tcp_pcb *client_pcb, err_t err) {
|
|
// TCP_SERVER_T *state = (TCP_SERVER_T*)arg;
|
|
if (err != ERR_OK || client_pcb == NULL) {
|
|
DEBUG_printf("Failure in accept\n");
|
|
tcp_ap_result(arg, err);
|
|
return ERR_VAL;
|
|
}
|
|
DEBUG_printf("Client connected\n");
|
|
|
|
/*state->client_pcb = client_pcb;
|
|
tcp_arg(client_pcb, state);
|
|
tcp_sent(client_pcb, tcp_server_sent);
|
|
tcp_recv(client_pcb, tcp_server_recv);
|
|
tcp_poll(client_pcb, tcp_server_poll, POLL_TIME_S * 2);
|
|
tcp_err(client_pcb, tcp_server_err);
|
|
|
|
return tcp_server_send_data(arg, state->client_pcb);*/
|
|
return ERR_OK;
|
|
}
|
|
|
|
static bool tcp_server_open(void *arg) {
|
|
TCP_SERVER_T *state = (TCP_SERVER_T*)arg;
|
|
DEBUG_printf("Starting server on port %u\n", TCP_PORT);
|
|
|
|
struct tcp_pcb *pcb = tcp_new_ip_type(IPADDR_TYPE_ANY);
|
|
if (!pcb) {
|
|
DEBUG_printf("failed to create pcb\n");
|
|
return false;
|
|
}
|
|
|
|
err_t err = tcp_bind(pcb, NULL, TCP_PORT);
|
|
if (err) {
|
|
DEBUG_printf("failed to bind to port %d\n");
|
|
return false;
|
|
}
|
|
|
|
state->server_pcb = tcp_listen_with_backlog(pcb, 1);
|
|
if (!state->server_pcb) {
|
|
DEBUG_printf("failed to listen\n");
|
|
if (pcb) {
|
|
tcp_close(pcb);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
tcp_arg(state->server_pcb, state);
|
|
tcp_accept(state->server_pcb, tcp_server_accept);
|
|
|
|
return true;
|
|
}
|
|
|
|
int main() {
|
|
stdio_init_all();
|
|
|
|
TCP_SERVER_T *state = calloc(1, sizeof(TCP_SERVER_T));
|
|
if (!state) {
|
|
DEBUG_printf("failed to allocate state\n");
|
|
return 1;
|
|
}
|
|
|
|
if (cyw43_arch_init()) {
|
|
printf("failed to initialise\n");
|
|
return 1;
|
|
}
|
|
const char *ap_name = "picow_test";
|
|
#if 1
|
|
const char *password = "password";
|
|
#else
|
|
const char *password = NULL;
|
|
#endif
|
|
|
|
cyw43_arch_enable_ap_mode(ap_name, password, CYW43_AUTH_WPA2_AES_PSK);
|
|
|
|
ip4_addr_t gw, mask;
|
|
IP4_ADDR(&gw, 192, 168, 4, 1);
|
|
IP4_ADDR(&mask, 255, 255, 255, 0);
|
|
|
|
// Start the dhcp server
|
|
dhcp_server_t dhcp_server;
|
|
dhcp_server_init(&dhcp_server, &gw, &mask);
|
|
|
|
if (!tcp_server_open(state)) {
|
|
tcp_ap_result(state, -1);
|
|
}
|
|
|
|
while(!state->complete) {
|
|
#if USE_LED
|
|
static absolute_time_t led_time;
|
|
static int led_on = true;
|
|
|
|
// Invert the led
|
|
if (absolute_time_diff_us(get_absolute_time(), led_time) < 0) {
|
|
led_on = !led_on;
|
|
cyw43_arch_gpio_put(CYW43_WL_GPIO_LED_PIN, led_on);
|
|
led_time = make_timeout_time_ms(1000);
|
|
}
|
|
#endif
|
|
// the following #ifdef is only here so this same example can be used in multiple modes;
|
|
// you do not need it in your code
|
|
#if PICO_CYW43_ARCH_POLL
|
|
// if you are using pico_cyw43_arch_poll, then you must poll periodically from your
|
|
// main loop (not from a timer) to check for WiFi driver or lwIP work that needs to be done.
|
|
cyw43_arch_poll();
|
|
sleep_ms(1);
|
|
#else
|
|
// if you are not using pico_cyw43_arch_poll, then WiFI driver and lwIP work
|
|
// is done via interrupt in the background. This sleep is just an example of some (blocking)
|
|
// work you might be doing.
|
|
sleep_ms(1000);
|
|
#endif
|
|
}
|
|
dhcp_server_deinit(&dhcp_server);
|
|
cyw43_arch_deinit();
|
|
return 0;
|
|
}
|