initial commit
This commit is contained in:
+234
@@ -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() );
|
||||
}
|
||||
Reference in New Issue
Block a user