This is an automated email from the ASF dual-hosted git repository.

lupyuen pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git

commit fe67544d5f0cc5a10affc1562a12f290c79b013b
Author: daniellizewski <[email protected]>
AuthorDate: Mon May 4 10:58:17 2026 -0400

    drivers/usbhost/usbhost_cdcecm.c: Converted CDC-ECM to lower half
    
    Converted USB Host CDC-ECM to a lower half driver.
    Removed existing full network driver callbacks and replaced with lower
    half.
    
    Signed-off-by: daniellizewski <[email protected]>
---
 .../nucleo-h563zi/configs/nshusbnet/defconfig      |   3 +-
 drivers/usbhost/usbhost_cdcecm.c                   | 487 +++++++--------------
 2 files changed, 170 insertions(+), 320 deletions(-)

diff --git a/boards/arm/stm32h5/nucleo-h563zi/configs/nshusbnet/defconfig 
b/boards/arm/stm32h5/nucleo-h563zi/configs/nshusbnet/defconfig
index 1a5b8df5377..b039cd460f2 100644
--- a/boards/arm/stm32h5/nucleo-h563zi/configs/nshusbnet/defconfig
+++ b/boards/arm/stm32h5/nucleo-h563zi/configs/nshusbnet/defconfig
@@ -16,7 +16,6 @@ CONFIG_ARCH_CHIP_STM32H563ZI=y
 CONFIG_ARCH_CHIP_STM32H5=y
 CONFIG_ARCH_INTERRUPTSTACK=2048
 CONFIG_ARCH_STACKDUMP=y
-CONFIG_ARMV8M_STACKCHECK_NONE=y
 CONFIG_BOARD_LOOPSPERMSEC=9251
 CONFIG_BUILTIN=y
 CONFIG_DEBUG_ASSERTIONS=y
@@ -31,6 +30,7 @@ CONFIG_HAVE_CXX=y
 CONFIG_HAVE_CXXINITIALIZE=y
 CONFIG_IDLETHREAD_STACKSIZE=2048
 CONFIG_INIT_ENTRYPOINT="nsh_main"
+CONFIG_INIT_STACKSIZE=4096
 CONFIG_LINE_MAX=64
 CONFIG_NET=y
 CONFIG_NETDB_DNSCLIENT=y
@@ -56,6 +56,7 @@ CONFIG_READLINE_CMD_HISTORY=y
 CONFIG_READLINE_TABCOMPLETION=y
 CONFIG_RR_INTERVAL=200
 CONFIG_SCHED_LPWORK=y
+CONFIG_SCHED_LPWORKSTACKSIZE=4096
 CONFIG_SCHED_WAITPID=y
 CONFIG_STACK_COLORATION=y
 CONFIG_STM32H5_USART3=y
diff --git a/drivers/usbhost/usbhost_cdcecm.c b/drivers/usbhost/usbhost_cdcecm.c
index d02c3cdd51b..d53a572276e 100644
--- a/drivers/usbhost/usbhost_cdcecm.c
+++ b/drivers/usbhost/usbhost_cdcecm.c
@@ -46,16 +46,12 @@
 #include <nuttx/fs/fs.h>
 #include <nuttx/wqueue.h>
 #include <nuttx/signal.h>
-#include <nuttx/net/netdev.h>
+#include <nuttx/net/netdev_lowerhalf.h>
 
 #include <nuttx/usb/cdc.h>
 #include <nuttx/usb/usb.h>
 #include <nuttx/usb/usbhost.h>
 
-#ifdef CONFIG_NET_PKT
-  #include <nuttx/net/pkt.h>
-#endif
-
 /****************************************************************************
  * Pre-processor Definitions
  ****************************************************************************/
@@ -147,7 +143,6 @@ struct usbhost_cdcecm_s
   mutex_t                 lock;         /* Used to maintain mutual exclusive 
access */
   struct work_s           ntwork;       /* Notification work */
   struct work_s           bulk_rxwork;
