From 14e2b6dc5bce9411c2b0ebcd6018287b9ff1d9bf Mon Sep 17 00:00:00 2001 From: Masayuki Ishikawa Date: Mon, 13 Nov 2017 08:55:41 +0000 Subject: [PATCH] Merged in masayuki2009/nuttx.nuttx/stm32f4discovery_rndis (pull request #533) RNDIS support on STM32F4Discovery * stm32f4discovery: Add stm32_netinit.c to avoid a compilation error * stm32f4discovery: Add rndis initialization in stm32_bringup.c NOTE: MAC address for the host side starts 0xaa. This assignment scheme should be fixed later. * stm32f4discovery: Add rndis configuration NOTE: STM32F4Discovery + DM-STF4BB * drivers/usbdev/rndis.c: Fix some issues in rndis.c Introduce rndis_transmit() and change rndis_rxdispatch() to avoid packet corruption. Introduce max packet size for dual speed which is mainly used for high speed mode. Fix adjusting MTU warning on Linux host. Fix data corruption if a packet size excceds MTU. NOTE: Max packet size is not configured dynamically. This should be fixed in the future version. * stm32f4discovery: Modify #ifdef condition for rndis in stm32_bringup() * drivers/usbdev/rndis.c: Change HPWORK to ETHWORK * drivers/usbdev/rndis.c: Merge the commit 07b98ccbb5 Previous commit b09365784a was based on old rndis.c thus resulted in reverting the commit 07b98ccbb5. This change merges the commit. NOTE: In the commit 07b98ccbb5, max packet size of bulkout was assumed to be 64. In this commit, priv->epbulkout->maxpacket is used instead. Approved-by: Gregory Nutt --- configs/stm32f4discovery/rndis/defconfig | 102 +++++++++++ configs/stm32f4discovery/src/Makefile | 6 + configs/stm32f4discovery/src/stm32_bringup.c | 15 ++ configs/stm32f4discovery/src/stm32_netinit.c | 52 ++++++ drivers/usbdev/rndis.c | 182 ++++++++++++++----- 5 files changed, 314 insertions(+), 43 deletions(-) create mode 100644 configs/stm32f4discovery/rndis/defconfig create mode 100644 configs/stm32f4discovery/src/stm32_netinit.c diff --git a/configs/stm32f4discovery/rndis/defconfig b/configs/stm32f4discovery/rndis/defconfig new file mode 100644 index 0000000000..072f3cf4a5 --- /dev/null +++ b/configs/stm32f4discovery/rndis/defconfig @@ -0,0 +1,102 @@ +CONFIG_ARCH="arm" +CONFIG_ARCH_BOARD="stm32f4discovery" +CONFIG_ARCH_BOARD_STM32F4_DISCOVERY=y +CONFIG_ARCH_BUTTONS=y +CONFIG_ARCH_CHIP_STM32F407VG=y +CONFIG_ARCH_CHIP_STM32=y +# CONFIG_ARCH_FPU is not set +CONFIG_ARCH_STACKDUMP=y +CONFIG_ARMV7M_TOOLCHAIN_CODESOURCERYW=y +CONFIG_BOARDCTL_RESET=y +CONFIG_BOARDCTL_USBDEVCTRL=y +CONFIG_BOARD_LOOPSPERMSEC=16717 +CONFIG_BUILTIN=y +CONFIG_CLOCK_MONOTONIC=y +CONFIG_DEBUG_ASSERTIONS=y +CONFIG_DEBUG_ERROR=y +CONFIG_DEBUG_FEATURES=y +CONFIG_DEBUG_FULLOPT=y +CONFIG_DEBUG_NET_ERROR=y +CONFIG_DEBUG_NET=y +CONFIG_DEBUG_SYMBOLS=y +CONFIG_DEBUG_WARN=y +CONFIG_EXAMPLES_NSH_CXXINITIALIZE=y +CONFIG_EXAMPLES_NSH=y +CONFIG_FAT_LCNAMES=y +CONFIG_FAT_LFN=y +CONFIG_FS_FAT=y +CONFIG_FS_PROCFS=y +CONFIG_HAVE_CXXINITIALIZE=y +CONFIG_HAVE_CXX=y +CONFIG_HOST_WINDOWS=y +CONFIG_INTELHEX_BINARY=y +CONFIG_MAX_TASKS=16 +CONFIG_MAX_WDOGPARMS=2 +# CONFIG_MMCSD_MMCSUPPORT is not set +CONFIG_MMCSD_MULTIBLOCK_DISABLE=y +CONFIG_MMCSD_SDIO=y +# CONFIG_MMCSD_SPI is not set +CONFIG_MMCSD=y +CONFIG_NET_ARP_SEND=y +CONFIG_NET_BROADCAST=y +CONFIG_NETDB_DNSCLIENT=y +CONFIG_NETDB_DNSSERVER_IPv4ADDR=0x0 +CONFIG_NETDEVICES=y +CONFIG_NET_ICMP=y +CONFIG_NET_LOOPBACK=y +CONFIG_NET_SOCKOPTS=y +CONFIG_NET_STATISTICS=y +CONFIG_NET_TCP_WRITE_BUFFERS=y +CONFIG_NET_TCP=y +CONFIG_NET_UDP=y +CONFIG_NETUTILS_DHCPC=y +CONFIG_NETUTILS_TELNETD=y +CONFIG_NETUTILS_WEBCLIENT=y +CONFIG_NET=y +CONFIG_NFILE_DESCRIPTORS=8 +CONFIG_NFILE_STREAMS=8 +CONFIG_NSH_ARCHINIT=y +# CONFIG_NSH_ARGCAT is not set +CONFIG_NSH_BUILTIN_APPS=y +# CONFIG_NSH_CMDOPT_HEXDUMP is not set +# CONFIG_NSH_CMDPARMS is not set +CONFIG_NSH_DHCPC=y +# CONFIG_NSH_DISABLE_DATE is not set +CONFIG_NSH_DRIPADDR=0x0 +CONFIG_NSH_FILEIOSIZE=512 +CONFIG_NSH_LINELEN=128 +CONFIG_NSH_MACADDR=0x00e0deadcafe +CONFIG_NSH_NETINIT_THREAD=y +CONFIG_NSH_NETMASK=0x0 +CONFIG_NSH_NOMAC=y +CONFIG_NSH_READLINE=y +CONFIG_PREALLOC_MQ_MSGS=4 +CONFIG_PREALLOC_TIMERS=4 +CONFIG_PREALLOC_WDOGS=16 +CONFIG_RAM_SIZE=114688 +CONFIG_RAM_START=0x20000000 +CONFIG_RAW_BINARY=y +CONFIG_RNDIS=y +CONFIG_SCHED_HPWORKPRIORITY=192 +CONFIG_SCHED_HPWORK=y +CONFIG_SCHED_WAITPID=y +CONFIG_SDCLONE_DISABLE=y +CONFIG_SENSORS=y +CONFIG_START_DAY=13 +CONFIG_START_MONTH=9 +CONFIG_START_YEAR=2014 +CONFIG_STM32_DMA2=y +CONFIG_STM32_DMACAPABLE=y +CONFIG_STM32F4DISBB=y +CONFIG_STM32_JTAG_SW_ENABLE=y +CONFIG_STM32_OTGFS=y +CONFIG_STM32_PWR=y +# CONFIG_STM32_SDIO_DMA is not set +CONFIG_STM32_SDIO=y +CONFIG_STM32_SPI1=y +CONFIG_STM32_USART6=y +CONFIG_USART6_RXBUFSIZE=64 +CONFIG_USART6_SERIAL_CONSOLE=y +CONFIG_USART6_TXBUFSIZE=64 +CONFIG_USBDEV=y +CONFIG_USER_ENTRYPOINT="nsh_main" diff --git a/configs/stm32f4discovery/src/Makefile b/configs/stm32f4discovery/src/Makefile index e6ef059bfa..af68c1cca5 100644 --- a/configs/stm32f4discovery/src/Makefile +++ b/configs/stm32f4discovery/src/Makefile @@ -168,4 +168,10 @@ ifeq ($(CONFIG_USBMSC),y) CSRCS += stm32_usbmsc.c endif +ifneq ($(CONFIG_STM32_ETHMAC),y) +ifeq ($(CONFIG_NETDEVICES),y) +CSRCS += stm32_netinit.c +endif +endif + include $(TOPDIR)/configs/Board.mk diff --git a/configs/stm32f4discovery/src/stm32_bringup.c b/configs/stm32f4discovery/src/stm32_bringup.c index 22fbf97830..e2df2fd3c5 100644 --- a/configs/stm32f4discovery/src/stm32_bringup.c +++ b/configs/stm32f4discovery/src/stm32_bringup.c @@ -66,6 +66,10 @@ # include #endif +#ifdef CONFIG_RNDIS +# include +#endif + #include "stm32f4discovery.h" /* Conditional logic in stm32f4discovery.h will determine if certain features @@ -315,5 +319,16 @@ int stm32_bringup(void) } #endif +#if defined(CONFIG_RNDIS) && defined(CONFIG_NSH_MACADDR) + uint8_t mac[6]; + mac[0] = 0xaa; /* TODO */ + mac[1] = (CONFIG_NSH_MACADDR >> (8 * 4)) & 0xff; + mac[2] = (CONFIG_NSH_MACADDR >> (8 * 3)) & 0xff; + mac[3] = (CONFIG_NSH_MACADDR >> (8 * 2)) & 0xff; + mac[4] = (CONFIG_NSH_MACADDR >> (8 * 1)) & 0xff; + mac[5] = (CONFIG_NSH_MACADDR >> (8 * 0)) & 0xff; + usbdev_rndis_initialize(mac); +#endif + return ret; } diff --git a/configs/stm32f4discovery/src/stm32_netinit.c b/configs/stm32f4discovery/src/stm32_netinit.c new file mode 100644 index 0000000000..5cc73b4a53 --- /dev/null +++ b/configs/stm32f4discovery/src/stm32_netinit.c @@ -0,0 +1,52 @@ +/************************************************************************************ + * config/stm32f4discovery/src/stm32_netinit.c + * + * Copyright (C) 2017 Masayuki Ishikawa. All rights reserved. + * Author: Masayuki Ishikawa + * + * 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. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "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 + * COPYRIGHT OWNER OR CONTRIBUTORS 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. + * + ************************************************************************************/ + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include + +/************************************************************************************ + * Public Functions + ************************************************************************************/ + +/************************************************************************************ + * Name: up_netinitialize + ************************************************************************************/ + +void up_netinitialize(void) +{ +} diff --git a/drivers/usbdev/rndis.c b/drivers/usbdev/rndis.c index 938be1c2c8..7e85b1b9f5 100644 --- a/drivers/usbdev/rndis.c +++ b/drivers/usbdev/rndis.c @@ -80,6 +80,7 @@ #define RNDIS_PACKET_HDR_SIZE (sizeof(struct rndis_packet_msg)) #define CONFIG_RNDIS_BULKIN_REQLEN (CONFIG_NET_ETH_MTU + RNDIS_PACKET_HDR_SIZE) +#define CONFIG_RNDIS_BULKOUT_REQLEN CONFIG_RNDIS_BULKIN_REQLEN #define RNDIS_NCONFIGS (1) #define RNDIS_CONFIGID (1) @@ -217,6 +218,7 @@ struct rndis_oid_value_s static int rndis_ifup(FAR struct net_driver_s *dev); static int rndis_ifdown(FAR struct net_driver_s *dev); static int rndis_txavail(FAR struct net_driver_s *dev); +static int rndis_transmit(FAR struct rndis_dev_s *priv); static int rndis_txpoll(FAR struct net_driver_s *dev); static void rndis_polltimer(int argc, uint32_t arg, ...); @@ -329,16 +331,26 @@ const static struct rndis_cfgdesc_s g_rndis_cfgdesc = .type = USB_DESC_TYPE_ENDPOINT, .addr = RNDIS_EPBULKIN_ADDR, .attr = USB_EP_ATTR_XFER_BULK, +#ifdef CONFIG_USBDEV_DUALSPEED + .mxpacketsize = { LSBYTE(512), MSBYTE(512) }, + .interval = 0 +#else .mxpacketsize = { LSBYTE(64), MSBYTE(64) }, .interval = 1 +#endif }, { .len = USB_SIZEOF_EPDESC, .type = USB_DESC_TYPE_ENDPOINT, .addr = RNDIS_EPBULKOUT_ADDR, .attr = USB_EP_ATTR_XFER_BULK, +#ifdef CONFIG_USBDEV_DUALSPEED + .mxpacketsize = { LSBYTE(512), MSBYTE(512) }, + .interval = 0 +#else .mxpacketsize = { LSBYTE(64), MSBYTE(64) }, .interval = 1 +#endif } }; @@ -390,7 +402,11 @@ static const struct rndis_oid_value_s g_rndis_oid_values[] = { {RNDIS_OID_GEN_SUPPORTED_LIST, sizeof(g_rndis_supported_oids), 0, g_rndis_supported_oids}, {RNDIS_OID_GEN_MAXIMUM_FRAME_SIZE, 4, CONFIG_NET_ETH_MTU, NULL}, +#ifdef CONFIG_USBDEV_DUALSPEED {RNDIS_OID_GEN_LINK_SPEED, 4, 100000, NULL}, +#else + {RNDIS_OID_GEN_LINK_SPEED, 4, 2000000, NULL}, +#endif {RNDIS_OID_GEN_TRANSMIT_BLOCK_SIZE, 4, CONFIG_NET_ETH_MTU, NULL}, {RNDIS_OID_GEN_RECEIVE_BLOCK_SIZE, 4, CONFIG_NET_ETH_MTU, NULL}, {RNDIS_OID_GEN_VENDOR_ID, 4, 0x00FFFFFF, NULL}, @@ -833,6 +849,28 @@ static void rndis_rxdispatch(FAR void *arg) arp_ipin(&priv->netdev); ipv4_input(&priv->netdev); + + if (priv->netdev.d_len > 0) + { + /* Update the Ethernet header with the correct MAC address */ + +#ifdef CONFIG_NET_IPv6 + if (IFF_IS_IPv4(priv->netdev.d_flags)) +#endif + { + arp_out(&priv->netdev); + } +#ifdef CONFIG_NET_IPv6 + else + { + neighbor_out(&priv->netdev); + } +#endif + + /* And send the packet */ + + rndis_transmit(priv); + } } else #endif @@ -843,7 +881,31 @@ static void rndis_rxdispatch(FAR void *arg) /* Give the IPv6 packet to the network layer */ + arp_ipin(&priv->netdev); ipv6_input(&priv->netdev); + + if (priv->netdev.d_len > 0) + { + /* Update the Ethernet header with the correct MAC address */ + +#ifdef CONFIG_NET_IPv4 + if (IFF_IS_IPv4(priv->netdev.d_flags)) + { + arp_out(&priv->netdev); + } + else +#endif +#ifdef CONFIG_NET_IPv6 + { + neighbor_out(&priv->netdev); + } +#endif + + /* And send the packet */ + + rndis_transmit(priv); + } + } else #endif @@ -853,6 +915,11 @@ static void rndis_rxdispatch(FAR void *arg) NETDEV_RXARP(&priv->netdev); arp_arpin(&priv->netdev); + + if (priv->netdev.d_len > 0) + { + rndis_transmit(priv); + } } else #endif @@ -862,7 +929,6 @@ static void rndis_rxdispatch(FAR void *arg) priv->netdev.d_len = 0; } - rndis_txpoll(&priv->netdev); priv->current_rx_datagram_size = 0; rndis_unblock_rx(priv); @@ -892,6 +958,7 @@ static void rndis_rxdispatch(FAR void *arg) static int rndis_txpoll(FAR struct net_driver_s *dev) { FAR struct rndis_dev_s *priv = (FAR struct rndis_dev_s *)dev->d_private; + int ret = OK; if (!priv->connected) { @@ -927,22 +994,40 @@ static int rndis_txpoll(FAR struct net_driver_s *dev) } #endif /* CONFIG_NET_IPv6 */ - /* Queue the packet */ + ret = rndis_transmit(priv); - rndis_fillrequest(priv, priv->net_req->req); - rndis_sendnetreq(priv); - - if (!rndis_allocnetreq(priv)) - { - return -EBUSY; - } } /* If zero is returned, the polling will continue until all connections have * been examined. */ - return OK; + return ret; +} + +/**************************************************************************** + * Name: rndis_transmit + * + * Description: + * Start hardware transmission. + * + ****************************************************************************/ + +static int rndis_transmit(FAR struct rndis_dev_s *priv) +{ + int ret = OK; + + /* Queue the packet */ + + rndis_fillrequest(priv, priv->net_req->req); + rndis_sendnetreq(priv); + + if (!rndis_allocnetreq(priv)) + { + ret = -EBUSY; + } + + return ret; } /**************************************************************************** @@ -1128,7 +1213,7 @@ static inline int rndis_recvpacket(FAR struct rndis_dev_s *priv, * additional single-byte zero packet. Take that in account here. */ - if (priv->current_rx_msglen % 64 == 0) + if ((priv->current_rx_msglen % priv->epbulkout->maxpacket) == 0) { priv->current_rx_msglen += 1; } @@ -1154,47 +1239,53 @@ static inline int rndis_recvpacket(FAR struct rndis_dev_s *priv, else { if (priv->current_rx_received >= priv->current_rx_datagram_offset && - priv->current_rx_received < priv->current_rx_datagram_size + - priv->current_rx_datagram_offset) + priv->current_rx_received <= priv->current_rx_datagram_size + + priv->current_rx_datagram_offset) { - size_t index = priv->current_rx_received - priv->current_rx_datagram_offset; - size_t copysize = min(reqlen, priv->current_rx_datagram_size + - priv->current_rx_datagram_offset - - priv->current_rx_received); - memcpy(&priv->rx_req->req->buf[RNDIS_PACKET_HDR_SIZE + index], reqbuf, - copysize); - } + size_t copysize = min(reqlen, priv->current_rx_datagram_size - index); - priv->current_rx_received += reqlen; + /* Check if the received packet exceeds request buffer */ - if (priv->current_rx_received >= priv->current_rx_msglen) - { - /* Check for a usable packet length (4 added for the CRC) */ - - if (priv->current_rx_datagram_size > (CONFIG_NET_ETH_MTU + 4) || - priv->current_rx_datagram_size <= (ETH_HDRLEN + 4)) + if ((RNDIS_PACKET_HDR_SIZE + index + copysize) <= CONFIG_NET_ETH_MTU) { - uerr("ERROR: Bad packet size dropped (%d)\n", - priv->current_rx_datagram_size); - NETDEV_RXERRORS(&priv->netdev); - priv->current_rx_datagram_size = 0; + memcpy(&priv->rx_req->req->buf[RNDIS_PACKET_HDR_SIZE + index], reqbuf, + copysize); } else { - int ret; - - DEBUGASSERT(work_available(&priv->rxwork)); - ret = work_queue(ETHWORK, &priv->rxwork, rndis_rxdispatch, - priv, 0); - DEBUGASSERT(ret == 0); - UNUSED(ret); - - rndis_block_rx(priv); - priv->rndis_host_tx_count++; - return -EBUSY; + uerr("The packet exceeds request buffer (reqlen=%d) \n", reqlen); } } + priv->current_rx_received += reqlen; + } + + if (priv->current_rx_received >= priv->current_rx_msglen) + { + /* Check for a usable packet length (4 added for the CRC) */ + + if (priv->current_rx_datagram_size > (CONFIG_NET_ETH_MTU + 4) || + priv->current_rx_datagram_size <= (ETH_HDRLEN + 4)) + { + uerr("ERROR: Bad packet size dropped (%d)\n", + priv->current_rx_datagram_size); + NETDEV_RXERRORS(&priv->netdev); + priv->current_rx_datagram_size = 0; + } + else + { + int ret; + + DEBUGASSERT(work_available(&priv->rxwork)); + ret = work_queue(ETHWORK, &priv->rxwork, rndis_rxdispatch, + priv, 0); + DEBUGASSERT(ret == 0); + UNUSED(ret); + + rndis_block_rx(priv); + priv->rndis_host_tx_count++; + return -EBUSY; + } } return OK; @@ -1294,7 +1385,7 @@ static int rndis_handle_control_message(FAR struct rndis_dev_s *priv, resp->devflags = RNDIS_DEVICEFLAGS; resp->medium = RNDIS_MEDIUM_802_3; resp->pktperxfer = 1; - resp->xfrsize = 36 + RNDIS_BUFFER_SIZE; + resp->xfrsize = (4 + 44 + 22) + RNDIS_BUFFER_SIZE; resp->pktalign = 2; rndis_send_encapsulated_response(priv); @@ -1867,6 +1958,11 @@ static int usbclass_bind(FAR struct usbdevclass_driver_s *driver, reqlen = 64; + if (CONFIG_RNDIS_BULKOUT_REQLEN > reqlen) + { + reqlen = CONFIG_RNDIS_BULKOUT_REQLEN; + } + priv->rdreq = usbclass_allocreq(priv->epbulkout, reqlen); if (priv->rdreq == NULL) {