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

stack/pico_frame.c

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.

.

Authors: Daniele Lacamera
*********************************************************************/


#include "pico_config.h"
#include "pico_frame.h"

#ifdef PICO_SUPPORT_DEBUG_MEMORY
static int n_frames_allocated;
#endif

/** frame alloc/dealloc/copy **/
void pico_frame_discard(struct pico_frame *f)
{
  (*f->usage_count)--;
  if (*f->usage_count <= 0) {
    pico_free(f->usage_count);
#ifdef PICO_SUPPORT_DEBUG_MEMORY
    dbg("Discarded buffer @%p, caller: %p\n", f->buffer, __builtin_return_address(3));
    dbg("DEBUG MEMORY: %d frames in use.\n", --n_frames_allocated);
#endif
    pico_free(f->buffer);
    if (f->info)
      pico_free(f->info);
  }
#ifdef PICO_SUPPORT_DEBUG_MEMORY
  else {
    dbg("Removed frame @%p(copy), usage count now: %d\n", f, *f->usage_count);
  }
#endif
  pico_free(f);
}

struct pico_frame *pico_frame_copy(struct pico_frame *f)
{
  struct pico_frame *new = pico_zalloc(sizeof(struct pico_frame));
  if (!new)
    return NULL;
  memcpy(new, f, sizeof(struct pico_frame));
  *(new->usage_count) += 1;
#ifdef PICO_SUPPORT_DEBUG_MEMORY
  dbg("Copied frame @%p, into %p, usage count now: %d\n", f, new, *new->usage_count);
#endif
  new->next = NULL;
  return new;
}


struct pico_frame *pico_frame_alloc(int size)
{
  struct pico_frame *p = pico_zalloc(sizeof(struct pico_frame));
  if (!p)
    return NULL;
  p->buffer = pico_zalloc(size);
  if (!p->buffer) {
    pico_free(p);
    return NULL;
  }
  p->usage_count = pico_zalloc(sizeof(uint32_t));
  if (!p->usage_count) {
    pico_free(p->buffer);
    pico_free(p);
    return NULL;
  }
  p->buffer_len = size;


  /* By default, frame content is the full buffer. */
  p->start = p->buffer;
  p->len = p->buffer_len;
  *p->usage_count = 1;
#ifdef PICO_SUPPORT_DEBUG_MEMORY
    dbg("Allocated buffer @%p, len= %d caller: %p\n", p->buffer, p->buffer_len, __builtin_return_address(2));
    dbg("DEBUG MEMORY: %d frames in use.\n", ++n_frames_allocated);
#endif
  return p;
}

struct pico_frame *pico_frame_deepcopy(struct pico_frame *f)
{
  struct pico_frame *new = pico_frame_alloc(f->buffer_len);
  int addr_diff;
  unsigned char *buf;
  uint32_t *uc;
  if (!new)
    return NULL;

  /* Save the two key pointers... */
  buf = new->buffer;
  uc  = new->usage_count;

  /* Overwrite all fields with originals */
  memcpy(new, f, sizeof(struct pico_frame));

  /* ...restore the two key pointers */
  new->buffer = buf;
  new->usage_count = uc;

  /* Update in-buffer pointers with offset */
  addr_diff = (int)new->buffer - (int)f->buffer;
  new->net_hdr += addr_diff;
  new->transport_hdr += addr_diff;
  new->app_hdr += addr_diff;
  new->start += addr_diff;
  new->payload += addr_diff;

#ifdef PICO_SUPPORT_DEBUG_MEMORY
  dbg("Deep-Copied frame @%p, into %p, usage count now: %d\n", f, new, *new->usage_count);
#endif
  new->next = NULL;
  return new;
}

/**
 * Calculate checksum of a given string
 */
uint16_t pico_checksum(void *inbuf, int len)
{
  uint8_t *buf = (uint8_t *) inbuf;
  uint16_t tmp = 0;
  uint32_t sum = 0;
  int i = 0;

  for(i=0; i < len; i++) {
    if (i%2) {
      sum += buf[i];
    } else {
      tmp = buf[i];
      sum += (tmp << 8);
    }
  }

  while (sum >> 16) { /* a second carry is possible! */
    sum = (sum & 0x0000FFFF) + (sum >> 16);
  } 
  return (uint16_t) (~sum);
}

uint16_t pico_dualbuffer_checksum(void *inbuf1, int len1, void *inbuf2, int len2)
{
  uint8_t *b1 = (uint8_t *) inbuf1;
  uint8_t *b2 = (uint8_t *) inbuf2;
  uint16_t tmp = 0;
  uint32_t sum = 0;
  int i = 0, j = 0;

  for(i=0; i < len1; i++) {
    if (j%2) {
      sum += b1[i];
    } else {
      tmp = b1[i];
      sum += (tmp << 8);
    }
    j++;
  }

  j = 0; /* j has to be reset if len1 is odd */
  for(i=0; i < len2; i++) {
    if (j%2) {
      sum += b2[i];
    } else {
      tmp = b2[i];
      sum += (tmp << 8);
    }
    j++;
  }
  while (sum >> 16) { /* a second carry is possible! */
    sum = (sum & 0x0000FFFF) + (sum >> 16);
  } 
  return (uint16_t) (~sum);
}

uint16_t pico_dualbuffer_checksum_broken(void *inbuf1, int len1, void *inbuf2, int len2)
{
  uint16_t *b1 = (uint16_t *) inbuf1;
  uint16_t *b2 = (uint16_t *) inbuf2;
  uint32_t sum = 0;
  int i=0, j=0;
  for(i=0; i<(len1>>1); i++){
    sum += short_be(b1[i]);
    j++;
  }
  for(i=0; i<(len2>>1); i++){
    sum += short_be(b2[i]);
    j++;
  }
  sum = (sum & 0xFFFF) + (sum >> 16);
  sum += (sum >> 16);
  
  // Take the bitwise complement of sum
  sum = ~sum;
  return (uint16_t) (sum)  ;
}