-  struct work_s           txpollwork;
   struct work_s           destroywork;
   int16_t                 nnbytes;      /* Number of bytes received in 
notification */
   int16_t                 bulkinbytes;
@@ -167,11 +162,11 @@ struct usbhost_cdcecm_s
   uint8_t                 macstridx;     /* MAC address string index */
   uint8_t                 macaddr[6];    /* Device MAC address */
 
-  /* Network device members */
+  /* Network device lowerhalf members */
 
-  bool                    registered;   /* true if the device was registered */
+  netpkt_queue_t          rx_queue;     /* RX packet queue for lowerhalf */
   bool                    bifup;        /* true:ifup false:ifdown */
-  struct net_driver_s     netdev;       /* Interface understood by the network 
*/
+  struct netdev_lowerhalf_s dev;        /* lower half network interface */
 };
 
 /****************************************************************************
@@ -220,17 +215,18 @@ static int usbhost_connect(FAR struct usbhost_class_s 
*usbclass,
                            FAR const uint8_t *configdesc, int desclen);
 static int usbhost_disconnected(FAR struct usbhost_class_s *usbclass);
 
-/* NuttX network callback functions */
-
-static int cdcecm_ifup(struct net_driver_s *dev);
-static int cdcecm_ifdown(struct net_driver_s *dev);
-static int cdcecm_txavail(struct net_driver_s *dev);
-
-/* Network support functions */
+/* Lowerhalf network device operations */
 
-static void cdcecm_receive(struct usbhost_cdcecm_s *priv);
-
-static int cdcecm_txpoll(struct net_driver_s *dev);
+static int cdcecm_net_ifup(FAR struct netdev_lowerhalf_s *dev);
+static int cdcecm_net_ifdown(FAR struct netdev_lowerhalf_s *dev);
+static int cdcecm_net_transmit(FAR struct netdev_lowerhalf_s *dev,
+                               FAR netpkt_t *pkt);
+static FAR netpkt_t *cdcecm_net_receive(FAR struct netdev_lowerhalf_s *dev);
+#ifdef CONFIG_NETDEV_IOCTL
+static int cdcecm_net_ioctl(FAR struct netdev_lowerhalf_s *dev,
+                            int cmd, unsigned long arg);
+#endif
+static void cdcecm_net_reclaim(FAR struct netdev_lowerhalf_s *dev);
 
 /****************************************************************************
  * Private Data
@@ -269,6 +265,20 @@ static struct usbhost_registry_s g_cdcecm =
   g_cdcecm_id                     /* id[] */
 };
 
+/* Netdev operations */
+
+static const struct netdev_ops_s g_cdcecm_netdev_ops =
+{
+    .ifup     = cdcecm_net_ifup,
+    .ifdown   = cdcecm_net_ifdown,
+    .transmit = cdcecm_net_transmit,
+    .receive  = cdcecm_net_receive,
+#ifdef CONFIG_NETDEV_IOCTL
+    .ioctl    = cdcecm_net_ioctl,
+#endif
+    .reclaim  = cdcecm_net_reclaim,
+};
+
 /****************************************************************************
  * Private Functions
  ****************************************************************************/
@@ -402,19 +412,11 @@ static void usbhost_bulkin_work(FAR void *arg)
 {
   struct usbhost_cdcecm_s *priv;
   struct usbhost_hubport_s *hport;
-  struct iob_s *iob = NULL;
+  FAR netpkt_t *pkt = NULL;
 
   priv = (struct usbhost_cdcecm_s *)arg;
   DEBUGASSERT(priv);
 
-  /* We need net_lock and need priv->mutex.
-   * Since the TX path (cdcecm_txpoll) gets net_lock then priv->lock,
-   * we need to follow the same order to prevent a deadlock if there
-   * is more than 1 LPWORK thread
-   */
-
-  net_lock();
-
   nxmutex_lock(&priv->lock);
 
   hport = priv->usbclass.hport;
@@ -423,13 +425,10 @@ static void usbhost_bulkin_work(FAR void *arg)
   if (priv->disconnected || !priv->bifup)
     {
       nxmutex_unlock(&priv->lock);
-      net_unlock();
       return;
     }
 
-  /* Copy incoming data into IOB buffer and
-   * start a new RX as soon as possible
-   */
+  /* Process received data into netpkt and queue for upper half */
 
   if (priv->bulkinbytes > 0)
     {
@@ -439,50 +438,47 @@ static void usbhost_bulkin_work(FAR void *arg)
 
       /* ECM sends raw Ethernet frames - no additional framing */
 
-      if (priv->bulkinbytes <= iob_navail(true) * CONFIG_IOB_BUFSIZE)
+      pkt = netpkt_alloc(&priv->dev, NETPKT_RX);
+      if (pkt != NULL)
         {
-          iob = iob_tryalloc(true);
-          if (iob != NULL)
+          int ret = netpkt_copyin(&priv->dev, pkt,
+                                  priv->bulkinbuf,
+                                  priv->bulkinbytes, 0);
+          if (ret < 0)
+            {
+              netpkt_free(&priv->dev, pkt, NETPKT_RX);
+              pkt = NULL;
+            }
+          else
             {
-              iob_reserve(iob, CONFIG_NET_LL_GUARDSIZE);
-              int ret = iob_trycopyin(iob, priv->bulkinbuf,
-                                      priv->bulkinbytes,
-                                      -NET_LL_HDRLEN(&priv->netdev), true);
-              if (ret != priv->bulkinbytes)
+              ret = netpkt_tryadd_queue(pkt, &priv->rx_queue);
+              if (ret != 0)
                 {
-                  iob_free_chain(iob);
-                  iob = NULL;
+                  netpkt_free(&priv->dev, pkt, NETPKT_RX);
+                  pkt = NULL;
                 }
             }
         }
-
-      if (iob == NULL)
-        {
-          NETDEV_RXDROPPED(&priv->netdev);
-        }
-      else
-        {
-          priv->netdev.d_iob = iob;
-          priv->netdev.d_len = priv->bulkinbytes;
-        }
     }
   else if (priv->bulkinbytes < 0 && priv->bulkinbytes != -EAGAIN)
     {
       uerr("Bulk IN error: %d\n", priv->bulkinbytes);
     }
 
+  /* Restart async RX */
+
   DRVR_ASYNCH(hport->drvr, priv->bulkin,
               (uint8_t *)priv->bulkinbuf, CONFIG_USBHOST_CDCECM_RXBUFSIZE,
               usbhost_bulkin_callback, priv);
 
-  if (iob != NULL)
+  nxmutex_unlock(&priv->lock);
+
+  /* Notify upper half after unlocking to avoid deadlock */
+
+  if (pkt != NULL)
     {
-      cdcecm_receive(priv);
-      netdev_iob_release(&priv->netdev);
+      netdev_lower_rxready(&priv->dev);
     }
-
-  nxmutex_unlock(&priv->lock);
-  net_unlock();
 }
 
 /****************************************************************************
@@ -497,9 +493,6 @@ static void usbhost_bulkin_work(FAR void *arg)
  * Returned Value:
  *   None
  *
- * Assumptions:
- *   Probably called from an interrupt handler.
- *
  ****************************************************************************/
 
 static void usbhost_notification_work(FAR void *arg)
@@ -541,24 +534,28 @@ static void usbhost_notification_work(FAR void *arg)
                    */
 
                   if (inmsg->value[0] &&
-                      !IFF_IS_RUNNING(priv->netdev.d_flags))
+                      !IFF_IS_RUNNING(priv->dev.netdev.d_flags))
                   {
                     uinfo("Network connected\n");
-                    netdev_carrier_on(&priv->netdev);
+                    netdev_lower_carrier_on(&priv->dev);
                   }
                   else if (!inmsg->value[0] &&
-                           IFF_IS_RUNNING(priv->netdev.d_flags))
+                           IFF_IS_RUNNING(priv->dev.netdev.d_flags))
                   {
                     uinfo("Network disconnected\n");
-                    netdev_carrier_off(&priv->netdev);
+                    netdev_lower_carrier_off(&priv->dev);
                   }
                   break;
 
                 case ECM_SPEED_CHANGE:
 
-                  /* Connection speed changed - informational only */
+                  /* Connection speed changed - informational only.
+                   * Disabled print since some adapters send this very
+                   * frequently even if there is no change
+                   */
+
+                  /* uinfo("Speed change notification\n"); */
 
-                  uinfo("Speed change notification\n");
                   break;
 
                 default:
@@ -573,7 +570,7 @@ static void usbhost_notification_work(FAR void *arg)
 
       ret = DRVR_ASYNCH(hport->drvr, priv->intin,
                         (FAR uint8_t *)priv->notification,
-                        SIZEOF_NOTIFICATION_S(0),
+                        priv->maxintsize,
                         usbhost_notification_callback,
                         priv);
       if (ret < 0)
@@ -699,11 +696,7 @@ static void usbhost_destroy(FAR void *arg)
 
   /* Unregister the network device */
 
-  if (priv->registered)
-    {
-      netdev_unregister(&priv->netdev);
-      priv->registered = false;
-    }
+  netdev_lower_unregister(&priv->dev);
 
   /* Cancel any pending work */
 
@@ -711,8 +704,6 @@ static void usbhost_destroy(FAR void *arg)
 
   work_cancel(LPWORK, &priv->bulk_rxwork);
 
-  work_cancel(LPWORK, &priv->txpollwork);
-
   /* Free the endpoints */
 
   if (priv->intin)
@@ -1168,7 +1159,7 @@ static int usbhost_parse_mac_string(FAR const uint8_t * 
strdesc,
 static int usbhost_get_mac_address(FAR struct usbhost_cdcecm_s * priv)
 {
   int ret;
-  uint8_t strbuf[64];
+  uint8_t *strbuf;
 
   if (priv->macstridx == 0)
     {
@@ -1176,16 +1167,24 @@ static int usbhost_get_mac_address(FAR struct 
usbhost_cdcecm_s * priv)
       return -ENOENT;
     }
 
+  ret = DRVR_IOALLOC(priv->usbclass.hport->drvr, &strbuf, 64);
+  if (ret < 0)
+    {
+      uerr("ERROR: DRVR_IOALLOC of notification buf failed: %d (%d bytes)\n",
+           ret, priv->maxintsize);
+      return ret;
+    }
+
   ret = usbhost_ctrl_cmd(priv,
                          USB_REQ_DIR_IN | USB_REQ_TYPE_STANDARD |
                          USB_REQ_RECIPIENT_DEVICE,
                          USB_REQ_GETDESCRIPTOR,
                          (USB_DESC_TYPE_STRING << 8) | priv->macstridx,
-                         0x0409, strbuf, sizeof(strbuf));
+                         0x0409, strbuf, 64);
   if (ret < 0)
     {
       uerr("Failed to get MAC string descriptor: %d\n", ret);
-      return ret;
+      goto errout;
     }
 
   /* Parse MAC address from Unicode string */
@@ -1194,14 +1193,18 @@ static int usbhost_get_mac_address(FAR struct 
usbhost_cdcecm_s * priv)
   if (ret < 0)
     {
       uerr("Failed to parse MAC address: %d\n", ret);
-      return ret;
+      goto errout;
     }
 
   uinfo("Device MAC: %02x:%02x:%02x:%02x:%02x:%02x\n",
         priv->macaddr[0], priv->macaddr[1], priv->macaddr[2],
         priv->macaddr[3], priv->macaddr[4], priv->macaddr[5]);
 
-  return OK;
+  ret = OK;
+
+errout:
+  (void)DRVR_IOFREE(priv->usbclass.hport->drvr, strbuf);
+  return ret;
 }
 
 /****************************************************************************
@@ -1282,6 +1285,22 @@ static inline int usbhost_devinit(FAR struct 
usbhost_cdcecm_s *priv)
       priv->macaddr[5] = rand() & 0xff;
     }
 
+  /* Setup and register the lowerhalf network device */
+
+  FAR struct netdev_lowerhalf_s *dev = &priv->dev;
+
+  memset(dev, 0, sizeof(*dev));
+  memcpy(dev->netdev.d_mac.ether.ether_addr_octet,
+         priv->macaddr, sizeof(priv->macaddr));
+
+  dev->ops = &g_cdcecm_netdev_ops;
+  dev->quota[NETPKT_TX] = 1;
+  dev->quota[NETPKT_RX] = 1;
+  dev->rxtype           = NETDEV_RX_WORK;
+  dev->priority         = LPWORK;
+
+  netdev_lower_register(dev, NET_LL_ETHERNET);
+
   if (priv->intin)
     {
       /* Begin monitoring of message available events */
@@ -1289,7 +1308,7 @@ static inline int usbhost_devinit(FAR struct 
usbhost_cdcecm_s *priv)
       uinfo("Start notification monitoring\n");
       ret = DRVR_ASYNCH(hport->drvr, priv->intin,
                         (FAR uint8_t *)priv->notification,
-                        SIZEOF_NOTIFICATION_S(0),
+                        priv->maxintsize,
                         usbhost_notification_callback,
                         priv);
       if (ret < 0)
@@ -1298,21 +1317,6 @@ static inline int usbhost_devinit(FAR struct 
usbhost_cdcecm_s *priv)
         }
     }
 
-  /* Setup the network interface */
-
-  memset(&priv->netdev, 0, sizeof(struct net_driver_s));
-  priv->netdev.d_ifup    = cdcecm_ifup;
-  priv->netdev.d_ifdown  = cdcecm_ifdown;
-  priv->netdev.d_txavail = cdcecm_txavail;
-  priv->netdev.d_private = priv;
-  memcpy(priv->netdev.d_mac.ether.ether_addr_octet,
-         priv->macaddr, sizeof(priv->macaddr));
-
-  /* Register the network device */
-
-  netdev_register(&priv->netdev, NET_LL_ETHERNET);
-  priv->registered = true;
-
   /* Check if we successfully initialized. We now have to be concerned
    * about asynchronous modification of crefs because the character
    * driver has been registered.
@@ -1343,8 +1347,9 @@ static inline int usbhost_devinit(FAR struct 
usbhost_cdcecm_s *priv)
 
           uinfo("Successfully initialized\n");
           priv->crefs--;
-          nxmutex_unlock(&priv->lock);
         }
+
+      nxmutex_unlock(&priv->lock);
     }
 
   return ret;
@@ -1741,203 +1746,124 @@ static int usbhost_disconnected(struct 
usbhost_class_s *usbclass)
 }
 
 /****************************************************************************
- * Name: cdcecm_transmit
+ * Name: cdcecm_net_transmit
  *
  * Description:
- *   Start hardware transmission.  Called either from the txdone interrupt
- *   handling or from watchdog based polling.
+ *   Lowerhalf transmit callback. Copies packet data to USB bulk OUT buffer
+ *   and performs a blocking USB transfer.
  *
  * Input Parameters:
- *   priv - Reference to the driver state structure
+ *   dev - Reference to the lowerhalf driver structure
+ *   pkt - The packet to send (driver takes ownership and must free)
  *
  * Returned Value:
  *   OK on success; a negated errno on failure
  *
- * Assumptions:
- *   The network is locked.
- *
  ****************************************************************************/
 
