CDC/ECM driver for mbed, based on USBDevice by mbed-official. Uses PicoTCP to access Ethernet USB device. License: GPLv2
Fork of USB_Ethernet by
stack/pico_frame.c@2:540f6e142d59, 2013-08-03 (annotated)
- Committer:
- daniele
- Date:
- Sat Aug 03 13:16:14 2013 +0000
- Revision:
- 2:540f6e142d59
Moved to single package
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
daniele | 2:540f6e142d59 | 1 | /********************************************************************* |
daniele | 2:540f6e142d59 | 2 | PicoTCP. Copyright (c) 2012 TASS Belgium NV. Some rights reserved. |
daniele | 2:540f6e142d59 | 3 | See LICENSE and COPYING for usage. |
daniele | 2:540f6e142d59 | 4 | |
daniele | 2:540f6e142d59 | 5 | . |
daniele | 2:540f6e142d59 | 6 | |
daniele | 2:540f6e142d59 | 7 | Authors: Daniele Lacamera |
daniele | 2:540f6e142d59 | 8 | *********************************************************************/ |
daniele | 2:540f6e142d59 | 9 | |
daniele | 2:540f6e142d59 | 10 | |
daniele | 2:540f6e142d59 | 11 | #include "pico_config.h" |
daniele | 2:540f6e142d59 | 12 | #include "pico_frame.h" |
daniele | 2:540f6e142d59 | 13 | |
daniele | 2:540f6e142d59 | 14 | #ifdef PICO_SUPPORT_DEBUG_MEMORY |
daniele | 2:540f6e142d59 | 15 | static int n_frames_allocated; |
daniele | 2:540f6e142d59 | 16 | #endif |
daniele | 2:540f6e142d59 | 17 | |
daniele | 2:540f6e142d59 | 18 | /** frame alloc/dealloc/copy **/ |
daniele | 2:540f6e142d59 | 19 | void pico_frame_discard(struct pico_frame *f) |
daniele | 2:540f6e142d59 | 20 | { |
daniele | 2:540f6e142d59 | 21 | (*f->usage_count)--; |
daniele | 2:540f6e142d59 | 22 | if (*f->usage_count <= 0) { |
daniele | 2:540f6e142d59 | 23 | pico_free(f->usage_count); |
daniele | 2:540f6e142d59 | 24 | #ifdef PICO_SUPPORT_DEBUG_MEMORY |
daniele | 2:540f6e142d59 | 25 | dbg("Discarded buffer @%p, caller: %p\n", f->buffer, __builtin_return_address(3)); |
daniele | 2:540f6e142d59 | 26 | dbg("DEBUG MEMORY: %d frames in use.\n", --n_frames_allocated); |
daniele | 2:540f6e142d59 | 27 | #endif |
daniele | 2:540f6e142d59 | 28 | pico_free(f->buffer); |
daniele | 2:540f6e142d59 | 29 | if (f->info) |
daniele | 2:540f6e142d59 | 30 | pico_free(f->info); |
daniele | 2:540f6e142d59 | 31 | } |
daniele | 2:540f6e142d59 | 32 | #ifdef PICO_SUPPORT_DEBUG_MEMORY |
daniele | 2:540f6e142d59 | 33 | else { |
daniele | 2:540f6e142d59 | 34 | dbg("Removed frame @%p(copy), usage count now: %d\n", f, *f->usage_count); |
daniele | 2:540f6e142d59 | 35 | } |
daniele | 2:540f6e142d59 | 36 | #endif |
daniele | 2:540f6e142d59 | 37 | pico_free(f); |
daniele | 2:540f6e142d59 | 38 | } |
daniele | 2:540f6e142d59 | 39 | |
daniele | 2:540f6e142d59 | 40 | struct pico_frame *pico_frame_copy(struct pico_frame *f) |
daniele | 2:540f6e142d59 | 41 | { |
daniele | 2:540f6e142d59 | 42 | struct pico_frame *new = pico_zalloc(sizeof(struct pico_frame)); |
daniele | 2:540f6e142d59 | 43 | if (!new) |
daniele | 2:540f6e142d59 | 44 | return NULL; |
daniele | 2:540f6e142d59 | 45 | memcpy(new, f, sizeof(struct pico_frame)); |
daniele | 2:540f6e142d59 | 46 | *(new->usage_count) += 1; |
daniele | 2:540f6e142d59 | 47 | #ifdef PICO_SUPPORT_DEBUG_MEMORY |
daniele | 2:540f6e142d59 | 48 | dbg("Copied frame @%p, into %p, usage count now: %d\n", f, new, *new->usage_count); |
daniele | 2:540f6e142d59 | 49 | #endif |
daniele | 2:540f6e142d59 | 50 | new->next = NULL; |
daniele | 2:540f6e142d59 | 51 | return new; |
daniele | 2:540f6e142d59 | 52 | } |
daniele | 2:540f6e142d59 | 53 | |
daniele | 2:540f6e142d59 | 54 | |
daniele | 2:540f6e142d59 | 55 | struct pico_frame *pico_frame_alloc(int size) |
daniele | 2:540f6e142d59 | 56 | { |
daniele | 2:540f6e142d59 | 57 | struct pico_frame *p = pico_zalloc(sizeof(struct pico_frame)); |
daniele | 2:540f6e142d59 | 58 | if (!p) |
daniele | 2:540f6e142d59 | 59 | return NULL; |
daniele | 2:540f6e142d59 | 60 | p->buffer = pico_zalloc(size); |
daniele | 2:540f6e142d59 | 61 | if (!p->buffer) { |
daniele | 2:540f6e142d59 | 62 | pico_free(p); |
daniele | 2:540f6e142d59 | 63 | return NULL; |
daniele | 2:540f6e142d59 | 64 | } |
daniele | 2:540f6e142d59 | 65 | p->usage_count = pico_zalloc(sizeof(uint32_t)); |
daniele | 2:540f6e142d59 | 66 | if (!p->usage_count) { |
daniele | 2:540f6e142d59 | 67 | pico_free(p->buffer); |
daniele | 2:540f6e142d59 | 68 | pico_free(p); |
daniele | 2:540f6e142d59 | 69 | return NULL; |
daniele | 2:540f6e142d59 | 70 | } |
daniele | 2:540f6e142d59 | 71 | p->buffer_len = size; |
daniele | 2:540f6e142d59 | 72 | |
daniele | 2:540f6e142d59 | 73 | |
daniele | 2:540f6e142d59 | 74 | /* By default, frame content is the full buffer. */ |
daniele | 2:540f6e142d59 | 75 | p->start = p->buffer; |
daniele | 2:540f6e142d59 | 76 | p->len = p->buffer_len; |
daniele | 2:540f6e142d59 | 77 | *p->usage_count = 1; |
daniele | 2:540f6e142d59 | 78 | #ifdef PICO_SUPPORT_DEBUG_MEMORY |
daniele | 2:540f6e142d59 | 79 | dbg("Allocated buffer @%p, len= %d caller: %p\n", p->buffer, p->buffer_len, __builtin_return_address(2)); |
daniele | 2:540f6e142d59 | 80 | dbg("DEBUG MEMORY: %d frames in use.\n", ++n_frames_allocated); |
daniele | 2:540f6e142d59 | 81 | #endif |
daniele | 2:540f6e142d59 | 82 | return p; |
daniele | 2:540f6e142d59 | 83 | } |
daniele | 2:540f6e142d59 | 84 | |
daniele | 2:540f6e142d59 | 85 | struct pico_frame *pico_frame_deepcopy(struct pico_frame *f) |
daniele | 2:540f6e142d59 | 86 | { |
daniele | 2:540f6e142d59 | 87 | struct pico_frame *new = pico_frame_alloc(f->buffer_len); |
daniele | 2:540f6e142d59 | 88 | int addr_diff; |
daniele | 2:540f6e142d59 | 89 | unsigned char *buf; |
daniele | 2:540f6e142d59 | 90 | uint32_t *uc; |
daniele | 2:540f6e142d59 | 91 | if (!new) |
daniele | 2:540f6e142d59 | 92 | return NULL; |
daniele | 2:540f6e142d59 | 93 | |
daniele | 2:540f6e142d59 | 94 | /* Save the two key pointers... */ |
daniele | 2:540f6e142d59 | 95 | buf = new->buffer; |
daniele | 2:540f6e142d59 | 96 | uc = new->usage_count; |
daniele | 2:540f6e142d59 | 97 | |
daniele | 2:540f6e142d59 | 98 | /* Overwrite all fields with originals */ |
daniele | 2:540f6e142d59 | 99 | memcpy(new, f, sizeof(struct pico_frame)); |
daniele | 2:540f6e142d59 | 100 | |
daniele | 2:540f6e142d59 | 101 | /* ...restore the two key pointers */ |
daniele | 2:540f6e142d59 | 102 | new->buffer = buf; |
daniele | 2:540f6e142d59 | 103 | new->usage_count = uc; |
daniele | 2:540f6e142d59 | 104 | |
daniele | 2:540f6e142d59 | 105 | /* Update in-buffer pointers with offset */ |
daniele | 2:540f6e142d59 | 106 | addr_diff = (int)new->buffer - (int)f->buffer; |
daniele | 2:540f6e142d59 | 107 | new->net_hdr += addr_diff; |
daniele | 2:540f6e142d59 | 108 | new->transport_hdr += addr_diff; |
daniele | 2:540f6e142d59 | 109 | new->app_hdr += addr_diff; |
daniele | 2:540f6e142d59 | 110 | new->start += addr_diff; |
daniele | 2:540f6e142d59 | 111 | new->payload += addr_diff; |
daniele | 2:540f6e142d59 | 112 | |
daniele | 2:540f6e142d59 | 113 | #ifdef PICO_SUPPORT_DEBUG_MEMORY |
daniele | 2:540f6e142d59 | 114 | dbg("Deep-Copied frame @%p, into %p, usage count now: %d\n", f, new, *new->usage_count); |
daniele | 2:540f6e142d59 | 115 | #endif |
daniele | 2:540f6e142d59 | 116 | new->next = NULL; |
daniele | 2:540f6e142d59 | 117 | return new; |
daniele | 2:540f6e142d59 | 118 | } |
daniele | 2:540f6e142d59 | 119 | |
daniele | 2:540f6e142d59 | 120 | /** |
daniele | 2:540f6e142d59 | 121 | * Calculate checksum of a given string |
daniele | 2:540f6e142d59 | 122 | */ |
daniele | 2:540f6e142d59 | 123 | uint16_t pico_checksum(void *inbuf, int len) |
daniele | 2:540f6e142d59 | 124 | { |
daniele | 2:540f6e142d59 | 125 | uint8_t *buf = (uint8_t *) inbuf; |
daniele | 2:540f6e142d59 | 126 | uint16_t tmp = 0; |
daniele | 2:540f6e142d59 | 127 | uint32_t sum = 0; |
daniele | 2:540f6e142d59 | 128 | int i = 0; |
daniele | 2:540f6e142d59 | 129 | |
daniele | 2:540f6e142d59 | 130 | for(i=0; i < len; i++) { |
daniele | 2:540f6e142d59 | 131 | if (i%2) { |
daniele | 2:540f6e142d59 | 132 | sum += buf[i]; |
daniele | 2:540f6e142d59 | 133 | } else { |
daniele | 2:540f6e142d59 | 134 | tmp = buf[i]; |
daniele | 2:540f6e142d59 | 135 | sum += (tmp << 8); |
daniele | 2:540f6e142d59 | 136 | } |
daniele | 2:540f6e142d59 | 137 | } |
daniele | 2:540f6e142d59 | 138 | |
daniele | 2:540f6e142d59 | 139 | while (sum >> 16) { /* a second carry is possible! */ |
daniele | 2:540f6e142d59 | 140 | sum = (sum & 0x0000FFFF) + (sum >> 16); |
daniele | 2:540f6e142d59 | 141 | } |
daniele | 2:540f6e142d59 | 142 | return (uint16_t) (~sum); |
daniele | 2:540f6e142d59 | 143 | } |
daniele | 2:540f6e142d59 | 144 | |
daniele | 2:540f6e142d59 | 145 | uint16_t pico_dualbuffer_checksum(void *inbuf1, int len1, void *inbuf2, int len2) |
daniele | 2:540f6e142d59 | 146 | { |
daniele | 2:540f6e142d59 | 147 | uint8_t *b1 = (uint8_t *) inbuf1; |
daniele | 2:540f6e142d59 | 148 | uint8_t *b2 = (uint8_t *) inbuf2; |
daniele | 2:540f6e142d59 | 149 | uint16_t tmp = 0; |
daniele | 2:540f6e142d59 | 150 | uint32_t sum = 0; |
daniele | 2:540f6e142d59 | 151 | int i = 0, j = 0; |
daniele | 2:540f6e142d59 | 152 | |
daniele | 2:540f6e142d59 | 153 | for(i=0; i < len1; i++) { |
daniele | 2:540f6e142d59 | 154 | if (j%2) { |
daniele | 2:540f6e142d59 | 155 | sum += b1[i]; |
daniele | 2:540f6e142d59 | 156 | } else { |
daniele | 2:540f6e142d59 | 157 | tmp = b1[i]; |
daniele | 2:540f6e142d59 | 158 | sum += (tmp << 8); |
daniele | 2:540f6e142d59 | 159 | } |
daniele | 2:540f6e142d59 | 160 | j++; |
daniele | 2:540f6e142d59 | 161 | } |
daniele | 2:540f6e142d59 | 162 | |
daniele | 2:540f6e142d59 | 163 | j = 0; /* j has to be reset if len1 is odd */ |
daniele | 2:540f6e142d59 | 164 | for(i=0; i < len2; i++) { |
daniele | 2:540f6e142d59 | 165 | if (j%2) { |
daniele | 2:540f6e142d59 | 166 | sum += b2[i]; |
daniele | 2:540f6e142d59 | 167 | } else { |
daniele | 2:540f6e142d59 | 168 | tmp = b2[i]; |
daniele | 2:540f6e142d59 | 169 | sum += (tmp << 8); |
daniele | 2:540f6e142d59 | 170 | } |
daniele | 2:540f6e142d59 | 171 | j++; |
daniele | 2:540f6e142d59 | 172 | } |
daniele | 2:540f6e142d59 | 173 | while (sum >> 16) { /* a second carry is possible! */ |
daniele | 2:540f6e142d59 | 174 | sum = (sum & 0x0000FFFF) + (sum >> 16); |
daniele | 2:540f6e142d59 | 175 | } |
daniele | 2:540f6e142d59 | 176 | return (uint16_t) (~sum); |
daniele | 2:540f6e142d59 | 177 | } |
daniele | 2:540f6e142d59 | 178 | |
daniele | 2:540f6e142d59 | 179 | uint16_t pico_dualbuffer_checksum_broken(void *inbuf1, int len1, void *inbuf2, int len2) |
daniele | 2:540f6e142d59 | 180 | { |
daniele | 2:540f6e142d59 | 181 | uint16_t *b1 = (uint16_t *) inbuf1; |
daniele | 2:540f6e142d59 | 182 | uint16_t *b2 = (uint16_t *) inbuf2; |
daniele | 2:540f6e142d59 | 183 | uint32_t sum = 0; |
daniele | 2:540f6e142d59 | 184 | int i=0, j=0; |
daniele | 2:540f6e142d59 | 185 | for(i=0; i<(len1>>1); i++){ |
daniele | 2:540f6e142d59 | 186 | sum += short_be(b1[i]); |
daniele | 2:540f6e142d59 | 187 | j++; |
daniele | 2:540f6e142d59 | 188 | } |
daniele | 2:540f6e142d59 | 189 | for(i=0; i<(len2>>1); i++){ |
daniele | 2:540f6e142d59 | 190 | sum += short_be(b2[i]); |
daniele | 2:540f6e142d59 | 191 | j++; |
daniele | 2:540f6e142d59 | 192 | } |
daniele | 2:540f6e142d59 | 193 | sum = (sum & 0xFFFF) + (sum >> 16); |
daniele | 2:540f6e142d59 | 194 | sum += (sum >> 16); |
daniele | 2:540f6e142d59 | 195 | |
daniele | 2:540f6e142d59 | 196 | // Take the bitwise complement of sum |
daniele | 2:540f6e142d59 | 197 | sum = ~sum; |
daniele | 2:540f6e142d59 | 198 | return (uint16_t) (sum) ; |
daniele | 2:540f6e142d59 | 199 | } |
daniele | 2:540f6e142d59 | 200 | |
daniele | 2:540f6e142d59 | 201 |