diff --git a/README.md b/README.md index b23a416..9395f70 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,7 @@ I add my Pi Pico (RP2040) stuff here. There are complete [apps](/apps) and [libr ## Libraries - [BMP180](/lib/bmp180): Header-only library for the BMP180 atmospheric pressure sensor. +- [USB Network Stack](/lib/usb_network_stack): Library using TinyUSB's implementation of the RNDIS protocol to enable network over USB. ## Apps - [PiccoloSDR](/apps/piccolosdr): A primitive direct-sampling SDR. diff --git a/apps/piccolosdr/CMakeLists.txt b/apps/piccolosdr/CMakeLists.txt index f3a41b1..3de975c 100644 --- a/apps/piccolosdr/CMakeLists.txt +++ b/apps/piccolosdr/CMakeLists.txt @@ -2,28 +2,18 @@ cmake_minimum_required(VERSION 3.12) project(piccolosdr) -add_executable(piccolosdr - usb_descriptors.c - main.c -) +add_executable(piccolosdr main.c) -target_link_libraries(piccolosdr - pico_stdlib - pico_stdio - tinyusb_host - tinyusb_board - tinyusb_net +target_link_libraries(piccolosdr LINK_PUBLIC + usb_network_stack hardware_adc hardware_dma hardware_irq - lwip ) -target_include_directories(piccolosdr PRIVATE .) +pico_add_extra_outputs(piccolosdr) pico_enable_stdio_usb(piccolosdr 1) pico_enable_stdio_uart(piccolosdr 0) -pico_add_extra_outputs(piccolosdr) - set(CMAKE_EXPORT_COMPILE_COMMANDS ON) diff --git a/apps/piccolosdr/main.c b/apps/piccolosdr/main.c index 884efa1..b1f9f52 100644 --- a/apps/piccolosdr/main.c +++ b/apps/piccolosdr/main.c @@ -1,172 +1,11 @@ -// Initial TinyUSB RNDIS written by Peter Lawrence. -// Modifications were made by Luigi Cruz. - #include #include "bsp/board.h" #include "pico/stdlib.h" #include "hardware/adc.h" +#include "lwip/tcp.h" #include "hardware/dma.h" #include "hardware/irq.h" - -#include "tusb.h" -#include "dhserver.h" -#include "dnserver.h" - -#include "lwip/init.h" -#include "lwip/timeouts.h" -#include "lwip/api.h" -#include "lwip/sys.h" -#include "lwip/tcp.h" - -/* lwip context */ -static struct netif netif_data; - -/* shared between tud_network_recv_cb() and service_traffic() */ -static struct pbuf *received_frame; - -/* this is used by this code, ./class/net/net_driver.c, and usb_descriptors.c */ -/* ideally speaking, this should be generated from the hardware's unique ID (if available) */ -/* it is suggested that the first byte is 0x02 to indicate a link-local address */ -const uint8_t tud_network_mac_address[6] = {0x02,0x02,0x84,0x6A,0x96,0x00}; - -/* network parameters of this MCU */ -static const ip_addr_t ipaddr = IPADDR4_INIT_BYTES(192, 168, 7, 1); -static const ip_addr_t netmask = IPADDR4_INIT_BYTES(255, 255, 255, 0); -static const ip_addr_t gateway = IPADDR4_INIT_BYTES(0, 0, 0, 0); - -/* database IP addresses that can be offered to the host; this must be in RAM to store assigned MAC addresses */ -static dhcp_entry_t entries[] = { - /* mac ip address lease time */ - { {0}, IPADDR4_INIT_BYTES(192, 168, 7, 2), 24 * 60 * 60 }, - { {0}, IPADDR4_INIT_BYTES(192, 168, 7, 3), 24 * 60 * 60 }, - { {0}, IPADDR4_INIT_BYTES(192, 168, 7, 4), 24 * 60 * 60 }, -}; - -static const dhcp_config_t dhcp_config = { - .router = IPADDR4_INIT_BYTES(0, 0, 0, 0), /* router address (if any) */ - .port = 67, /* listen port */ - .dns = IPADDR4_INIT_BYTES(192, 168, 7, 1), /* dns server (if any) */ - "usb", /* dns suffix */ - TU_ARRAY_SIZE(entries), /* num entry */ - entries /* entries */ -}; -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()) { - 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(); - } -} - -static err_t output_fn(struct netif *netif, struct pbuf *p, const ip_addr_t *addr) { - return etharp_output(netif, p, addr); -} - -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 = output_fn; - return ERR_OK; -} - -static void init_lwip(void) { - struct netif *netif = &netif_data; - - lwip_init(); - - /* the lwip virtual MAC address must be different from the host's; to ensure this, we toggle the LSbit */ - netif->hwaddr_len = sizeof(tud_network_mac_address); - memcpy(netif->hwaddr, tud_network_mac_address, sizeof(tud_network_mac_address)); - netif->hwaddr[5] ^= 0x01; - - netif = netif_add(netif, &ipaddr, &netmask, &gateway, NULL, netif_init_cb, ip_input); - netif_set_default(netif); -} - -/* handle any DNS requests from dns-server */ -bool dns_query_proc(const char *name, ip_addr_t *addr) -{ - if (0 == strcmp(name, "tiny.usb")) - { - *addr = ipaddr; - return true; - } - return false; -} - -bool tud_network_recv_cb(const uint8_t *src, uint16_t size) { - /* this shouldn't happen, but if we get another packet before - parsing the previous, we must signal our inability to accept it */ - if (received_frame) return false; - - if (size) { - struct pbuf *p = pbuf_alloc(PBUF_RAW, size, PBUF_POOL); - - if (p) { - /* pbuf_alloc() has already initialized struct; all we need to do is copy the data */ - memcpy(p->payload, src, size); - - /* store away the pointer for service_traffic() to later handle */ - received_frame = p; - } - } - - return true; -} - -uint16_t tud_network_xmit_cb(uint8_t *dst, void *ref, uint16_t arg) { - struct pbuf *p = (struct pbuf *)ref; - struct pbuf *q; - uint16_t len = 0; - - (void)arg; /* unused for this example */ - - /* traverse the "pbuf chain"; see ./lwip/src/core/pbuf.c for more info */ - for(q = p; q != NULL; q = q->next) { - memcpy(dst, (char *)q->payload, q->len); - dst += q->len; - len += q->len; - if (q->len == q->tot_len) break; - } - - return len; -} - -static void service_traffic(void) -{ - /* handle any packet received by tud_network_recv_cb() */ - if (received_frame) { - ethernet_input(received_frame, &netif_data); - pbuf_free(received_frame); - received_frame = NULL; - tud_network_recv_renew(); - } - - sys_check_timeouts(); -} - -void tud_network_init_cb(void) { - /* if the network is re-initializing and we have a leftover packet, we must do a cleanup */ - if (received_frame) { - pbuf_free(received_frame); - received_frame = NULL; - } -} +#include "usb_network.h" bool streaming = false; struct tcp_pcb* client; @@ -338,8 +177,6 @@ bool led_timer(struct repeating_timer *t) { } int main(void) { - board_init(); - // Init built-in LED. gpio_init(PICO_DEFAULT_LED_PIN); gpio_set_dir(PICO_DEFAULT_LED_PIN, GPIO_OUT); @@ -348,13 +185,7 @@ int main(void) { init_adc_dma_chain(); // Init network stack. - tusb_init(); - init_lwip(); - - // Startup lwIP stack. - while (!netif_is_up(&netif_data)); - while (dhserv_init(&dhcp_config) != ERR_OK); - while (dnserv_init(&ipaddr, 53, dns_query_proc) != ERR_OK); + network_init(); // Start TCP server. struct tcp_pcb* pcb = tcp_new(); @@ -371,8 +202,7 @@ int main(void) { // Listen to events. while (1) { - tud_task(); - service_traffic(); + network_step(); } return 0; diff --git a/apps/tcp_server/CMakeLists.txt b/apps/tcp_server/CMakeLists.txt index f048e89..260a607 100644 --- a/apps/tcp_server/CMakeLists.txt +++ b/apps/tcp_server/CMakeLists.txt @@ -2,26 +2,16 @@ cmake_minimum_required(VERSION 3.12) project(pico-tcp-server) -add_executable(tcp_server - usb_descriptors.c - main.c -) +add_executable(tcp_server main.c) -target_link_libraries(tcp_server - pico_stdlib - pico_stdio - tinyusb_host - tinyusb_board - tinyusb_net +target_link_libraries(tcp_server LINK_PUBLIC + usb_network_stack hardware_adc - lwip ) -target_include_directories(tcp_server PRIVATE .) +pico_add_extra_outputs(tcp_server) pico_enable_stdio_usb(tcp_server 1) pico_enable_stdio_uart(tcp_server 0) -pico_add_extra_outputs(tcp_server) - -set(CMAKE_EXPORT_COMPILE_COMMANDS ON) +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) \ No newline at end of file diff --git a/apps/tcp_server/lwipopts.h b/apps/tcp_server/lwipopts.h deleted file mode 100644 index 755e214..0000000 --- a/apps/tcp_server/lwipopts.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2001-2003 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Simon Goldschmidt - * - */ -#ifndef __LWIPOPTS_H__ -#define __LWIPOPTS_H__ - -/* Prevent having to link sys_arch.c (we don't test the API layers in unit tests) */ -#define NO_SYS 1 -#define MEM_ALIGNMENT 4 -#define LWIP_RAW 0 -#define LWIP_NETCONN 0 -#define LWIP_SOCKET 0 -#define LWIP_DHCP 0 -#define LWIP_ICMP 1 -#define LWIP_UDP 1 -#define LWIP_TCP 1 -#define ETH_PAD_SIZE 0 -#define LWIP_IP_ACCEPT_UDP_PORT(p) ((p) == PP_NTOHS(67)) -#define LWIP_TCP_KEEPALIVE 1 - -#define TCP_MSS (1500 /*mtu*/ - 20 /*iphdr*/ - 20 /*tcphhr*/) -#define TCP_SND_BUF (2 * TCP_MSS) - -#define ETHARP_SUPPORT_STATIC_ENTRIES 1 - -#define LWIP_HTTPD_CGI 0 -#define LWIP_HTTPD_SSI 0 -#define LWIP_HTTPD_SSI_INCLUDE_TAG 0 - -#define LWIP_SINGLE_NETIF 1 - -#endif /* __LWIPOPTS_H__ */ diff --git a/apps/tcp_server/main.c b/apps/tcp_server/main.c index baa0c52..dbe8cdb 100644 --- a/apps/tcp_server/main.c +++ b/apps/tcp_server/main.c @@ -1,173 +1,10 @@ -// Initial TinyUSB RNDIS written by Peter Lawrence. -// Modifications were made by Luigi Cruz. - #include #include "bsp/board.h" #include "pico/stdlib.h" #include "hardware/adc.h" -#include "hardware/irq.h" -#include "hardware/gpio.h" - -#include "tusb.h" -#include "dhserver.h" -#include "dnserver.h" - -#include "lwip/init.h" -#include "lwip/timeouts.h" -#include "lwip/api.h" -#include "lwip/sys.h" +#include "usb_network.h" #include "lwip/tcp.h" -/* lwip context */ -static struct netif netif_data; - -/* shared between tud_network_recv_cb() and service_traffic() */ -static struct pbuf *received_frame; - -/* this is used by this code, ./class/net/net_driver.c, and usb_descriptors.c */ -/* ideally speaking, this should be generated from the hardware's unique ID (if available) */ -/* it is suggested that the first byte is 0x02 to indicate a link-local address */ -const uint8_t tud_network_mac_address[6] = {0x02,0x02,0x84,0x6A,0x96,0x00}; - -/* network parameters of this MCU */ -static const ip_addr_t ipaddr = IPADDR4_INIT_BYTES(192, 168, 7, 1); -static const ip_addr_t netmask = IPADDR4_INIT_BYTES(255, 255, 255, 0); -static const ip_addr_t gateway = IPADDR4_INIT_BYTES(0, 0, 0, 0); - -/* database IP addresses that can be offered to the host; this must be in RAM to store assigned MAC addresses */ -static dhcp_entry_t entries[] = { - /* mac ip address lease time */ - { {0}, IPADDR4_INIT_BYTES(192, 168, 7, 2), 24 * 60 * 60 }, - { {0}, IPADDR4_INIT_BYTES(192, 168, 7, 3), 24 * 60 * 60 }, - { {0}, IPADDR4_INIT_BYTES(192, 168, 7, 4), 24 * 60 * 60 }, -}; - -static const dhcp_config_t dhcp_config = { - .router = IPADDR4_INIT_BYTES(0, 0, 0, 0), /* router address (if any) */ - .port = 67, /* listen port */ - .dns = IPADDR4_INIT_BYTES(192, 168, 7, 1), /* dns server (if any) */ - "usb", /* dns suffix */ - TU_ARRAY_SIZE(entries), /* num entry */ - entries /* entries */ -}; -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()) { - 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(); - } -} - -static err_t output_fn(struct netif *netif, struct pbuf *p, const ip_addr_t *addr) { - return etharp_output(netif, p, addr); -} - -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 = output_fn; - return ERR_OK; -} - -static void init_lwip(void) { - struct netif *netif = &netif_data; - - lwip_init(); - - /* the lwip virtual MAC address must be different from the host's; to ensure this, we toggle the LSbit */ - netif->hwaddr_len = sizeof(tud_network_mac_address); - memcpy(netif->hwaddr, tud_network_mac_address, sizeof(tud_network_mac_address)); - netif->hwaddr[5] ^= 0x01; - - netif = netif_add(netif, &ipaddr, &netmask, &gateway, NULL, netif_init_cb, ip_input); - netif_set_default(netif); -} - -/* handle any DNS requests from dns-server */ -bool dns_query_proc(const char *name, ip_addr_t *addr) -{ - if (0 == strcmp(name, "tiny.usb")) - { - *addr = ipaddr; - return true; - } - return false; -} - -bool tud_network_recv_cb(const uint8_t *src, uint16_t size) { - /* this shouldn't happen, but if we get another packet before - parsing the previous, we must signal our inability to accept it */ - if (received_frame) return false; - - if (size) { - struct pbuf *p = pbuf_alloc(PBUF_RAW, size, PBUF_POOL); - - if (p) { - /* pbuf_alloc() has already initialized struct; all we need to do is copy the data */ - memcpy(p->payload, src, size); - - /* store away the pointer for service_traffic() to later handle */ - received_frame = p; - } - } - - return true; -} - -uint16_t tud_network_xmit_cb(uint8_t *dst, void *ref, uint16_t arg) { - struct pbuf *p = (struct pbuf *)ref; - struct pbuf *q; - uint16_t len = 0; - - (void)arg; /* unused for this example */ - - /* traverse the "pbuf chain"; see ./lwip/src/core/pbuf.c for more info */ - for(q = p; q != NULL; q = q->next) { - memcpy(dst, (char *)q->payload, q->len); - dst += q->len; - len += q->len; - if (q->len == q->tot_len) break; - } - - return len; -} - -static void service_traffic(void) -{ - /* handle any packet received by tud_network_recv_cb() */ - if (received_frame) { - ethernet_input(received_frame, &netif_data); - pbuf_free(received_frame); - received_frame = NULL; - tud_network_recv_renew(); - } - - sys_check_timeouts(); -} - -void tud_network_init_cb(void) { - /* if the network is re-initializing and we have a leftover packet, we must do a cleanup */ - if (received_frame) { - pbuf_free(received_frame); - received_frame = NULL; - } -} - struct tcp_pcb* client; struct repeating_timer timer; @@ -235,16 +72,8 @@ static err_t srv_accept(void * arg, struct tcp_pcb * pcb, err_t err) { } int main(void) { - // Init network stack. - board_init(); - tusb_init(); - init_lwip(); - adc_init(); - - // Startup lwIP stack. - while (!netif_is_up(&netif_data)); - while (dhserv_init(&dhcp_config) != ERR_OK); - while (dnserv_init(&ipaddr, 53, dns_query_proc) != ERR_OK); + // Init network RNDIS stack. + network_init(); // Start TCP server. struct tcp_pcb* pcb = tcp_new(); @@ -257,13 +86,13 @@ int main(void) { tcp_accept(listen, srv_accept); // Start ADC. + adc_init(); adc_set_temp_sensor_enabled(true); adc_select_input(4); // Listen to events. while (1) { - tud_task(); - service_traffic(); + network_step(); } return 0; diff --git a/apps/tcp_server/tusb_config.h b/apps/tcp_server/tusb_config.h deleted file mode 100644 index 262d4eb..0000000 --- a/apps/tcp_server/tusb_config.h +++ /dev/null @@ -1,109 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * 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 - * AUTHORS 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 IN - * THE SOFTWARE. - * - */ - -#ifndef _TUSB_CONFIG_H_ -#define _TUSB_CONFIG_H_ - -#ifdef __cplusplus - extern "C" { -#endif - -//-------------------------------------------------------------------- -// COMMON CONFIGURATION -//-------------------------------------------------------------------- - -// defined by board.mk -#ifndef CFG_TUSB_MCU - #error CFG_TUSB_MCU must be defined -#endif - -// RHPort number used for device can be defined by board.mk, default to port 0 -#ifndef BOARD_DEVICE_RHPORT_NUM - #define BOARD_DEVICE_RHPORT_NUM 0 -#endif - -// RHPort max operational speed can defined by board.mk -// Default to Highspeed for MCU with internal HighSpeed PHY (can be port specific), otherwise FullSpeed -#ifndef BOARD_DEVICE_RHPORT_SPEED - #if (CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX || \ - CFG_TUSB_MCU == OPT_MCU_NUC505 || CFG_TUSB_MCU == OPT_MCU_CXD56) - #define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_HIGH_SPEED - #else - #define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_FULL_SPEED - #endif -#endif - -// Device mode with rhport and speed defined by board.mk -#if BOARD_DEVICE_RHPORT_NUM == 0 - #define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE | BOARD_DEVICE_RHPORT_SPEED) -#elif BOARD_DEVICE_RHPORT_NUM == 1 - #define CFG_TUSB_RHPORT1_MODE (OPT_MODE_DEVICE | BOARD_DEVICE_RHPORT_SPEED) -#else - #error "Incorrect RHPort configuration" -#endif - -#ifndef CFG_TUSB_OS -#define CFG_TUSB_OS OPT_OS_NONE -#endif - -// CFG_TUSB_DEBUG is defined by compiler in DEBUG build -// #define CFG_TUSB_DEBUG 0 - -/* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment. - * Tinyusb use follows macros to declare transferring memory so that they can be put - * into those specific section. - * e.g - * - CFG_TUSB_MEM SECTION : __attribute__ (( section(".usb_ram") )) - * - CFG_TUSB_MEM_ALIGN : __attribute__ ((aligned(4))) - */ -#ifndef CFG_TUSB_MEM_SECTION -#define CFG_TUSB_MEM_SECTION -#endif - -#ifndef CFG_TUSB_MEM_ALIGN -#define CFG_TUSB_MEM_ALIGN __attribute__ ((aligned(4))) -#endif - -//-------------------------------------------------------------------- -// DEVICE CONFIGURATION -//-------------------------------------------------------------------- - -#ifndef CFG_TUD_ENDPOINT0_SIZE -#define CFG_TUD_ENDPOINT0_SIZE 64 -#endif - -//------------- CLASS -------------// -#define CFG_TUD_CDC 0 -#define CFG_TUD_MSC 0 -#define CFG_TUD_HID 0 -#define CFG_TUD_MIDI 0 -#define CFG_TUD_VENDOR 0 -#define CFG_TUD_NET 1 - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_CONFIG_H_ */ diff --git a/apps/tcp_server/usb_descriptors.c b/apps/tcp_server/usb_descriptors.c deleted file mode 100644 index f1c0b47..0000000 --- a/apps/tcp_server/usb_descriptors.c +++ /dev/null @@ -1,225 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * 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 - * AUTHORS 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 IN - * THE SOFTWARE. - * - */ - -#include "tusb.h" - -/* A combination of interfaces must have a unique product id, since PC will save device driver after the first plug. - * Same VID/PID with different interface e.g MSC (first), then CDC (later) will possibly cause system error on PC. - * - * Auto ProductID layout's Bitmap: - * [MSB] NET | VENDOR | MIDI | HID | MSC | CDC [LSB] - */ -#define _PID_MAP(itf, n) ( (CFG_TUD_##itf) << (n) ) -#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ - _PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) | _PID_MAP(NET, 5) ) - -// String Descriptor Index -enum -{ - STRID_LANGID = 0, - STRID_MANUFACTURER, - STRID_PRODUCT, - STRID_SERIAL, - STRID_INTERFACE, - STRID_MAC -}; - -enum -{ - ITF_NUM_CDC = 0, - ITF_NUM_CDC_DATA, - ITF_NUM_TOTAL -}; - -enum -{ - CONFIG_ID_RNDIS = 0, - CONFIG_ID_ECM = 1, - CONFIG_ID_COUNT -}; - -//--------------------------------------------------------------------+ -// Device Descriptors -//--------------------------------------------------------------------+ -tusb_desc_device_t const desc_device = -{ - .bLength = sizeof(tusb_desc_device_t), - .bDescriptorType = TUSB_DESC_DEVICE, - .bcdUSB = 0x0200, - - // Use Interface Association Descriptor (IAD) device class - .bDeviceClass = TUSB_CLASS_MISC, - .bDeviceSubClass = MISC_SUBCLASS_COMMON, - .bDeviceProtocol = MISC_PROTOCOL_IAD, - - .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, - - .idVendor = 0xCafe, - .idProduct = USB_PID, - .bcdDevice = 0x0101, - - .iManufacturer = STRID_MANUFACTURER, - .iProduct = STRID_PRODUCT, - .iSerialNumber = STRID_SERIAL, - - .bNumConfigurations = CONFIG_ID_COUNT // multiple configurations -}; - -// Invoked when received GET DEVICE DESCRIPTOR -// Application return pointer to descriptor -uint8_t const * tud_descriptor_device_cb(void) -{ - return (uint8_t const *) &desc_device; -} - -//--------------------------------------------------------------------+ -// Configuration Descriptor -//--------------------------------------------------------------------+ -#define MAIN_CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_RNDIS_DESC_LEN) -#define ALT_CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_ECM_DESC_LEN) - -#if CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || CFG_TUSB_MCU == OPT_MCU_LPC177X_8X || CFG_TUSB_MCU == OPT_MCU_LPC40XX - // LPC 17xx and 40xx endpoint type (bulk/interrupt/iso) are fixed by its number - // 0 control, 1 In, 2 Bulk, 3 Iso, 4 In etc ... - #define EPNUM_NET_NOTIF 0x81 - #define EPNUM_NET_OUT 0x02 - #define EPNUM_NET_IN 0x82 - -#elif CFG_TUSB_MCU == OPT_MCU_SAMG - // SAMG doesn't support a same endpoint number with different direction IN and OUT - // e.g EP1 OUT & EP1 IN cannot exist together - #define EPNUM_NET_NOTIF 0x81 - #define EPNUM_NET_OUT 0x02 - #define EPNUM_NET_IN 0x83 - -#else - #define EPNUM_NET_NOTIF 0x81 - #define EPNUM_NET_OUT 0x02 - #define EPNUM_NET_IN 0x82 -#endif - -static uint8_t const rndis_configuration[] = -{ - // Config number (index+1), interface count, string index, total length, attribute, power in mA - TUD_CONFIG_DESCRIPTOR(CONFIG_ID_RNDIS+1, ITF_NUM_TOTAL, 0, MAIN_CONFIG_TOTAL_LEN, 0, 100), - - // Interface number, string index, EP notification address and size, EP data address (out, in) and size. - TUD_RNDIS_DESCRIPTOR(ITF_NUM_CDC, STRID_INTERFACE, EPNUM_NET_NOTIF, 8, EPNUM_NET_OUT, EPNUM_NET_IN, CFG_TUD_NET_ENDPOINT_SIZE), -}; - -static uint8_t const ecm_configuration[] = -{ - // Config number (index+1), interface count, string index, total length, attribute, power in mA - TUD_CONFIG_DESCRIPTOR(CONFIG_ID_ECM+1, ITF_NUM_TOTAL, 0, ALT_CONFIG_TOTAL_LEN, 0, 100), - - // Interface number, description string index, MAC address string index, EP notification address and size, EP data address (out, in), and size, max segment size. - TUD_CDC_ECM_DESCRIPTOR(ITF_NUM_CDC, STRID_INTERFACE, STRID_MAC, EPNUM_NET_NOTIF, 64, EPNUM_NET_OUT, EPNUM_NET_IN, CFG_TUD_NET_ENDPOINT_SIZE, CFG_TUD_NET_MTU), -}; - -// Configuration array: RNDIS and CDC-ECM -// - Windows only works with RNDIS -// - MacOS only works with CDC-ECM -// - Linux will work on both -// Note index is Num-1x -static uint8_t const * const configuration_arr[2] = -{ - [CONFIG_ID_RNDIS] = rndis_configuration, - [CONFIG_ID_ECM ] = ecm_configuration -}; - -// Invoked when received GET CONFIGURATION DESCRIPTOR -// Application return pointer to descriptor -// Descriptor contents must exist long enough for transfer to complete -uint8_t const * tud_descriptor_configuration_cb(uint8_t index) -{ - return (index < CONFIG_ID_COUNT) ? configuration_arr[index] : NULL; -} - -//--------------------------------------------------------------------+ -// String Descriptors -//--------------------------------------------------------------------+ - -// array of pointer to string descriptors -static char const* string_desc_arr [] = -{ - [STRID_LANGID] = (const char[]) { 0x09, 0x04 }, // supported language is English (0x0409) - [STRID_MANUFACTURER] = "TinyUSB", // Manufacturer - [STRID_PRODUCT] = "TinyUSB Device", // Product - [STRID_SERIAL] = "123456", // Serial - [STRID_INTERFACE] = "TinyUSB Network Interface" // Interface Description - - // STRID_MAC index is handled separately -}; - -static uint16_t _desc_str[32]; - -// Invoked when received GET STRING DESCRIPTOR request -// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete -uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid) -{ - (void) langid; - - unsigned int chr_count = 0; - - if (STRID_LANGID == index) - { - memcpy(&_desc_str[1], string_desc_arr[STRID_LANGID], 2); - chr_count = 1; - } - else if (STRID_MAC == index) - { - // Convert MAC address into UTF-16 - - for (unsigned i=0; i> 4) & 0xf]; - _desc_str[1+chr_count++] = "0123456789ABCDEF"[(tud_network_mac_address[i] >> 0) & 0xf]; - } - } - else - { - // Note: the 0xEE index string is a Microsoft OS 1.0 Descriptors. - // https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/microsoft-defined-usb-descriptors - - if ( !(index < sizeof(string_desc_arr)/sizeof(string_desc_arr[0])) ) return NULL; - - const char* str = string_desc_arr[index]; - - // Cap at max char - chr_count = strlen(str); - if ( chr_count > (TU_ARRAY_SIZE(_desc_str) - 1)) chr_count = TU_ARRAY_SIZE(_desc_str) - 1; - - // Convert ASCII string into UTF-16 - for (unsigned int i=0; imtu = 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 = output_fn; + return ERR_OK; +} + +static void init_lwip(void) { + struct netif *netif = &netif_data; + + lwip_init(); + + /* the lwip virtual MAC address must be different from the host's; to ensure this, we toggle the LSbit */ + netif->hwaddr_len = sizeof(tud_network_mac_address); + memcpy(netif->hwaddr, tud_network_mac_address, sizeof(tud_network_mac_address)); + netif->hwaddr[5] ^= 0x01; + + netif = netif_add(netif, &ipaddr, &netmask, &gateway, NULL, netif_init_cb, ip_input); + netif_set_default(netif); +} + +/* handle any DNS requests from dns-server */ +bool dns_query_proc(const char *name, ip_addr_t *addr) +{ + if (0 == strcmp(name, "tiny.usb")) + { + *addr = ipaddr; + return true; + } + return false; +} + +bool tud_network_recv_cb(const uint8_t *src, uint16_t size) { + /* this shouldn't happen, but if we get another packet before + parsing the previous, we must signal our inability to accept it */ + if (received_frame) return false; + + if (size) { + struct pbuf *p = pbuf_alloc(PBUF_RAW, size, PBUF_POOL); + + if (p) { + /* pbuf_alloc() has already initialized struct; all we need to do is copy the data */ + memcpy(p->payload, src, size); + + /* store away the pointer for service_traffic() to later handle */ + received_frame = p; + } + } + + return true; +} + +uint16_t tud_network_xmit_cb(uint8_t *dst, void *ref, uint16_t arg) { + struct pbuf *p = (struct pbuf *)ref; + struct pbuf *q; + uint16_t len = 0; + + (void)arg; /* unused for this example */ + + /* traverse the "pbuf chain"; see ./lwip/src/core/pbuf.c for more info */ + for(q = p; q != NULL; q = q->next) { + memcpy(dst, (char *)q->payload, q->len); + dst += q->len; + len += q->len; + if (q->len == q->tot_len) break; + } + + return len; +} + +static void service_traffic(void) +{ + /* handle any packet received by tud_network_recv_cb() */ + if (received_frame) { + ethernet_input(received_frame, &netif_data); + pbuf_free(received_frame); + received_frame = NULL; + tud_network_recv_renew(); + } + + sys_check_timeouts(); +} + +void tud_network_init_cb(void) { + /* if the network is re-initializing and we have a leftover packet, we must do a cleanup */ + if (received_frame) { + pbuf_free(received_frame); + received_frame = NULL; + } +} + +void network_init() { + // Init network stack. + board_init(); + tusb_init(); + init_lwip(); + + // Startup lwIP stack. + while (!netif_is_up(&netif_data)); + while (dhserv_init(&dhcp_config) != ERR_OK); + while (dnserv_init(&ipaddr, 53, dns_query_proc) != ERR_OK); +} + +void network_step() { + tud_task(); + service_traffic(); +} \ No newline at end of file