-static int cdcecm_transmit(struct usbhost_cdcecm_s *priv)
+static int cdcecm_net_transmit(FAR struct netdev_lowerhalf_s *dev,
+                               FAR netpkt_t *pkt)
 {
-  struct usbhost_hubport_s *hport;
+  FAR struct usbhost_cdcecm_s *priv;
+  FAR struct usbhost_hubport_s *hport;
+  unsigned int datalen;
   ssize_t ret;
 
+  priv = container_of(dev, struct usbhost_cdcecm_s, dev);
   hport = priv->usbclass.hport;
 
-  uinfo("transmit packet: %d bytes\n", priv->netdev.d_len);
+  datalen = netpkt_getdatalen(dev, pkt);
+  uinfo("transmit packet: %u bytes\n", datalen);
 
-  /* Increment statistics */
-
-  NETDEV_TXPACKETS(&priv->netdev);
+  if (datalen > CONFIG_USBHOST_CDCECM_TXBUFSIZE)
+    {
+      netpkt_free(dev, pkt, NETPKT_TX);
+      return -EMSGSIZE;
+    }
 
-  /* For ECM, we send raw Ethernet frames - no additional framing needed.
-   * Copy the frame to the TX buffer and send it.
+  /* Copy packet data to USB bulk out buffer.
+   * ECM sends raw Ethernet frames - no additional framing needed.
    */
 
-  if (priv->netdev.d_len > CONFIG_USBHOST_CDCECM_TXBUFSIZE)
+  ret = netpkt_copyout(dev, priv->bulkoutbuf, pkt, datalen, 0);
+  netpkt_free(dev, pkt, NETPKT_TX);
+
+  if (ret < 0)
     {
-      NETDEV_TXERRORS(&priv->netdev);
-      return -EMSGSIZE;
+      return ret;
     }
 
-  iob_copyout(priv->bulkoutbuf, priv->netdev.d_iob, priv->netdev.d_len,
-    -NET_LL_HDRLEN(&priv->netdev));
-  cdcecm_print_packet("ECM TX Packet:",
-                      priv->bulkoutbuf, priv->netdev.d_len);
+  cdcecm_print_packet("ECM TX Packet:", priv->bulkoutbuf, datalen);
 
-  ret = DRVR_TRANSFER(hport->drvr, priv->bulkout, priv->bulkoutbuf,
-    priv->netdev.d_len);
+  ret = DRVR_TRANSFER(hport->drvr, priv->bulkout,
+                      priv->bulkoutbuf, datalen);
   if (ret < 0)
     {
-      uerr("transfer returned error: %d\n", ret);
+      uerr("ERROR: DRVR_TRANSFER failed: %zd\n", ret);
       return ret;
     }
 
-  NETDEV_TXDONE(&priv->netdev);
+  netdev_lower_txdone(dev);
   return OK;
 }
 
 /****************************************************************************
- * Name: cdcecm_receive
+ * Name: cdcecm_net_receive
  *
  * Description:
- *   Handle a received packet.
+ *   Lowerhalf receive callback. Dequeues a received packet from the RX
+ *   queue. Called by upper half after netdev_lower_rxready() notification.
  *
  * Input Parameters:
- *   priv - Reference to the driver state structure
+ *   dev - Reference to the lowerhalf driver structure
  *
  * Returned Value:
- *   OK on success; a negated errno on failure
+ *   A netpkt containing the received packet, or NULL if no more packets.
  *
- * Assumptions:
- *   The network is locked.
  ****************************************************************************/
 
-static void cdcecm_receive(struct usbhost_cdcecm_s *priv)
+static FAR netpkt_t *cdcecm_net_receive(FAR struct netdev_lowerhalf_s *dev)
 {
-  FAR struct eth_hdr_s * ethhdr;
-
-  NETDEV_RXPACKETS(&priv->netdev);
-
-  /* Validate frame length */
-
-  if (priv->netdev.d_len < ETH_HDRLEN ||
-      priv->netdev.d_len > priv->maxsegment)
-    {
-      NETDEV_RXERRORS(&priv->netdev);
-      nwarn("Invalid frame length: %zu\n", priv->netdev.d_len);
-      return;
-    }
-
-  ethhdr = (struct eth_hdr_s *)
-        &priv->netdev.d_iob->io_data[CONFIG_NET_LL_GUARDSIZE -
-                             NET_LL_HDRLEN(&priv->netdev)];
-
-  /* Check the Ethertype */
-
-#ifdef CONFIG_NET_IPv4
-  if (ethhdr->type == HTONS(ETHTYPE_IP))
-    {
-      NETDEV_RXIPV4(&priv->netdev);
-      ipv4_input(&priv->netdev);
-
-      if (priv->netdev.d_len > 0)
-        {
-          cdcecm_transmit(priv);
-        }
-    }
-  else
-#endif
-#ifdef CONFIG_NET_IPv6
-  if (ethhdr->type == HTONS(ETHTYPE_IP6))
-    {
-      NETDEV_RXIPV6(&priv->netdev);
-      ipv6_input(&priv->netdev);
-
-      if (priv->netdev.d_len > 0)
-        {
-          cdcecm_transmit(priv);
-        }
-    }
-  else
-#endif
-#ifdef CONFIG_NET_ARP
-  if (ethhdr->type == HTONS(ETHTYPE_ARP))
-    {
-      NETDEV_RXARP(&priv->netdev);
-      arp_input(&priv->netdev);
-
-      if (priv->netdev.d_len > 0)
-        {
-          cdcecm_transmit(priv);
-        }
-    }
-  else
-#endif
-#ifdef CONFIG_NET_PKT
-  if (1)
-    {
-      /* Forward raw packet to packet socket */
+  FAR struct usbhost_cdcecm_s *priv;
 
-      pkt_input(&priv->netdev);
-    }
-  else
-#endif
-    {
-      NETDEV_RXDROPPED(&priv->netdev);
-    }
+  priv = container_of(dev, struct usbhost_cdcecm_s, dev);
+  return netpkt_remove_queue(&priv->rx_queue);
 }
 
 /****************************************************************************
- * Name: cdcecm_txpoll
+ * Name: cdcecm_net_ioctl
  *
  * Description:
- *   The transmitter is available, check if the network has any outgoing
- *   packets ready to send.  This is a callback from devif_poll().
- *   devif_poll() may be called:
- *
- *   1. When the preceding TX packet send is complete,
- *   2. When the preceding TX packet send timesout and the interface is reset
- *   3. During normal TX polling
- *
- * Input Parameters:
- *   dev - Reference to the NuttX driver state structure
- *
- * Returned Value:
- *   OK on success; a negated errno on failure
- *
- * Assumptions:
- *   The network is locked.
+ *   Lowerhalf ioctl callback.
  *
  ****************************************************************************/
 
-static int cdcecm_txpoll(struct net_driver_s *dev)
+#ifdef CONFIG_NETDEV_IOCTL
+static int cdcecm_net_ioctl(FAR struct netdev_lowerhalf_s *dev, int cmd,
+                            unsigned long arg)
 {
-  struct usbhost_cdcecm_s *priv = (struct usbhost_cdcecm_s *)
-                                   dev->d_private;
-
-  /* If the polling resulted in data that should be sent out on the network,
-   * the field d_len is set to a value > 0.
-   */
-
-  nxmutex_lock(&priv->lock);
-
-  /* Send the packet */
-
-  cdcecm_transmit(priv);
+  return -ENOTTY;
+}
+#endif
 
-  nxmutex_unlock(&priv->lock);
+/****************************************************************************
+ * Name: cdcecm_net_reclaim
+ *
+ * Description:
+ *   Lowerhalf reclaim callback. TX is synchronous via DRVR_TRANSFER
+ *   so there are no queued TX packets to reclaim.
+ *
+ ****************************************************************************/
 
-  return 0;
+static void cdcecm_net_reclaim(FAR struct netdev_lowerhalf_s *dev)
+{
 }
 
 /****************************************************************************
  * Name: cdcecm_ifup
  *
  * Description:
- *   NuttX Callback: Bring up the ECM interface when an IP address is
- *   provided
+ *   NuttX Callback: Bring up the ECM interface
  *
  * Input Parameters:
  *   dev - Reference to the NuttX driver state structure
@@ -1949,27 +1875,16 @@ static int cdcecm_txpoll(struct net_driver_s *dev)
  *
  ****************************************************************************/
 
-static int cdcecm_ifup(struct net_driver_s *dev)
+static int cdcecm_net_ifup(struct netdev_lowerhalf_s *dev)
 {
-  struct usbhost_cdcecm_s *priv = (struct usbhost_cdcecm_s *)
-                                   dev->d_private;
+  FAR struct usbhost_cdcecm_s *priv;
+
+  priv = container_of(dev, struct usbhost_cdcecm_s, dev);
   nxmutex_lock(&priv->lock);
 
   struct usbhost_hubport_s *hport = priv->usbclass.hport;
   int ret;
 
-#ifdef CONFIG_NET_IPv4
-  ninfo("Bringing up: %d.%d.%d.%d\n",
-        (int)(dev->d_ipaddr & 0xff), (int)((dev->d_ipaddr >> 8) & 0xff),
-        (int)((dev->d_ipaddr >> 16) & 0xff), (int)(dev->d_ipaddr >> 24));
-#endif
-#ifdef CONFIG_NET_IPv6
-  ninfo("Bringing up: %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
-        dev->d_ipv6addr[0], dev->d_ipv6addr[1], dev->d_ipv6addr[2],
-        dev->d_ipv6addr[3], dev->d_ipv6addr[4], dev->d_ipv6addr[5],
-        dev->d_ipv6addr[6], dev->d_ipv6addr[7]);
-#endif
-
   /* Activate the data interface by setting alternate setting 1 */
 
   ret = usbhost_setinterface(priv, priv->dataif, 1);
@@ -2025,18 +1940,17 @@ static int cdcecm_ifup(struct net_driver_s *dev)
  *
  ****************************************************************************/
 
-static int cdcecm_ifdown(struct net_driver_s *dev)
+static int cdcecm_net_ifdown(struct netdev_lowerhalf_s *dev)
 {
-  struct usbhost_cdcecm_s *priv = (struct usbhost_cdcecm_s *)
-                                   dev->d_private;
+  struct usbhost_cdcecm_s *priv;
+
+  priv = container_of(dev, struct usbhost_cdcecm_s, dev);
   nxmutex_lock(&priv->lock);
 
   /* Deactivate the data interface */
 
   usbhost_setinterface(priv, priv->dataif, 0);
 
-  /* Mark the device "down" */
-
   priv->bifup = false;
 
   nxmutex_unlock(&priv->lock);
@@ -2044,71 +1958,6 @@ static int cdcecm_ifdown(struct net_driver_s *dev)
   return OK;
 }
 
-/****************************************************************************
- * Name: cdcecm_txavail_work
- *
- * Description:
- *   Driver callback invoked when new TX data is available.  This is a
- *   stimulus perform an out-of-cycle poll and, thereby, reduce the TX
- *   latency.
- *
- * Input Parameters:
- *   dev - Reference to the NuttX driver state structure
- *
- * Returned Value:
- *   None
- *
- * Assumptions:
- *   Called in normal user mode
- *
- ****************************************************************************/
-
-static void cdcecm_txavail_work(void *arg)
-{
-  struct usbhost_cdcecm_s *priv = (struct usbhost_cdcecm_s *)arg;
-
-  net_lock();
-
-  if (priv->bifup)
-    {
-      devif_poll(&priv->netdev, cdcecm_txpoll);
-    }
-
-  net_unlock();
-}
-
-/****************************************************************************
- * Name: cdcecm_txavail
- *
- * Description:
- *   Driver callback invoked when new TX data is available.  This is a
- *   stimulus perform an out-of-cycle poll and, thereby, reduce the TX
- *   latency.
- *
- * Input Parameters:
- *   dev - Reference to the NuttX driver state structure
- *
- * Returned Value:
- *   None
- *
- * Assumptions:
- *   Called from the network stack with the network locked.
- *
- ****************************************************************************/
-
-static int cdcecm_txavail(struct net_driver_s *dev)
-{
-  struct usbhost_cdcecm_s *priv = (struct usbhost_cdcecm_s *)
-                                   dev->d_private;
-
-  if (work_available(&priv->txpollwork))
-    {
-      work_queue(LPWORK, &priv->txpollwork, cdcecm_txavail_work, priv, 0);
-    }
-
-  return OK;
-}
-
 /****************************************************************************
  * Public Functions
  ****************************************************************************/

Reply via email to