initial commit

This commit is contained in:
2025-08-26 19:58:07 -04:00
commit 7367171767
27 changed files with 4618 additions and 0 deletions
+234
View File
@@ -0,0 +1,234 @@
#include "bsp/board_api.h"
#include "tusb.h"
#include "dhserver.h"
#include "dnserver.h"
#include "lwip/apps/httpd.h"
#include "lwip/init.h"
#include "lwip/timeouts.h"
#include "websocket.h"
#include "usb_device.h"
#include "aw410k.h"
#include "usb_server.h"
// ip address of the USB server and dhcp address(es) it will give out
static const ip4_addr_t usb_ip = INIT_IP4(192, 168, 40, 1);
static const ip4_addr_t usb_netmask = INIT_IP4(255, 255, 255, 0);
static const ip4_addr_t usb_gateway = INIT_IP4(0, 0, 0, 0);
static dhcp_entry_t dhcp_clients[] = {
{ {0}, INIT_IP4(192, 168, 40, 2), 4*3600 },
};
static const dhcp_config_t dhcp_config = {
.router = INIT_IP4(0,0,0,0),
.port = 67,
.dns = usb_ip,
"usb",
TU_ARRAY_SIZE(dhcp_clients),
dhcp_clients
};
static struct netif netif_data;
static err_t netif_init_cb(struct netif *netif);
static err_t ip4_output_fn(struct netif *netif, struct pbuf *p, const ip4_addr_t *addr);
static err_t linkoutput_fn(struct netif *netif, struct pbuf *p);
static void usb_server_netif_link_cb(struct netif *netif);
static bool dns_request(const char *name, ip4_addr_t *addr);
// called to initialize the USB network and HTTP server
void usb_server_init(void) {
struct netif *netif = &netif_data;
lwip_init();
// use 02 followed by last 10 digits from board serial as MAC address
uint8_t board_serial[16];
size_t count = board_get_unique_id(board_serial, sizeof(board_serial));
netif->hwaddr_len = 6;
memcpy(netif->hwaddr, &board_serial[count-6], 6);
netif->hwaddr[0]=0x02;
// lwip virtual MAC address msut differ from the host MAC - toggle last bit
netif->hwaddr[5] ^= 0x01;
netif = netif_add(netif, &usb_ip, &usb_netmask, &usb_gateway, NULL, netif_init_cb, ethernet_input);
netif_set_default(netif);
#if LWIP_NETIF_LINK_CALLBACK
netif_set_link_callback(netif, usb_server_netif_link_cb);
netif_set_link_up(netif);
#else
//tud_network_link_state(BOARD_TUD_RHPORT, true);
// unsupported in current version - add when Pico SDK updates TinyUSB version
#endif
while (!netif_is_up(&netif_data));
while (dhserv_init(&dhcp_config) != ERR_OK);
while (dnserv_init(IP_ADDR_ANY, 53, dns_request) != ERR_OK);
httpd_init();
// start the websocket server
ws_server_init();
ws_set_open_handler(ws_open_handler);
ws_set_receive_handler(ws_receive_handler);
}
// callback when data is received on USB network
// return true if the packet buffer was accepted
bool tud_network_recv_cb(const uint8_t *src, uint16_t size) {
struct netif *netif = &netif_data;
if (size) {
struct pbuf *p = pbuf_alloc(PBUF_RAW, size, PBUF_POOL);
if (p == NULL) {
printf("ERROR: Failed to allocate pbuf of size %d\n", size);
return false;
}
/* Copy buf to pbuf */
pbuf_take(p, src, size);
// Surrender ownership of our pbuf unless there was an error
// Only call pbuf_free if not Ok else it will panic with "pbuf_free: p->ref > 0"
// or steal it from whatever took ownership of it with undefined consequences.
// See: https://savannah.nongnu.org/patch/index.php?10121
if (netif->input(p, netif) != ERR_OK) {
printf("ERROR: netif input failed\n");
pbuf_free(p);
}
// Signal tinyusb that the current frame has been processed.
tud_network_recv_renew();
}
return true;
}
// callback when network interface is initialized
// save the network configuration
static err_t netif_init_cb(struct netif *netif) {
LWIP_ASSERT("netif != NULL", (netif != NULL));
netif->mtu = CFG_TUD_NET_MTU;
netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP | NETIF_FLAG_UP;
netif->state = NULL;
netif->name[0] = 'E';
netif->name[1] = 'X';
netif->linkoutput = linkoutput_fn;
netif->output = ip4_output_fn;
return ERR_OK;
}
// callback for sending data over USB network interface
// copy from network stack packet pointer to dst
uint16_t tud_network_xmit_cb(uint8_t *dst, void *ref, uint16_t arg) {
struct pbuf *p = (struct pbuf *) ref;
(void) arg; /* unused for this example */
return pbuf_copy_partial(p, dst, p->tot_len, 0);
}
static err_t ip4_output_fn(struct netif *netif, struct pbuf *p, const ip4_addr_t *addr) {
return etharp_output(netif, p, addr);
}
static err_t linkoutput_fn(struct netif *netif, struct pbuf *p) {
(void) netif;
for (;;) {
// if TinyUSB isn't ready, we must signal back to lwip that there is nothing we can do
if (!tud_ready())
return ERR_USE;
// if the network driver can accept another packet, we make it happen
if (tud_network_can_xmit(p->tot_len)) {
tud_network_xmit(p, 0 /* unused for this example */);
return ERR_OK;
}
// transfer execution to TinyUSB in the hopes that it will finish transmitting the prior packet
tud_task();
}
}
// notify USB host about link state changes
static void usb_server_netif_link_cb(struct netif *netif) {
bool link_up = netif_is_link_up(netif);
//tud_network_link_state(BOARD_TUD_RHPORT, link_up);
// unsupported in current version - add when Pico SDK updates TinyUSB version
}
// handle DNS requests and serve on designed domain
static bool dns_request(const char *name, ip4_addr_t *addr) {
if (0 == strcmp(name, "aw410k.usb")) {
*addr = usb_ip;
return true;
}
return false;
}
// handler called when websocket connection is opened
const void ws_open_handler(struct ws_state * wss) {
(void) wss;
// nothing to do
}
// handler for data received on websocket connection
const void ws_receive_handler(uint8_t *data, uint16_t len) {
if (strncmp(data, "S,", 2) == 0) {
// set color command
parse_colors(&data[2], len-2);
} else if ( strncmp(data, "G,", 2) == 0) {
// get color comand
get_color(&data[2], len-2);
} else if ( strncmp(data, "F,", 2) == 0) {
// save to flash memory
save_rgb_config();
} else if ( strncmp(data, "L,", 2) == 0) {
// load from flash memory
load_rgb_config();
}
}
// Pico specific routines needed by lwip
auto_init_mutex(lwip_mutex);
static int lwip_mutex_count = 0;
sys_prot_t sys_arch_protect(void)
{
uint32_t owner;
if (!mutex_try_enter(&lwip_mutex, &owner))
{
if (owner != get_core_num())
{
// Wait until other core releases mutex
mutex_enter_blocking(&lwip_mutex);
}
}
lwip_mutex_count++;
return 0;
}
void sys_arch_unprotect(sys_prot_t pval)
{
(void)pval;
if (lwip_mutex_count)
{
lwip_mutex_count--;
if (!lwip_mutex_count)
{
mutex_exit(&lwip_mutex);
}
}
}
uint32_t sys_now(void)
{
return to_ms_since_boot( get_absolute_time() );
}