CDC/ECM driver for mbed, based on USBDevice by mbed-official. Uses PicoTCP to access Ethernet USB device. License: GPLv2

Dependents:   USBEthernet_TEST

Fork of USB_Ethernet by Daniele Lacamera

modules/pico_dev_mbed_usb.cpp

Committer:
daniele
Date:
2013-08-03
Revision:
2:540f6e142d59

File content as of revision 2:540f6e142d59:

/*********************************************************************
PicoTCP. Copyright (c) 2012 TASS Belgium NV. Some rights reserved.
See LICENSE and COPYING for usage.
Do not redistribute without a written permission by the Copyright
holders.

Authors: Daniele Lacamera, Julien Duraj
*********************************************************************/
#include "mbed.h"
#include "USBCDC_ECM.h"
#include "ethernet_api.h"
#include "pico_dev_mbed_usb.h"

extern "C" {
#include "pico_device.h"
#include "pico_stack.h"
}

struct pico_device_mbed_usb {
  struct pico_device dev;
  int bytes_left_in_frame;
  USBCDC_ECM *ecm;
};

#define ETH_MTU 1514
static uint8_t buf[ETH_MTU];
static int rx_i = 0;

Serial __pc(p9, p10, "Serial port"); // tx, rx

extern "C" {

static int pico_mbed_usb_send(struct pico_device *dev, void *buffer, int len)
{
  int ret, sent = 0;
  struct pico_device_mbed_usb *mb = (struct pico_device_mbed_usb *) dev;

  //printf("USBETH> sending %d bytes\n", len);
  if (len > ETH_MTU)
    return -1;
  while (sent < len) {
    int to_send = 64;
    if ((len - sent) < to_send) 
        to_send = len -sent;
    ret = mb->ecm->send(((uint8_t *)buffer) + sent, to_send);
    if (!ret)
        return -1;
    sent += to_send;
  }
  if ((len % 64) == 0) {
    mb->ecm->send(((uint8_t *)buffer), 0);
  }
  //printf("USBETH> Sent %d bytes.\n", sent);
  return sent;
}

static int pico_mbed_usb_poll(struct pico_device *dev, int loop_score)
{
  int size;
  struct pico_device_mbed_usb *mb = (struct pico_device_mbed_usb *) dev;
  
  while(loop_score > 0)
  {
    bool ret;
    /* check for new frame(s) */
    ret = mb->ecm->readEP_NB(buf + rx_i, (uint32_t *)&size);
    
    /* return if no frame has arrived */
    if (!ret)
      return loop_score;
      
    rx_i += size;
    if (size < 64) {
        /* read and process frame */
        pico_stack_recv(dev, buf, rx_i);
        loop_score--;
        rx_i = 0;
    }
  }
  return loop_score;
}

/* Public interface: create/destroy. */
void pico_mbed_usb_destroy(struct pico_device *dev)
{
  pico_device_destroy(dev);
}

struct pico_device *pico_mbed_usb_create(char *name, USBCDC_ECM *ecm)
{
  std::uint8_t mac[PICO_SIZE_ETH] = {0x00, 0x01, 0xaa, 0x00, 0x02, 0xbb};
  struct pico_device_mbed_usb *mb = (struct pico_device_mbed_usb*) pico_zalloc(sizeof(struct pico_device_mbed_usb));

  if (!mb)
    return NULL;

  if(0 != pico_device_init((struct pico_device *)mb, name, mac)) {
    __pc.printf ("ETH> Loop init failed.\n");
    //pico_loop_destroy(mb);
    return NULL;
  }
  mb->ecm = ecm;
  mb->dev.send = pico_mbed_usb_send;
  mb->dev.poll = pico_mbed_usb_poll;
  mb->dev.destroy = pico_mbed_usb_destroy;
  mb->bytes_left_in_frame = 0;

  if(0 != ethernet_init()) {
    __pc.printf("ETH> Failed to initialize hardware.\r\n");
    pico_device_destroy((struct pico_device *)mb);
    return NULL;
  }

  __pc.printf("ETH> Device %s created.\r\n", mb->dev.name);

  return (struct pico_device *)mb;
}

void pico_mbed_usb_get_address(char *mac)
{
  /* TODO */
}

}