Skip to content
Snippets Groups Projects
Commit 14e2b6dc authored by Masayuki Ishikawa's avatar Masayuki Ishikawa Committed by Gregory Nutt
Browse files

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 07b98ccb

    Previous commit b09365784a was based on old rndis.c thus resulted
    in reverting the commit 07b98ccb. This change merges the commit.

    NOTE: In the commit 07b98ccb, max packet size of bulkout was
    assumed to be 64. In this commit, priv->epbulkout->maxpacket is
    used instead.

Approved-by: default avatarGregory Nutt <gnutt@nuttx.org>
parent b238ede6
No related branches found
No related tags found
No related merge requests found
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"
......@@ -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
......@@ -66,6 +66,10 @@
# include <nuttx/leds/userled.h>
#endif
#ifdef CONFIG_RNDIS
# include <nuttx/usb/rndis.h>
#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;
}
/************************************************************************************
* config/stm32f4discovery/src/stm32_netinit.c
*
* Copyright (C) 2017 Masayuki Ishikawa. All rights reserved.
* Author: Masayuki Ishikawa <masayuki.ishikawa@gmail.com>
*
* 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 <nuttx/config.h>
/************************************************************************************
* Public Functions
************************************************************************************/
/************************************************************************************
* Name: up_netinitialize
************************************************************************************/
void up_netinitialize(void)
{
}
......@@ -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 */
rndis_fillrequest(priv, priv->net_req->req);
rndis_sendnetreq(priv);
ret = rndis_transmit(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,46 +1239,52 @@ 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;
uerr("The packet exceeds request buffer (reqlen=%d) \n", reqlen);
}
}
priv->current_rx_received += reqlen;
}
DEBUGASSERT(work_available(&priv->rxwork));
ret = work_queue(ETHWORK, &priv->rxwork, rndis_rxdispatch,
priv, 0);
DEBUGASSERT(ret == 0);
UNUSED(ret);
if (priv->current_rx_received >= priv->current_rx_msglen)
{
/* Check for a usable packet length (4 added for the CRC) */
rndis_block_rx(priv);
priv->rndis_host_tx_count++;
return -EBUSY;
}
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;
}
}
......@@ -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)
{
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment