| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186 |
- /*
- * Copyright (c) 2024, sakumisu
- *
- * SPDX-License-Identifier: Apache-2.0
- */
- #include <nuttx/net/ip.h>
- #include <nuttx/net/netdev.h>
- #include "usbh_core.h"
- #if CONFIG_NET_ETH_PKTSIZE < 1514
- #error "CONFIG_NET_ETH_PKTSIZE must be at least 1514"
- #endif
- #if CONFIG_IOB_BUFSIZE < 1514
- #error "CONFIG_IOB_BUFSIZE must be at least 1514"
- #endif
- #ifndef CONFIG_NETDEV_LATEINIT
- #error "CONFIG_NETDEV_LATEINIT must be enabled"
- #endif
- #ifndef CONFIG_NETUTILS_DHCPC
- #error "CONFIG_NETUTILS_DHCPC must be enabled"
- #endif
- #ifndef CONFIG_NETINIT_DHCPC
- #error "CONFIG_NETINIT_DHCPC must be enabled"
- #endif
- // #define CONFIG_USBHOST_PLATFORM_CDC_ECM
- #define CONFIG_USBHOST_PLATFORM_CDC_RNDIS
- // #define CONFIG_USBHOST_PLATFORM_CDC_NCM
- // #define CONFIG_USBHOST_PLATFORM_ASIX
- // #define CONFIG_USBHOST_PLATFORM_RTL8152
- struct usbh_net {
- struct net_driver_s netdev;
- struct work_s txpollwork;
- bool linkup;
- };
- void usbh_net_eth_output_common(struct net_driver_s *dev, uint8_t *buf)
- {
- usb_memcpy(buf, dev->d_buf, dev->d_len);
- }
- void usbh_net_eth_input_common(struct net_driver_s *dev, uint8_t *buf, size_t len, uint8_t* (*eth_input)(void), int (*eth_output)(uint32_t buflen))
- {
- FAR struct eth_hdr_s *hdr;
- net_lock();
- NETDEV_RXPACKETS(dev);
- /* Any ACK or other response packet generated by the network stack
- * will always be shorter than the received packet, therefore it is
- * safe to pass the received frame buffer directly.
- */
- dev->d_buf = buf;
- dev->d_len = len;
- hdr = (FAR struct eth_hdr_s *)dev->d_buf;
- #ifdef CONFIG_NET_IPv4
- if (hdr->type == HTONS(ETHTYPE_IP)) {
- NETDEV_RXIPV4(dev);
- /* Receive an IPv4 packet from the network device */
- ipv4_input(dev);
- if (dev->d_len > 0) {
- /* And send the packet */
- usbh_net_eth_output_common(dev, eth_input());
- eth_output(dev->d_len);
- }
- } else
- #endif
- #ifdef CONFIG_NET_IPv6
- if (hdr->type == HTONS(ETHTYPE_IP6)) {
- NETDEV_RXIPV6(dev);
- /* Give the IPv6 packet to the network layer */
- ipv6_input(dev);
- if (dev->d_len > 0) {
- /* And send the packet */
- usbh_net_eth_output_common(dev, eth_input());
- eth_output(dev->d_len);
- }
- } else
- #endif
- #ifdef CONFIG_NET_ARP
- if (hdr->type == HTONS(ETHTYPE_ARP)) {
- NETDEV_RXARP(dev);
- arp_input(dev);
- if (dev->d_len > 0) {
- usbh_net_eth_output_common(dev, eth_input());
- eth_output(dev->d_len);
- }
- } else
- #endif
- {
- NETDEV_RXDROPPED(dev);
- }
- net_unlock();
- }
- #ifdef CONFIG_USBHOST_PLATFORM_CDC_RNDIS
- #include "usbh_rndis.h"
- struct usbh_net g_rndis_dev;
- static int rndis_ifup(struct net_driver_s *dev)
- {
- printf("rndis if up\r\n");
- g_rndis_dev.linkup = true;
- usb_osal_thread_create("usbh_rndis_rx", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_rndis_rx_thread, NULL);
- return OK;
- }
- static int rndis_ifdown(struct net_driver_s *dev)
- {
- printf("rndis if down\r\n");
- g_rndis_dev.linkup = false;
- return OK;
- }
- static int rndis_txpoll(struct net_driver_s *dev)
- {
- usbh_net_eth_output_common(&g_rndis_dev.netdev, usbh_rndis_get_eth_txbuf());
- return usbh_rndis_eth_output(g_rndis_dev.netdev.d_len);
- }
- static void rndis_txavail_work(void *arg)
- {
- net_lock();
- if (g_rndis_dev.linkup) {
- devif_poll(&g_rndis_dev.netdev, rndis_txpoll);
- } else {
- }
- net_unlock();
- }
- static int rndis_txavail(struct net_driver_s *dev)
- {
- if (work_available(&g_rndis_dev.txpollwork)) {
- work_queue(LPWORK, &g_rndis_dev.txpollwork, rndis_txavail_work, NULL, 0);
- } else {
- return -1;
- }
- return OK;
- }
- void usbh_rndis_eth_input(uint8_t *buf, uint32_t buflen)
- {
- usbh_net_eth_input_common(&g_rndis_dev.netdev, buf, buflen, usbh_rndis_get_eth_txbuf, usbh_rndis_eth_output);
- }
- void usbh_rndis_run(struct usbh_rndis *rndis_class)
- {
- memset(&g_rndis_dev.netdev, 0, sizeof(struct net_driver_s));
- g_rndis_dev.netdev.d_ifup = rndis_ifup;
- g_rndis_dev.netdev.d_ifdown = rndis_ifdown;
- g_rndis_dev.netdev.d_txavail = rndis_txavail;
- g_rndis_dev.netdev.d_private = rndis_class;
- for (uint8_t j = 0; j < 6; j++) {
- g_rndis_dev.netdev.d_mac.ether.ether_addr_octet[j] = rndis_class->mac[j];
- }
- netdev_register(&g_rndis_dev.netdev, NET_LL_ETHERNET);
- netinit_bringup();
- }
- void usbh_rndis_stop(struct usbh_rndis *rndis_class)
- {
- }
- #endif
|