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 <zhanghongyu@xiaomi.com>
This commit is contained in:
zhanghongyu 2024-04-08 21:01:21 +08:00 committed by Xiang Xiao
parent 4e79741e7d
commit 7aa3e2ebd6
3 changed files with 197 additions and 350 deletions

View File

@ -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

View File

@ -29,7 +29,6 @@
#include <nuttx/config.h>
#include <arpa/inet.h>
#include <assert.h>
#include <debug.h>
#include <errno.h>
@ -37,24 +36,15 @@
#include <stdint.h>
#include <string.h>
#include <time.h>
#include <sys/types.h>
#include <nuttx/arch.h>
#include <nuttx/irq.h>
#include <nuttx/kmalloc.h>
#include <nuttx/net/ip.h>
#include <nuttx/net/netdev.h>
#include <nuttx/semaphore.h>
#include <nuttx/net/netdev_lowerhalf.h>
#include <nuttx/usb/cdc.h>
#include <nuttx/usb/cdcncm.h>
#include <nuttx/usb/usbdev.h>
#include <nuttx/usb/usbdev_trace.h>
#include <nuttx/wqueue.h>
#ifdef CONFIG_NET_PKT
# include <nuttx/net/pkt.h>
#endif
#ifdef CONFIG_BOARD_USBDEV_SERIALSTR
# include <nuttx/board.h>
#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

View File

@ -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 */