From 7aa3e2ebd657962940cba587172ee5b712bc0e36 Mon Sep 17 00:00:00 2001 From: zhanghongyu Date: Mon, 8 Apr 2024 21:01:21 +0800 Subject: [PATCH] cdcncm: switch net driver to netdev_lowerhalf optimize the interaction flow associated with network drivers to reduce the amount of code and improve compatibility Signed-off-by: zhanghongyu --- drivers/usbdev/Kconfig | 9 + drivers/usbdev/cdcncm.c | 486 ++++++++------------------- include/nuttx/net/netdev_lowerhalf.h | 52 +++ 3 files changed, 197 insertions(+), 350 deletions(-) diff --git a/drivers/usbdev/Kconfig b/drivers/usbdev/Kconfig index 9fab49cd51..20d2751303 100644 --- a/drivers/usbdev/Kconfig +++ b/drivers/usbdev/Kconfig @@ -1389,6 +1389,15 @@ config CDCNCM_PRODUCTSTR default "CDC/NCM Ethernet" endif # !CDCNCM_COMPOSITE + +config CDCNCM_QUOTA_TX + int "The drive holds the maximum quota of TX" + default 8 + +config CDCNCM_QUOTA_RX + int "The drive holds the maximum quota of RX" + default 8 + endif # CDCNCM config USBDEV_FS diff --git a/drivers/usbdev/cdcncm.c b/drivers/usbdev/cdcncm.c index 038d12760d..34b7d0aace 100644 --- a/drivers/usbdev/cdcncm.c +++ b/drivers/usbdev/cdcncm.c @@ -29,7 +29,6 @@ #include -#include #include #include #include @@ -37,24 +36,15 @@ #include #include #include -#include -#include -#include #include -#include -#include -#include +#include #include #include #include #include #include -#ifdef CONFIG_NET_PKT -# include -#endif - #ifdef CONFIG_BOARD_USBDEV_SERIALSTR # include #endif @@ -88,10 +78,6 @@ #define CDCNCM_TXTIMEOUT (60*CLK_TCK) #define CDCNCM_DGRAM_COMBINE_PERIOD 1 -/* This is a helper pointer for accessing the contents of Ethernet header */ - -#define BUF ((FAR struct eth_hdr_s *)self->dev.d_buf) - #define NTB_DEFAULT_IN_SIZE 16384 #define NTB_OUT_SIZE 16384 #define TX_MAX_NUM_DPE 32 @@ -304,9 +290,6 @@ struct cdcncm_driver_s FAR struct usbdev_ep_s *epbulkout; /* Bulk OUT endpoint */ uint8_t config; /* Selected configuration number */ - uint16_t pktbuf[(CONFIG_NET_ETH_PKTSIZE + - CONFIG_NET_GUARDSIZE + 1) / 2]; - FAR struct usbdev_req_s *rdreq; /* Single read request */ bool rxpending; /* Packet available in rdreq */ @@ -327,15 +310,14 @@ struct cdcncm_driver_s * to the work queue */ struct work_s notifywork; /* For deferring notify work * to the work queue */ - struct work_s pollwork; /* For deferring poll work to - * the work queue */ struct work_s delaywork; /* For deferring tx work * to the work queue */ /* This holds the information visible to the NuttX network */ - struct net_driver_s dev; /* Interface understood by the + struct netdev_lowerhalf_s dev; /* Interface understood by the * network */ + netpkt_queue_t rx_queue; /* RX packet queue */ }; /**************************************************************************** @@ -344,14 +326,8 @@ struct cdcncm_driver_s /* Network Device ***********************************************************/ -/* Common TX logic */ - -static int cdcncm_transmit(FAR struct cdcncm_driver_s *priv); -static int cdcncm_txpoll(FAR struct net_driver_s *dev); - /* Interrupt handling */ -static void cdcncm_reply(FAR struct cdcncm_driver_s *priv); static void cdcncm_receive(FAR struct cdcncm_driver_s *priv); static void cdcncm_txdone(FAR struct cdcncm_driver_s *priv); @@ -359,22 +335,21 @@ static void cdcncm_interrupt_work(FAR void *arg); /* NuttX callback functions */ -static int cdcncm_ifup(FAR struct net_driver_s *dev); -static int cdcncm_ifdown(FAR struct net_driver_s *dev); - -static void cdcncm_txavail_work(FAR void *arg); -static int cdcncm_txavail(FAR struct net_driver_s *dev); +static int cdcncm_ifup(FAR struct netdev_lowerhalf_s *dev); +static int cdcncm_ifdown(FAR struct netdev_lowerhalf_s *dev); +static int cdcncm_send(struct netdev_lowerhalf_s *dev, netpkt_t *pkt); +static FAR netpkt_t *cdcncm_recv(FAR struct netdev_lowerhalf_s *dev); #if defined(CONFIG_NET_MCASTGROUP) || defined(CONFIG_NET_ICMPv6) -static int cdcncm_addmac(FAR struct net_driver_s *dev, - FAR const uint8_t *mac); +static int cdcncm_addmac(FAR struct netdev_lowerhalf_s *dev, + FAR const uint8_t *mac); #ifdef CONFIG_NET_MCASTGROUP -static int cdcncm_rmmac(FAR struct net_driver_s *dev, - FAR const uint8_t *mac); +static int cdcncm_rmmac(FAR struct netdev_lowerhalf_s *dev, + FAR const uint8_t *mac); #endif #endif #ifdef CONFIG_NETDEV_IOCTL -static int cdcncm_ioctl(FAR struct net_driver_s *dev, int cmd, +static int cdcncm_ioctl(FAR struct netdev_lowerhalf_s *dev, int cmd, unsigned long arg); #endif @@ -475,6 +450,21 @@ static const struct usb_cdc_ncm_ntb_parameters_s g_ntbparameters = .ndpoutalignment = 4, }; +static const struct netdev_ops_s g_netops = +{ + cdcncm_ifup, /* ifup */ + cdcncm_ifdown, /* ifdown */ + cdcncm_send, /* transmit */ + cdcncm_recv, /* receive */ +#ifdef CONFIG_NET_MCASTGROUP + cdcncm_addmac, /* addmac */ + cdcncm_rmmac, /* rmmac */ +#endif +#ifdef CONFIG_NETDEV_IOCTL + cdcncm_ioctl, /* ioctl */ +#endif +}; + /**************************************************************************** * Inline Functions ****************************************************************************/ @@ -558,22 +548,24 @@ void cdcncm_put(FAR uint8_t **address, size_t size, uint32_t value) * Name: cdcncm_transmit_format * * Description: - * Format the data to be sent + * Format the data to be transmitted to the host in the format specified by + * the NCM protocol (Network Control Model) and the NCM NTB (Network + * Transfer Block) format. * * Input Parameters: * self - Reference to the driver state structure + * pkt - Reference to the packet to be transmitted * * Returned Value: * None * - * Assumptions: - * The network is locked. - * ****************************************************************************/ -static void cdcncm_transmit_format(FAR struct cdcncm_driver_s *self) +static void cdcncm_transmit_format(FAR struct cdcncm_driver_s *self, + FAR netpkt_t *pkt) { FAR const struct ndp_parser_opts_s *opts = self->parseropts; + unsigned int dglen = netpkt_getdatalen(&self->dev, pkt); const int div = g_ntbparameters.ndpindivisor; const int rem = g_ntbparameters.ndpinpayloadremainder; const int dgramidxlen = 2 * opts->dgramitemlen; @@ -612,12 +604,13 @@ static void cdcncm_transmit_format(FAR struct cdcncm_driver_s *self) tmp = self->wrreq->buf + ndpindex + opts->ndpsize + self->dgramcount * dgramidxlen; cdcncm_put(&tmp, opts->dgramitemlen, self->dgramaddr - self->wrreq->buf); - cdcncm_put(&tmp, opts->dgramitemlen, self->dev.d_len); + cdcncm_put(&tmp, opts->dgramitemlen, dglen); - /* Fill IP packet: address=self->dev.d_buf, length=self->dev.d_len */ + /* Fill IP packet */ - memcpy(self->dgramaddr, self->dev.d_buf, self->dev.d_len); - self->dgramaddr += self->dev.d_len; + netpkt_copyout(&self->dev, self->dgramaddr, pkt, dglen, 0); + + self->dgramaddr += dglen; self->dgramaddr = (FAR uint8_t *)NCM_ALIGN((uintptr_t)self->dgramaddr, div) + rem; @@ -657,8 +650,6 @@ static void cdcncm_transmit_work(FAR void *arg) { } - net_lock(); - ncblen = opts->nthsize; ndpindex = NCM_ALIGN(ncblen, ndpalign); @@ -683,122 +674,6 @@ static void cdcncm_transmit_work(FAR void *arg) self->wrreq->len = totallen; EP_SUBMIT(self->epbulkin, self->wrreq); - - net_unlock(); -} - -/**************************************************************************** - * Name: cdcncm_transmit - * - * Description: - * Start hardware transmission. Called either from the txdone interrupt - * handling or from watchdog based polling - * - * Input Parameters: - * priv - Reference to the driver state structure - * - * Returned Value: - * OK on success; a negated errno on failure - * - * Assumptions: - * The network is locked. - * - ****************************************************************************/ - -static int cdcncm_transmit(FAR struct cdcncm_driver_s *self) -{ - /* Increment statistics */ - - NETDEV_TXPACKETS(self->dev); - - cdcncm_transmit_format(self); - - if ((self->wrreq->buf + NTB_OUT_SIZE - self->dgramaddr < - self->dev.d_pktsize) || self->dgramcount >= TX_MAX_NUM_DPE) - { - work_cancel(ETHWORK, &self->delaywork); - cdcncm_transmit_work(self); - } - else - { - work_queue(ETHWORK, &self->delaywork, cdcncm_transmit_work, self, - MSEC2TICK(CDCNCM_DGRAM_COMBINE_PERIOD)); - } - - return OK; -} - -/**************************************************************************** - * Name: cdcncm_txpoll - * - * 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 times out 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. - * - ****************************************************************************/ - -static int cdcncm_txpoll(FAR struct net_driver_s *dev) -{ - FAR struct cdcncm_driver_s *priv = - (FAR struct cdcncm_driver_s *)dev->d_private; - - /* Send the packet */ - - cdcncm_transmit(priv); - - /* Check if there is room in the device to hold another packet. If - * not, return a non-zero value to terminate the poll. - */ - - return 1; -} - -/**************************************************************************** - * Name: cdcncm_reply - * - * Description: - * After a packet has been received and dispatched to the network, it - * may return return with an outgoing packet. This function checks for - * that case and performs the transmission if necessary. - * - * Input Parameters: - * priv - Reference to the driver state structure - * - * Returned Value: - * None - * - * Assumptions: - * The network is locked. - * - ****************************************************************************/ - -static void cdcncm_reply(FAR struct cdcncm_driver_s *priv) -{ - /* If the packet dispatch resulted in data that should be sent out on the - * network, the field d_len will set to a value > 0. - */ - - if (priv->dev.d_len > 0) - { - /* And send the packet */ - - cdcncm_transmit(priv); - } } /**************************************************************************** @@ -813,77 +688,33 @@ static void cdcncm_reply(FAR struct cdcncm_driver_s *priv) * Returned Value: * None * - * Assumptions: - * The network is locked. - * ****************************************************************************/ -static void cdcncm_packet_handler(FAR struct cdcncm_driver_s *self) +static int cdcncm_packet_handler(FAR struct cdcncm_driver_s *self, + FAR uint8_t *dgram, uint32_t dglen) { - /* Check for errors and update statistics */ + FAR netpkt_t *pkt = netpkt_alloc(&self->dev, NETPKT_RX); + int ret = -ENOMEM; -#ifdef CONFIG_NET_PKT - /* When packet sockets are enabled, feed the frame into the tap */ - - pkt_input(&self->dev); -#endif - - /* We only accept IP packets of the configured type and ARP packets */ - -#ifdef CONFIG_NET_IPv4 - if (BUF->type == HTONS(ETHTYPE_IP)) + if (pkt == NULL) { - ninfo("IPv4 frame\n"); - NETDEV_RXIPV4(&self->dev); - - /* Receive an IPv4 packet from the network device */ - - ipv4_input(&self->dev); - - /* Check for a reply to the IPv4 packet */ - - cdcncm_reply(self); + return ret; } - else -#endif -#ifdef CONFIG_NET_IPv6 - if (BUF->type == HTONS(ETHTYPE_IP6)) + + ret = netpkt_copyin(&self->dev, pkt, dgram, dglen, 0); + if (ret < 0) { - ninfo("IPv6 frame\n"); - NETDEV_RXIPV6(&self->dev); - - /* Dispatch IPv6 packet to the network layer */ - - ipv6_input(&self->dev); - - /* Check for a reply to the IPv6 packet */ - - cdcncm_reply(self); + netpkt_free(&self->dev, pkt, NETPKT_RX); + return ret; } - else -#endif -#ifdef CONFIG_NET_ARP - if (BUF->type == HTONS(ETHTYPE_ARP)) + + ret = netpkt_tryadd_queue(pkt, &self->rx_queue); + if (ret != 0) { - /* Dispatch ARP packet to the network layer */ - - arp_input(&self->dev); - NETDEV_RXARP(&self->dev); - - /* If the above function invocation resulted in data that should be - * sent out on the network, d_len field will set to a value > 0. - */ - - if (self->dev.d_len > 0) - { - cdcncm_transmit(self); - } - } - else -#endif - { - NETDEV_RXDROPPED(&self->dev); + netpkt_free(&self->dev, pkt, NETPKT_RX); } + + return ret; } /**************************************************************************** @@ -898,9 +729,6 @@ static void cdcncm_packet_handler(FAR struct cdcncm_driver_s *self) * Returned Value: * None * - * Assumptions: - * The network is locked. - * ****************************************************************************/ static void cdcncm_receive(FAR struct cdcncm_driver_s *self) @@ -997,14 +825,11 @@ static void cdcncm_receive(FAR struct cdcncm_driver_s *self) break; } - /* Copy the data data from the hardware to self->dev.d_buf. Set - * amount of data in self->dev.d_len - */ - - memcpy(self->dev.d_buf, self->rdreq->buf + index, dglen); - self->dev.d_len = dglen; dgramcounter++; - cdcncm_packet_handler(self); + + /* Copy the data from the hardware to self->rx_queue. */ + + cdcncm_packet_handler(self, self->rdreq->buf + index, dglen); ndplen -= 2 * (opts->dgramitemlen); } @@ -1025,20 +850,13 @@ static void cdcncm_receive(FAR struct cdcncm_driver_s *self) * Returned Value: * None * - * Assumptions: - * The network is locked. - * ****************************************************************************/ static void cdcncm_txdone(FAR struct cdcncm_driver_s *priv) { - /* Check for errors and update statistics */ - - NETDEV_TXDONE(priv->dev); - /* In any event, poll the network for new TX data */ - devif_poll(&priv->dev, cdcncm_txpoll); + netdev_lower_txdone(&priv->dev); } /**************************************************************************** @@ -1063,19 +881,12 @@ static void cdcncm_interrupt_work(FAR void *arg) FAR struct cdcncm_driver_s *self = (FAR struct cdcncm_driver_s *)arg; irqstate_t flags; - /* Lock the network and serialize driver operations if necessary. - * NOTE: Serialization is only required in the case where the driver work - * is performed on an LP worker thread and where more than one LP worker - * thread has been configured. - */ - - net_lock(); - /* Check if we received an incoming packet, if so, call cdcncm_receive() */ if (self->rxpending) { cdcncm_receive(self); + netdev_lower_rxready(&self->dev); flags = enter_critical_section(); self->rxpending = false; @@ -1100,8 +911,6 @@ static void cdcncm_interrupt_work(FAR void *arg) { leave_critical_section(flags); } - - net_unlock(); } /**************************************************************************** @@ -1122,21 +931,22 @@ static void cdcncm_interrupt_work(FAR void *arg) * ****************************************************************************/ -static int cdcncm_ifup(FAR struct net_driver_s *dev) +static int cdcncm_ifup(FAR struct netdev_lowerhalf_s *dev) { FAR struct cdcncm_driver_s *priv = - (FAR struct cdcncm_driver_s *)dev->d_private; + container_of(dev, struct cdcncm_driver_s, dev); #ifdef CONFIG_NET_IPv4 ninfo("Bringing up: %u.%u.%u.%u\n", - ip4_addr1(dev->d_ipaddr), ip4_addr2(dev->d_ipaddr), - ip4_addr3(dev->d_ipaddr), ip4_addr4(dev->d_ipaddr)); + ip4_addr1(dev->netdev.d_ipaddr), ip4_addr2(dev->netdev.d_ipaddr), + ip4_addr3(dev->netdev.d_ipaddr), ip4_addr4(dev->netdev.d_ipaddr)); #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]); + dev->netdev.d_ipv6addr[0], dev->netdev.d_ipv6addr[1], + dev->netdev.d_ipv6addr[2], dev->netdev.d_ipv6addr[3], + dev->netdev.d_ipv6addr[4], dev->netdev.d_ipv6addr[5], + dev->netdev.d_ipv6addr[6], dev->netdev.d_ipv6addr[7]); #endif priv->bifup = true; @@ -1160,10 +970,10 @@ static int cdcncm_ifup(FAR struct net_driver_s *dev) * ****************************************************************************/ -static int cdcncm_ifdown(FAR struct net_driver_s *dev) +static int cdcncm_ifdown(FAR struct netdev_lowerhalf_s *dev) { FAR struct cdcncm_driver_s *priv = - (FAR struct cdcncm_driver_s *)dev->d_private; + container_of(dev, struct cdcncm_driver_s, dev); irqstate_t flags; /* Disable the Ethernet interrupt */ @@ -1179,87 +989,72 @@ static int cdcncm_ifdown(FAR struct net_driver_s *dev) priv->bifup = false; leave_critical_section(flags); + return OK; } /**************************************************************************** - * Name: cdcncm_txavail_work + * Name: cdcncm_send * * Description: - * Perform an out-of-cycle poll on the worker thread. + * Transmit a packet through the USB interface * * Input Parameters: - * arg - Reference to the NuttX driver state structure (cast to void*) + * dev - Reference to the NuttX netdev lowerhalf driver structure + * pkt - The packet to be sent * * Returned Value: - * None - * - * Assumptions: - * Runs on a work queue thread. + * OK on success * ****************************************************************************/ -static void cdcncm_txavail_work(FAR void *arg) +static int cdcncm_send(FAR struct netdev_lowerhalf_s *dev, FAR netpkt_t *pkt) { - FAR struct cdcncm_driver_s *self = (FAR struct cdcncm_driver_s *)arg; + FAR struct cdcncm_driver_s *self; - /* Lock the network and serialize driver operations if necessary. - * NOTE: Serialization is only required in the case where the driver work - * is performed on an LP worker thread and where more than one LP worker - * thread has been configured. - */ + self = container_of(dev, struct cdcncm_driver_s, dev); + cdcncm_transmit_format(self, pkt); + netpkt_free(dev, pkt, NETPKT_TX); - net_lock(); - - /* Ignore the notification if the interface is not yet up */ - - if (self->bifup) + if ((self->wrreq->buf + NTB_OUT_SIZE - self->dgramaddr < + self->dev.netdev.d_pktsize) || self->dgramcount >= TX_MAX_NUM_DPE) { - devif_poll(&self->dev, cdcncm_txpoll); + work_cancel(ETHWORK, &self->delaywork); + cdcncm_transmit_work(self); } - - net_unlock(); -} - -/**************************************************************************** - * Name: cdcncm_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: - * The network is locked. - * - ****************************************************************************/ - -static int cdcncm_txavail(FAR struct net_driver_s *dev) -{ - FAR struct cdcncm_driver_s *priv = - (FAR struct cdcncm_driver_s *)dev->d_private; - - /* Is our single work structure available? It may not be if there are - * pending interrupt actions and we will have to ignore the Tx - * availability action. - */ - - if (work_available(&priv->pollwork)) + else { - /* Schedule to serialize the poll on the worker thread. */ - - work_queue(ETHWORK, &priv->pollwork, cdcncm_txavail_work, priv, 0); + work_queue(ETHWORK, &self->delaywork, cdcncm_transmit_work, self, + MSEC2TICK(CDCNCM_DGRAM_COMBINE_PERIOD)); } return OK; } +/**************************************************************************** + * Name: cdcncm_recv + * + * Description: + * Receive a packet from the USB interface + * + * Input Parameters: + * dev - Reference to the NuttX netdev lowerhalf driver structure + * + * Returned Value: + * The received packet, or NULL if no packet is available + * + ****************************************************************************/ + +static FAR netpkt_t *cdcncm_recv(FAR struct netdev_lowerhalf_s *dev) +{ + FAR struct cdcncm_driver_s *self; + FAR netpkt_t *pkt; + + self = container_of(dev, struct cdcncm_driver_s, dev); + pkt = netpkt_remove_queue(&self->rx_queue); + return pkt; +} + /**************************************************************************** * Name: cdcncm_addmac * @@ -1277,7 +1072,7 @@ static int cdcncm_txavail(FAR struct net_driver_s *dev) ****************************************************************************/ #if defined(CONFIG_NET_MCASTGROUP) || defined(CONFIG_NET_ICMPv6) -static int cdcncm_addmac(FAR struct net_driver_s *dev, +static int cdcncm_addmac(FAR struct netdev_lowerhalf_s *dev, FAR const uint8_t *mac) { return OK; @@ -1301,7 +1096,8 @@ static int cdcncm_addmac(FAR struct net_driver_s *dev, ****************************************************************************/ #ifdef CONFIG_NET_MCASTGROUP -static int cdcncm_rmmac(FAR struct net_driver_s *dev, FAR const uint8_t *mac) +static int cdcncm_rmmac(FAR struct netdev_lowerhalf_s *dev, + FAR const uint8_t *mac) { return OK; } @@ -1327,7 +1123,7 @@ static int cdcncm_rmmac(FAR struct net_driver_s *dev, FAR const uint8_t *mac) ****************************************************************************/ #ifdef CONFIG_NETDEV_IOCTL -static int cdcncm_ioctl(FAR struct net_driver_s *dev, int cmd, +static int cdcncm_ioctl(FAR struct netdev_lowerhalf_s *dev, int cmd, unsigned long arg) { return -ENOTTY; @@ -1449,7 +1245,7 @@ static void cdcncm_resetconfig(FAR struct cdcncm_driver_s *self) /* Inform the networking layer that the link is down */ - self->dev.d_ifdown(&self->dev); + cdcncm_ifdown(&self->dev); /* Disable endpoints. This should force completion of all pending * transfers. @@ -1545,14 +1341,14 @@ static int cdcncm_setconfig(FAR struct cdcncm_driver_s *self, uint8_t config) /* Set client's MAC address */ - memcpy(self->dev.d_mac.ether.ether_addr_octet, + memcpy(self->dev.netdev.d_mac.ether.ether_addr_octet, "\x00\xe0\xde\xad\xbe\xef", IFHWADDRLEN); /* Report link up to networking layer */ - if (self->dev.d_ifup(&self->dev) == OK) + if (cdcncm_ifup(&self->dev) == OK) { - self->dev.d_flags |= IFF_UP; + self->dev.netdev.d_flags |= IFF_UP; } return OK; @@ -1583,8 +1379,8 @@ static int ncm_notify(FAR struct cdcncm_driver_s *self) /* Notifying the host of the NIC modification status */ req->req = NCM_NETWORK_CONNECTION; - req->value[0] = LSBYTE(IFF_IS_RUNNING(self->dev.d_flags)); - req->value[1] = MSBYTE(IFF_IS_RUNNING(self->dev.d_flags)); + req->value[0] = LSBYTE(IFF_IS_RUNNING(self->dev.netdev.d_flags)); + req->value[1] = MSBYTE(IFF_IS_RUNNING(self->dev.netdev.d_flags)); req->len[0] = 0; req->len[1] = 0; ret = sizeof(*req); @@ -1662,7 +1458,7 @@ static int cdcncm_setinterface(FAR struct cdcncm_driver_s *self, self->notify = NCM_NOTIFY_SPEED; } - netdev_carrier_on(&self->dev); + netdev_lower_carrier_on(&self->dev); work_queue(ETHWORK, &self->notifywork, ncm_do_notify, self, MSEC2TICK(100)); } @@ -2246,7 +2042,6 @@ static int cdcncm_bind(FAR struct usbdevclass_driver_s *driver, } self->txdone = false; - self->dev.d_len = 0; #ifndef CONFIG_CDCNCM_COMPOSITE #ifdef CONFIG_USBDEV_SELFPOWERED @@ -2342,9 +2137,9 @@ static void cdcncm_unbind(FAR struct usbdevclass_driver_s *driver, self->epbulkin = NULL; } - /* Clear out all data in the buffer */ + /* Clear out all data in the rx_queue */ - self->dev.d_len = 0; + netpkt_free_queue(&self->rx_queue); } static int cdcncm_setup(FAR struct usbdevclass_driver_s *driver, @@ -2514,18 +2309,9 @@ static int cdcncm_classobject(int minor, /* Network device initialization */ - self->dev.d_buf = (FAR uint8_t *)self->pktbuf; - self->dev.d_ifup = cdcncm_ifup; /* I/F up (new IP address) callback */ - self->dev.d_ifdown = cdcncm_ifdown; /* I/F down callback */ - self->dev.d_txavail = cdcncm_txavail; /* New TX data callback */ -#ifdef CONFIG_NET_MCASTGROUP - self->dev.d_addmac = cdcncm_addmac; /* Add multicast MAC address */ - self->dev.d_rmmac = cdcncm_rmmac; /* Remove multicast MAC address */ -#endif -#ifdef CONFIG_NETDEV_IOCTL - self->dev.d_ioctl = cdcncm_ioctl; /* Handle network IOCTL commands */ -#endif - self->dev.d_private = self; /* Used to recover private state from dev */ + self->dev.ops = &g_netops; + self->dev.quota[NETPKT_TX] = CONFIG_CDCNCM_QUOTA_TX; + self->dev.quota[NETPKT_RX] = CONFIG_CDCNCM_QUOTA_RX; /* USB device initialization */ @@ -2545,19 +2331,19 @@ static int cdcncm_classobject(int minor, cdcncm_ifdown(&self->dev); /* Read the MAC address from the hardware into - * priv->dev.d_mac.ether.ether_addr_octet + * priv->dev.netdev.d_mac.ether.ether_addr_octet * Applies only if the Ethernet MAC has its own internal address. */ - memcpy(self->dev.d_mac.ether.ether_addr_octet, + memcpy(self->dev.netdev.d_mac.ether.ether_addr_octet, "\x00\xe0\xde\xad\xbe\xef", IFHWADDRLEN); /* Register the device with the OS so that socket IOCTLs can be performed */ - ret = netdev_register(&self->dev, NET_LL_ETHERNET); + ret = netdev_lower_register(&self->dev, NET_LL_ETHERNET); if (ret < 0) { - nerr("netdev_register failed. ret: %d\n", ret); + nerr("netdev_lower_register failed. ret: %d\n", ret); } *classdev = (FAR struct usbdevclass_driver_s *)self; @@ -2592,10 +2378,10 @@ static void cdcncm_uninitialize(FAR struct usbdevclass_driver_s *classdev) /* Un-register the CDC/ECM netdev device */ - ret = netdev_unregister(&self->dev); + ret = netdev_lower_unregister(&self->dev); if (ret < 0) { - nerr("ERROR: netdev_unregister failed. ret: %d\n", ret); + nerr("ERROR: netdev_lower_unregister failed. ret: %d\n", ret); } #ifndef CONFIG_CDCNCM_COMPOSITE diff --git a/include/nuttx/net/netdev_lowerhalf.h b/include/nuttx/net/netdev_lowerhalf.h index c13157d823..1af7ea82cc 100644 --- a/include/nuttx/net/netdev_lowerhalf.h +++ b/include/nuttx/net/netdev_lowerhalf.h @@ -81,6 +81,7 @@ */ typedef struct iob_s netpkt_t; +typedef struct iob_queue_s netpkt_queue_t; enum netpkt_type_e { @@ -510,4 +511,55 @@ bool netpkt_is_fragmented(FAR netpkt_t *pkt); int netpkt_to_iov(FAR struct netdev_lowerhalf_s *dev, FAR netpkt_t *pkt, FAR struct iovec *iov, int iovcnt); +/**************************************************************************** + * Name: netpkt_tryadd_queue + * + * Description: + * Add one net packet to the end of a queue without waiting for resources + * to become free. + * + * Input Parameters: + * pkt - The packet to add + * queue - The queue to add the packet to + * + * Returned Value: + * 0:Success; negated errno on failure + * + ****************************************************************************/ + +#define netpkt_tryadd_queue(pkt, queue) iob_tryadd_queue(pkt, queue) + +/**************************************************************************** + * Name: netpkt_remove_queue + * + * Description: + * Remove one net packet from the head of a queue. + * + * Input Parameters: + * queue - The queue to remove the packet from + * + * Returned Value: + * The packet removed from the queue. NULL is returned if the queue is + * empty. + * + ****************************************************************************/ + +#define netpkt_remove_queue(queue) iob_remove_queue(queue) + +/**************************************************************************** + * Name: netpkt_free_queue + * + * Description: + * Free all net packets in a queue. + * + * Input Parameters: + * queue - The queue to free + * + * Returned Value: + * None + * + ****************************************************************************/ + +#define netpkt_free_queue(queue) iob_free_queue(queue) + #endif /* __INCLUDE_NUTTX_NET_NETDEV_LOWERHALF_H */