| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975 |
- #include "usb_os_adapter.h"
- #include "board.h"
- #include <linux/usb/cdc.h>
- #include "linux/usb/composite.h"
- #include "linux/usb/ether.h"
- #include <stdio.h>
- #include "FreeRTOS.h"
- #include "trace.h"
- #include "list.h"
- #include "task.h"
- #include "ark_dwc2.h"
- #if !USE_LWIP
- #include "FreeRTOS_IP.h"
- #include "FreeRTOS_IP_Private.h"
- #include "NetworkBufferManagement.h"
- #include "NetworkInterface.h"
- #else
- #include "queue.h"
- #include "lwip/pbuf.h"
- #include "ethernet.h"
- struct netif *ncm_netif = NULL;
- void ncm_net_set_intf(void* intf)
- {
- ncm_netif = (struct netif *)intf;
- }
- extern void ncm_ethernetif_input(void *h, struct pbuf* p);
- #endif
- #define UETH__VERSION "29-May-2008"
- #define WORK_RX_MEMORY 0
- struct eth_dev {
- spinlock_t lock;
- struct gether *port_usb;
- struct usb_gadget *gadget;
- spinlock_t req_lock;
- List_t tx_reqs;
- atomic_t tx_qlen;
- #if !USE_LWIP
- List_t rx_frames;
- #else
- struct pbuf rx_frames;
- #endif
- struct usb_request *out_req;
- unsigned header_len;
- bool zlp;
- u8 host_mac[ETH_ALEN];
- TaskHandle_t usb_ether_task;
- QueueHandle_t usb_ether_event_queue;
- int start;
- int tx_err_count;
- };
- struct eth_event
- {
- int type;
- void* priv;
- };
- #define USB_ETH_EVENT_USB_CONNECT 0
- #define USB_ETH_EVENT_USB_DISCONNECT 1
- #define USB_ETH_EVENT_USB_DATA_RX 2 // usb recv data
- #define USB_ETH_EVENT_USB_DATA_TX 3 // usb data tx ok notify
- #define USB_ETH_EVENT_NET_DATA_TX 4 // data from tcpip
- /*-------------------------------------------------------------------------*/
- #undef atomic_read
- #define atomic_read(v) ((v)->counter)
- #undef atomic_set
- #define atomic_set(v,i) ((v)->counter = (i))
- #undef atomic_inc
- #define atomic_inc(v) ((v)->counter++)
- #define RX_EXTRA 20 /* bytes guarding against rx overflows */
- #define DEFAULT_QLEN 4/* double buffering by default */
- static unsigned qmult = 2;
- static struct eth_dev *the_dev;
- /* for dual-speed hardware, use deeper queues at high/super speed */
- static inline int qlen(struct usb_gadget *gadget)
- {
- if (gadget_is_dualspeed(gadget) && (gadget->speed == USB_SPEED_HIGH ||
- gadget->speed == USB_SPEED_SUPER))
- return qmult * DEFAULT_QLEN;
- else
- return DEFAULT_QLEN * 8;
- }
- /*-------------------------------------------------------------------------*/
- #undef DBG
- #undef VDBG
- #undef ERROR
- #undef INFO
- #define xprintk(d, level, fmt, args...) \
- printk(level "%s: " fmt , (d)->net->name , ## args)
- #ifdef DEBUG
- #undef DEBUG
- #define DBG(dev, fmt, args...) \
- xprintk(dev , KERN_DEBUG , fmt , ## args)
- #else
- #define DBG(dev, fmt, args...) \
- do { } while (0)
- #endif /* DEBUG */
- #ifdef VERBOSE_DEBUG
- #define VDBG DBG
- #else
- #define VDBG(dev, fmt, args...) \
- do { } while (0)
- #endif /* DEBUG */
- #define ERROR(dev, fmt, args...) \
- xprintk(dev , KERN_ERR , fmt , ## args)
- #define INFO(dev, fmt, args...) \
- xprintk(dev , KERN_INFO , fmt , ## args)
- static void ether_disconnect(struct gether *link);
- static int ether_connect(struct eth_dev *dev, struct gether *link);
- static int rx_submit(struct eth_dev *dev, struct usb_request *req, gfp_t gfp_flags);
- static void rx_complete(struct usb_ep *ep, struct usb_request *req);
- int ncm_get_mac_address(char mac[6])
- {
- if (the_dev)
- memcpy(mac, the_dev->host_mac, 6);
- return 0;
- }
- static int prealloc(List_t *list, struct usb_ep *ep, unsigned n)
- {
- unsigned i;
- struct usb_request *req;
- ListItem_t *pxListItem = NULL;
- if (!n)
- return -ENOMEM;
- i = n;
- list_for_each_entry(pxListItem, req, list) {
- if (i-- == 0) {
- printf("prealloc out!\r\n");
- goto extra;
- }
- }
- while (i--) {
- req = usb_ep_alloc_request(ep, GFP_ATOMIC);
- if (!req)
- return list_empty(list) ? -ENOMEM : 0;
- vListInitialiseItem(&req->list);
- listSET_LIST_ITEM_OWNER(&(req->list), req);
- printf("req:%x is alloc\n", req);
- req->buf = NULL;
- req->length = 0;
- list_add_tail(&req->list, list);
- }
- return 0;
- extra:
- /* free extras */
- for (;;) {
- ListItem_t *next;
- next = listGET_NEXT(&req->list);
- uxListRemove(&req->list);
- usb_ep_free_request(ep, req);
- if (next == listGET_END_MARKER(list))
- break;
- req = listGET_LIST_ITEM_OWNER(&req->list);
- }
- return 0;
- }
- static int alloc_requests(struct eth_dev *dev, struct gether *link, unsigned n)
- {
- int status;
- spin_lock(&dev->req_lock);
- status = prealloc(&dev->tx_reqs, link->in_ep, n);
- if (status < 0)
- goto fail;
- /*status = prealloc(&dev->rx_reqs, link->out_ep, n);
- if (status < 0)
- goto fail;*/
- goto done;
- fail:
- DBG(dev, "can't alloc requests\n");
- done:
- spin_unlock(&dev->req_lock);
- return status;
- }
- static void rx_fill(struct eth_dev *dev, gfp_t gfp_flags)
- {
- //struct usb_request *req;
- //unsigned long flags;
- /* fill unused rxq slots with some skb */
- /*spin_lock_irqsave(&dev->req_lock, flags);
- while (!list_empty(&dev->rx_reqs)) {
- req = listGET_LIST_ITEM_OWNER(listGET_HEAD_ENTRY(&dev->rx_reqs));
- list_del_init(&req->list);
- spin_unlock_irqrestore(&dev->req_lock, flags);
- rx_submit(dev, req, 0);
- spin_lock_irqsave(&dev->req_lock, flags);
- }
- spin_unlock_irqrestore(&dev->req_lock, flags);*/
- rx_submit(dev, dev->out_req, 0);
- }
- static void tx_complete(struct usb_ep *ep, struct usb_request *req)
- {
- struct eth_dev *dev = ep->driver_data;
- struct eth_event ev;
- ev.type = USB_ETH_EVENT_USB_DATA_TX;
- ev.priv = (void*)req;
- xQueueSendFromISR(dev->usb_ether_event_queue, &ev, 0);
- }
- static void rx_complete(struct usb_ep *ep, struct usb_request *req)
- {
- struct eth_event ev;
- struct eth_dev *dev = ep->driver_data;
- if (req)
- //printf("%s:%d req->actual:%d\r\n", __func__, __LINE__, req->actual);
- ev.type = USB_ETH_EVENT_USB_DATA_RX;
- ev.priv = (void*)req;
- if (!xPortIsInInterrupt())
- xQueueSend(dev->usb_ether_event_queue, &ev, 0);
- else
- xQueueSendFromISR(dev->usb_ether_event_queue, &ev, 0);
- }
- static inline int is_promisc(u16 cdc_filter)
- {
- return cdc_filter & USB_CDC_PACKET_TYPE_PROMISCUOUS;
- }
- static int rx_submit(struct eth_dev *dev, struct usb_request *req, gfp_t gfp_flags)
- {
- int retval = -ENOMEM;
- size_t size = 0;
- struct usb_ep *out;
- unsigned long flags;
- void *buf = NULL;
- spin_lock_irqsave(&dev->lock, flags);
- if (dev->port_usb)
- out = dev->port_usb->out_ep;
- else
- out = NULL;
- spin_unlock_irqrestore(&dev->lock, flags);
- if (!out)
- return -ENOTCONN;
- size += ETH_ALEN + ipconfigNETWORK_MTU + RX_EXTRA;
- size += dev->port_usb->header_len;
- if (out->maxpacket <= 0) {
- printf("maxpacket err\r\n");
- }
- size += out->maxpacket - 1;
- size -= size % out->maxpacket;
- if (dev->port_usb->is_fixed)
- size = max_t(size_t, size, dev->port_usb->fixed_out_len);
- buf = req->buf;
- if (NULL == req->buf || req->length < size) {
- if (NULL != req->buf)
- vPortFree(req->buf);
- buf = pvPortMalloc(size);
- if (buf == NULL) {
- return -ENOMEM;
- }
- }
- //memset(req->buf, 0, req->length);
- req->buf = buf;
- req->length = size;
- req->complete = rx_complete;
- req->context = NULL;
- retval = usb_ep_queue(out, req, 0);
- if (retval) {
- printf("rx submit failed--> %d\r\n", retval);
- /*spin_lock_irqsave(&dev->req_lock, flags);
- list_add_tail(&req->list, &dev->rx_reqs);
- spin_unlock_irqrestore(&dev->req_lock, flags);*/
- }
- return retval;
- }
- int usb_data_rx_proc(struct eth_dev* dev, struct usb_request *req)
- {
- int ret = -1;
- if (!dev->port_usb->connected) {
- printf("%s:%d usb is disconnected\r\n", __func__, __LINE__);
- return -1;
- }
- if (req->status != 0) {
- usb_ep_queue(dev->port_usb->out_ep, req, 0);
- return -1;
- }
- if (dev->port_usb && dev->port_usb->unwrap) {
- #if !USE_LWIP
- dev->port_usb->unwrap(dev->port_usb, req->buf, req->actual, &dev->rx_frames);
- #else
- dev->port_usb->unwrap(dev->port_usb, req->buf, req->actual, (List_t *)&dev->rx_frames);
- #endif
- }
- if (dev->port_usb->connected) {
- #if !USE_LWIP
- NetworkBufferDescriptor_t* pxBufferDescriptor = NULL;
- IPStackEvent_t xRxEvent;
- ListItem_t *pxListItem, *pxListItem1;
- list_for_each_entry_safe(pxListItem, pxListItem1, pxBufferDescriptor, &dev->rx_frames) {
- list_del_init(&pxBufferDescriptor->xBufferListItem);
- xRxEvent.eEventType = eNetworkRxEvent;
- xRxEvent.pvData = ( void * ) pxBufferDescriptor;
- if (0) {
- int i, dump_len = pxBufferDescriptor->xDataLength;
- printf("recv len:%d\r\n", dump_len);
- for (i = 0; i < dump_len; i++) {
- printf("%02x ", pxBufferDescriptor->pucEthernetBuffer[i]);
- if ((i + 1) % 16 == 0)
- printf("\r\n");
- }printf("\r\n");
- }
- if( xSendEventStructToIPTask( &xRxEvent, 0 ) == pdFALSE ) {
- vReleaseNetworkBufferAndDescriptor( pxBufferDescriptor );
- iptraceETHERNET_RX_EVENT_LOST();
- } else {
- iptraceNETWORK_INTERFACE_RECEIVE();
- }
- }
- #else
- if (dev->rx_frames.next) {
- struct pbuf *header = dev->rx_frames.next;
- while(header != NULL) {
- struct pbuf *current = header;
- header = header->next;
- current->next = NULL;
- ncm_ethernetif_input(ncm_netif, current);
- }
- dev->rx_frames.next = NULL;
- }
- #endif
- }
- if (req) {
- ret = rx_submit(dev, req, 0);
- if (ret != 0) {
- rx_fill(dev, 0);
- }
- }
- return 0;
- }
- void usb_data_tx_proc(struct eth_dev* dev, struct usb_request *req)
- {
- if (1) {
- #if !USE_LWIP
- NetworkBufferDescriptor_t *pxBufferDescriptor = (NetworkBufferDescriptor_t *)req->context;
- if (pxBufferDescriptor) {
- if (pxBufferDescriptor->pucEthernetBuffer) {
- vPortFree(pxBufferDescriptor->pucEthernetBuffer);
- pxBufferDescriptor->pucEthernetBuffer = NULL;
- }
- vReleaseNetworkBufferAndDescriptor(pxBufferDescriptor);
- }
- #else
- struct pbuf* pxBufferDescriptor = (struct pbuf*)req->context;//the buf is alloc by ncm, it must be freed.
- if (pxBufferDescriptor) {
- pbuf_free(pxBufferDescriptor);
- }
- #endif
- }
- spin_lock(&dev->req_lock);
- if ((dev->port_usb == NULL || !dev->port_usb->connected)
- && dev->gadget && dev->gadget->ep0) {
- req->buf = NULL;
- req->length = 0;
- usb_ep_free_request(dev->gadget->ep0, req);
- printf("%s #############.\n", __func__);
- } else {
- list_add_tail(&req->list, &dev->tx_reqs);
- }
- spin_unlock(&dev->req_lock);
- }
- static void free_net_buffer(void* desc_handle)
- {
- #if !USE_LWIP
- NetworkBufferDescriptor_t *pxBufferDescriptor = (NetworkBufferDescriptor_t*)desc_handle;
- if (NULL != pxBufferDescriptor)
- vReleaseNetworkBufferAndDescriptor(pxBufferDescriptor);
- #else
- struct pbuf* pxBufferDescriptor = (struct pbuf*)desc_handle;
- if (pxBufferDescriptor) {
- pbuf_free(pxBufferDescriptor);
- }
- #endif
- }
- int net_data_tx_proc(struct eth_dev* dev, void *pxBufferDescriptorHandle)
- {
- int length = 0;
- int retval;
- struct usb_request *req = NULL;
- unsigned long flags;
- struct usb_ep *in;
- u16 cdc_filter;
- #if !USE_LWIP
- NetworkBufferDescriptor_t *pxBufferDescriptor = (NetworkBufferDescriptor_t*)pxBufferDescriptorHandle;
- #else
- struct pbuf* pxBufferDescriptor = (struct pbuf*)pxBufferDescriptorHandle;
- #endif
- spin_lock_irqsave(&dev->lock, flags);
- if (dev->port_usb) {
- in = dev->port_usb->in_ep;
- cdc_filter = dev->port_usb->cdc_filter;
- } else {
- in = NULL;
- cdc_filter = 0;
- }
- spin_unlock_irqrestore(&dev->lock, flags);
- if (!in || !dev->port_usb->connected) {
- free_net_buffer((void*)pxBufferDescriptor);
- return 0;
- }
- /* apply outgoing CDC or RNDIS filters */
- if (!is_promisc(cdc_filter)) {
- #if !USE_LWIP
- u8 *dest = pxBufferDescriptor->pucEthernetBuffer;
- #else
- u8 *dest = pxBufferDescriptor->payload;
- #endif
- if (is_multicast_ether_addr(dest)) {
- u16 type;
- /* ignores USB_CDC_PACKET_TYPE_MULTICAST and host
- * SET_ETHERNET_MULTICAST_FILTERS requests
- */
- if (is_broadcast_ether_addr(dest))
- type = USB_CDC_PACKET_TYPE_BROADCAST;
- else
- type = USB_CDC_PACKET_TYPE_ALL_MULTICAST;
- if (!(cdc_filter & type)) {
- free_net_buffer((void*)pxBufferDescriptor);
- return 0;
- }
- }
- /* ignores USB_CDC_PACKET_TYPE_DIRECTED */
- }
- spin_lock_irqsave(&dev->req_lock, flags);
- /*
- * this freelist can be empty if an interrupt triggered disconnect()
- * and reconfigured the gadget (shutting down this queue) after the
- * network stack decided to xmit but before we got the spinlock.
- */
- if (list_empty(&dev->tx_reqs)) {
- spin_unlock_irqrestore(&dev->req_lock, flags);
- printf("tx reqs empty\r\n");
- free_net_buffer((void*)pxBufferDescriptor);
- if (dev->tx_err_count++ > 3) {
- usb_dwc2_reset(0, 1);
- dev->tx_err_count = 0;
- }
- return -1;
- }
- dev->tx_err_count = 0;
- req = listGET_LIST_ITEM_OWNER(listGET_HEAD_ENTRY(&dev->tx_reqs));
- list_del(&req->list);
- /* temporarily stop TX queue when the freelist empties */
- if (list_empty(&dev->tx_reqs)) {
- }
- spin_unlock_irqrestore(&dev->req_lock, flags);
- /* no buffer copies needed, unless the network stack did it
- * or the hardware can't use skb buffers.
- * or there's not enough space for extra headers we need
- */
- #if !USE_LWIP
- spin_lock_irqsave(&dev->lock, flags);
- if (dev->port_usb && dev->port_usb->wrap)
- pxBufferDescriptor = dev->port_usb->wrap(dev->port_usb, pxBufferDescriptor);
- spin_unlock_irqrestore(&dev->lock, flags);
- if (!pxBufferDescriptor)
- goto drop;
- length = pxBufferDescriptor->xDataLength;
- req->buf = pxBufferDescriptor->pucEthernetBuffer;
- req->context = pxBufferDescriptor;
- req->complete = tx_complete;
- #else
- spin_lock_irqsave(&dev->lock, flags);
- if (dev->port_usb && dev->port_usb->wrap_ext)
- pxBufferDescriptor = (struct pbuf*)dev->port_usb->wrap_ext(dev->port_usb, (void*)pxBufferDescriptor);
- spin_unlock_irqrestore(&dev->lock, flags);
- if (!pxBufferDescriptor)
- goto drop;
- length = pxBufferDescriptor->len;
- req->buf = pxBufferDescriptor->payload;
- req->context = pxBufferDescriptor;
- req->complete = tx_complete;
- #endif
- /* NCM requires no zlp if transfer is dwNtbInMaxSize */
- if (dev->port_usb->is_fixed &&
- length == dev->port_usb->fixed_in_len &&
- (length % in->maxpacket) == 0)
- req->zero = 0;
- else
- req->zero = 1;
- /* use zlp framing on tx for strict CDC-Ether conformance,
- * though any robust network rx path ignores extra padding.
- * and some hardware doesn't like to write zlps.
- */
- if (req->zero && !dev->zlp && (length % in->maxpacket) == 0)
- length++;
- req->length = length;
- retval = usb_ep_queue(in, req, GFP_ATOMIC);
- switch (retval) {
- default:
- DBG(dev, "tx queue err %d\n", retval);
- break;
- case 0:
- atomic_inc(&dev->tx_qlen);
- }
- if (retval) {
- #if !USE_LWIP
- pxBufferDescriptor = (NetworkBufferDescriptor_t *)req->context;
- if (pxBufferDescriptor) {
- if (pxBufferDescriptor->pucEthernetBuffer) {
- vPortFree(pxBufferDescriptor->pucEthernetBuffer);
- pxBufferDescriptor->pucEthernetBuffer = NULL;
- }
- vReleaseNetworkBufferAndDescriptor(pxBufferDescriptor);
- }
- #else
- pxBufferDescriptor = (struct pbuf*)req->context;
- if (pxBufferDescriptor) {
- pbuf_free(pxBufferDescriptor);
- }
- #endif
- drop:
- spin_lock_irqsave(&dev->req_lock, flags);
- list_add_tail(&req->list, &dev->tx_reqs);
- spin_unlock_irqrestore(&dev->req_lock, flags);
- }
- return 0;
- }
- static void usb_ether_task_proc(void* arg)
- {
- struct eth_event ev;
- struct eth_dev *dev = (struct eth_dev *)arg;
- while(dev->start) {
- ev.type = -1;
- if (xQueueReceive(dev->usb_ether_event_queue, &ev, portMAX_DELAY) != pdPASS) {
- printf("%s xQueueReceive err!\r\n", __func__);
- continue;
- }
- if (ev.type == -1)
- continue;
- switch(ev.type) {
- case USB_ETH_EVENT_USB_DATA_RX:
- if (NULL != ev.priv)
- usb_data_rx_proc(dev, (struct usb_request *)ev.priv);
- break;
- case USB_ETH_EVENT_USB_DATA_TX:
- if (NULL != ev.priv)
- usb_data_tx_proc(dev, (struct usb_request *)ev.priv);
- break;
- case USB_ETH_EVENT_NET_DATA_TX:
- if (NULL != ev.priv)
- net_data_tx_proc(dev, ev.priv);
- break;
- case USB_ETH_EVENT_USB_DISCONNECT:
- if (NULL != ev.priv)
- ether_disconnect((struct gether *)ev.priv);
- break;
- case USB_ETH_EVENT_USB_CONNECT:
- if (NULL != ev.priv)
- ether_connect(dev, (struct gether *)ev.priv);
- break;
- default:
- break;
- }
- }
- vTaskDelete(NULL);
- }
- /**
- * gether_setup - initialize one ethernet-over-usb link
- * @g: gadget to associated with these links
- * @ethaddr: NULL, or a buffer in which the ethernet address of the
- * host side of the link is recorded
- * Context: may sleep
- *
- * This sets up the single network link that may be exported by a
- * gadget driver using this framework. The link layer addresses are
- * set up using module parameters.
- *
- * Returns negative errno, or zero on success
- */
- #if 0
- UBaseType_t uxRand( void );
- static void random_ether_addr(u8 *addr)
- {
- UBaseType_t val = uxRand();
- if (NULL == addr)
- return;
- addr [0] = ((val >> 0) & 0xff);
- addr [1] = ((val >> 8) & 0xff);
- addr [2] = ((val >> 16) & 0xff);
- addr [3] = ((val >> 24) & 0xff);
- val = uxRand();
- addr [4] = ((val >> 0) & 0xff);
- addr [5] = ((val >> 8) & 0xff);
- addr [0] &= 0xfe; /* clear multicast bit */
- addr [0] |= 0x02; /* set local assignment bit (IEEE802) */
- }
- #endif
- int gether_setup(struct usb_gadget *g, u8 ethaddr[ETH_ALEN])
- {
- struct eth_dev *dev;
- BaseType_t ret = pdFAIL;
- if (the_dev)
- return -EBUSY;
- dev = pvPortMalloc(sizeof(struct eth_dev));
- if (dev == NULL)
- return -ENOMEM;
- memset((void*)dev, 0, sizeof(struct eth_dev));
- spin_lock_init(&dev->lock);
- spin_lock_init(&dev->req_lock);
- INIT_LIST_HEAD(&dev->tx_reqs);
- //INIT_LIST_HEAD(&dev->rx_reqs);
- #if !USE_LWIP
- INIT_LIST_HEAD(&dev->rx_frames);
- #else
- dev->rx_frames.next = NULL;
- dev->rx_frames.len = 0;
- dev->rx_frames.tot_len = 0;
- #endif
- #if 1
- dev->host_mac[0] = 0x00;//00:0c:29:53:02:09
- dev->host_mac[1] = 0x0c;
- dev->host_mac[2] = 0x29;
- dev->host_mac[3] = 0x53;
- dev->host_mac[4] = 0x02;
- dev->host_mac[5] = 0x09;
- #else
- random_ether_addr(dev->host_mac);
- #endif
- //FreeRTOS_UpdateMACAddress(dev->host_mac);
- printf("\r\nncm mac: %02x %02x %02x %02x %02x %02x\r\n", dev->host_mac[0], dev->host_mac[1],
- dev->host_mac[2], dev->host_mac[3], dev->host_mac[4], dev->host_mac[5]);
- if (ethaddr)
- memcpy(ethaddr, dev->host_mac, ETH_ALEN);
- dev->usb_ether_event_queue = xQueueCreate(16, sizeof(struct eth_event));
- if (NULL == dev->usb_ether_event_queue) {
- goto exit;
- }
- dev->start = 1;
- ret = xTaskCreate(usb_ether_task_proc, "usb_ether_task", 2048, (void*)dev, configMAX_PRIORITIES - 3, &dev->usb_ether_task);
- if (ret != pdPASS) {
- goto exit;
- }
- dev->gadget = g;
- the_dev = dev;
- return 0;
- exit:
- if (ret != pdPASS) {
- if (dev) {
- if (dev->usb_ether_event_queue) {
- vQueueDelete(dev->usb_ether_event_queue);
- }
- vPortFree(dev);
- }
- }
- return -1;
- }
- /**
- * gether_cleanup - remove Ethernet-over-USB device
- * Context: may sleep
- *
- * This is called to free all resources allocated by @gether_setup().
- */
- void gether_cleanup(void)
- {
- struct eth_event ev;
- struct eth_dev *dev = the_dev;
- if (!dev)
- return;
- dev->start = 0;
- if (dev->usb_ether_event_queue) {
- ev.type = -1;
- xQueueSend(dev->usb_ether_event_queue, &ev, 0);
- vQueueDelete(dev->usb_ether_event_queue);
- }//maybe exist bug
- vPortFree(dev);
- the_dev = NULL;
- }
- static int ether_connect(struct eth_dev *dev, struct gether *link)
- {
- int result = 0;
- if (!dev)
- return -EINVAL;
- dev->tx_err_count = 0;
- if (link && link->connected)
- return 0;
- link->in_ep->driver_data = dev;
- result = usb_ep_enable(link->in_ep, link->in);
- if (result != 0) {
- DBG(dev, "enable %s --> %d\n",
- link->in_ep->name, result);
- goto fail0;
- }
- link->out_ep->driver_data = dev;
- result = usb_ep_enable(link->out_ep, link->out);
- if (result != 0) {
- DBG(dev, "enable %s --> %d\n",
- link->out_ep->name, result);
- goto fail1;
- }
- if (result == 0) {
- result = alloc_requests(dev, link, qlen(dev->gadget));
- dev->out_req = NULL;
- dev->out_req = usb_ep_alloc_request(link->out_ep, GFP_ATOMIC);
- if (!dev->out_req) {
- printf("usb_ep_alloc_request %s --> %d\r\n",
- link->out_ep->name, result);
- goto fail1;
- }
- dev->out_req->buf = NULL;
- dev->out_req->length = 0;
- }
- if (result == 0 && dev->out_req) {
- dev->zlp = link->is_zlp_ok;
- DBG(dev, "qlen %d\n", qlen(dev->gadget));
- dev->header_len = link->header_len;
- spin_lock(&dev->lock);
- dev->port_usb = link;
- link->ctx = (void *)dev;
- spin_unlock(&dev->lock);
- rx_fill(dev, 0);
- atomic_set(&dev->tx_qlen, 0);
- link->connected = true;
- /* on error, disable any endpoints */
- } else {
- (void) usb_ep_disable(link->out_ep);
- fail1:
- (void) usb_ep_disable(link->in_ep);
- }
- fail0:
- /* caller is responsible for cleanup on error */
- if (result < 0)
- return result;
- return result;
- }
- /**
- * gether_disconnect - notify network layer that USB link is inactive
- * @link: the USB link, on which gether_connect() was called
- * Context: irqs blocked
- *
- * This is called to deactivate endpoints and let the network layer know
- * the connection went inactive ("no carrier").
- *
- * On return, the state is as if gether_connect() had never been called.
- * The endpoints are inactive, and accordingly without active USB I/O.
- * Pointers to endpoint descriptors and endpoint private data are nulled.
- */
- static void ether_disconnect(struct gether *link)
- {
- struct eth_dev *dev = (struct eth_dev *)link->ctx;
- struct usb_request *req;
- if (!dev || !link->connected)
- return;
- dev->tx_err_count = 0;
- link->connected = false;
- printf("%s:%d start\r\n", __func__, __LINE__);
- usb_ep_disable(link->in_ep);
- spin_lock(&dev->req_lock);
- while (!list_empty(&dev->tx_reqs)) {
- req = listGET_LIST_ITEM_OWNER(listGET_HEAD_ENTRY(&dev->tx_reqs));
- list_del(&req->list);
- spin_unlock(&dev->req_lock);
- req->buf = NULL;
- req->length = 0;
- usb_ep_free_request(link->in_ep, req);
- printf("req:%x is released at disconnect\n", req);
- spin_lock(&dev->req_lock);
- }
- spin_unlock(&dev->req_lock);
- link->in_ep->driver_data = NULL;
- link->in_ep->desc = NULL;
- usb_ep_disable(link->out_ep);
- spin_lock(&dev->req_lock);
- #if !USE_LWIP
- while (!list_empty(&dev->rx_frames)) {
- NetworkBufferDescriptor_t * pxNetworkBuffer = listGET_LIST_ITEM_OWNER(listGET_HEAD_ENTRY(&dev->rx_frames));
- list_del_init(&pxNetworkBuffer->xBufferListItem);
- vReleaseNetworkBufferAndDescriptor(pxNetworkBuffer);
- }
- #else
- if (dev->rx_frames.next) {
- struct pbuf *header = dev->rx_frames.next;
- while(header != NULL) {
- struct pbuf *current = header;
- header = header->next;
- pbuf_free(current);
- }
- dev->rx_frames.next = NULL;
- }
- #endif
- req = dev->out_req;
- if (req && req->buf) {
- vPortFree(req->buf);
- req->buf = NULL;
- req->length = 0;
- }
- usb_ep_free_request(link->out_ep, dev->out_req);
- spin_unlock(&dev->req_lock);
- link->out_ep->driver_data = NULL;
- link->out_ep->desc = NULL;
- /* finish forgetting about this USB link episode */
- dev->header_len = 0;
- spin_lock(&dev->lock);
- dev->port_usb = NULL;
- spin_unlock(&dev->lock);
- if (link && link->disconnect_cb)
- link->disconnect_cb(link);
- printf("%s:%d end\r\n", __func__, __LINE__);
- }
- int gether_connect(struct gether *link)
- {
- struct eth_event ev;
- struct eth_dev *dev = the_dev;
- if (dev && dev->usb_ether_event_queue) {
- ev.type = USB_ETH_EVENT_USB_CONNECT;
- ev.priv = (void*)link;
- if (!xPortIsInInterrupt())
- xQueueSend(dev->usb_ether_event_queue, &ev, 0);
- else
- xQueueSendFromISR(dev->usb_ether_event_queue, &ev, 0);
- }
- return 0;
- }
- void gether_disconnect(struct gether *link)
- {
- struct eth_event ev;
- struct eth_dev *dev = (struct eth_dev *)link->ctx;
- if (dev && dev->usb_ether_event_queue) {
- ev.type = USB_ETH_EVENT_USB_DISCONNECT;
- ev.priv = (void*)link;
- if (!xPortIsInInterrupt())
- xQueueSend(dev->usb_ether_event_queue, &ev, 0);
- else
- xQueueSendFromISR(dev->usb_ether_event_queue, &ev, 0);
- }
- }
- void gether_send(NetworkBufferDescriptor_t * const pxDescriptor)
- {
- struct eth_event ev;
- struct eth_dev *dev = the_dev;
- if (dev && dev->usb_ether_event_queue) {
- ev.type = USB_ETH_EVENT_NET_DATA_TX;
- ev.priv = (void*)pxDescriptor;
- xQueueSend(dev->usb_ether_event_queue, &ev, 0);
- } else {
- #if !USE_LWIP
- vReleaseNetworkBufferAndDescriptor( pxDescriptor );
- #endif
- }
- }
- void gether_send_ext(void * const pxDescriptor)
- {
- struct eth_event ev;
- struct eth_dev *dev = the_dev;
- if (dev && dev->usb_ether_event_queue) {
- ev.type = USB_ETH_EVENT_NET_DATA_TX;
- ev.priv = (void*)pxDescriptor;
- xQueueSend(dev->usb_ether_event_queue, &ev, 0);
- } else {
- #if !USE_LWIP
- vReleaseNetworkBufferAndDescriptor( pxDescriptor );
- #endif
- }
- }
|