]> oss.titaniummirror.com Git - tinyos-2.x.git/blobdiff - support/sdk/c/blip/libtcp/circ.c
Merge TinyOS 2.1.1 into master.
[tinyos-2.x.git] / support / sdk / c / blip / libtcp / circ.c
diff --git a/support/sdk/c/blip/libtcp/circ.c b/support/sdk/c/blip/libtcp/circ.c
new file mode 100644 (file)
index 0000000..cd91d8e
--- /dev/null
@@ -0,0 +1,147 @@
+/*
+ * "Copyright (c) 2008, 2009 The Regents of the University  of California.
+ * All rights reserved."
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ *
+ * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+ * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+ * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
+ *
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+
+#include "tcplib.h"
+
+struct circ_buf {
+  uint8_t  *data_start;
+  uint8_t  *data_head;
+  uint16_t  data_len;
+  uint32_t  head_seqno;
+};
+
+int circ_buf_init(void *data, int len, uint32_t seqno) {
+  struct circ_buf *b = (struct circ_buf *)data;
+
+  if (len < sizeof(struct circ_buf))
+    return -1;
+
+  b->data_head = b->data_start = (uint8_t *)(b + 1);
+  b->data_len = len - sizeof(struct circ_buf);
+  b->head_seqno = seqno;
+  return 0;
+}
+
+uint32_t circ_get_seqno(void *buf) {
+  struct circ_buf *b = (struct circ_buf *)buf;
+  return b->head_seqno;
+}
+
+static void get_ptr_off_1(struct circ_buf *b, uint32_t sseqno, int len,
+                          uint8_t **writeptr, int *w_len) {
+  uint8_t *endptr =  b->data_start + b->data_len;
+  int offset;
+
+  *writeptr = NULL;
+  *w_len = len;
+
+  /* write up to either the end of the buffer */
+  offset = sseqno - b->head_seqno;
+  if (b->data_head + offset < endptr) {
+    *writeptr = b->data_head + offset;
+  } else {
+    offset -= (endptr - b->data_head);
+    *writeptr = b->data_start + offset;
+  }
+  if (*writeptr + *w_len > endptr) {
+    *w_len = endptr - *writeptr;
+  }
+}
+
+int circ_shorten_head(void *buf, uint32_t seqno) {
+  struct circ_buf *b = (struct circ_buf *)buf;
+  int offset = seqno - b->head_seqno;
+
+  b->head_seqno = seqno;
+  b->data_head += offset;
+
+  while (b->data_head > b->data_start + b->data_len)
+    b->data_head -= b->data_len;
+
+  return 0;
+}
+
+int circ_buf_read(void *buf, uint32_t sseqno,
+                  uint8_t *data, int len) {
+  struct circ_buf *b = (struct circ_buf *)buf;
+  uint8_t *readptr;
+  int r_len, rc = 0;
+
+  get_ptr_off_1(b, sseqno, len, &readptr, &r_len);
+  memcpy(data, readptr, r_len);
+  data += r_len;
+  rc += r_len;
+  
+  if (r_len != len) {
+    readptr = b->data_start;
+    r_len = min(len - r_len, b->data_head - b->data_start);
+    memcpy(data, readptr, r_len);
+    rc += r_len;
+  }
+  return rc;
+}
+
+int circ_buf_write(char *buf, uint32_t sseqno,
+                   uint8_t *data, int len) {
+  struct circ_buf *b = (struct circ_buf *)buf;
+  uint8_t *writeptr;
+  int w_len;
+  /* we can't write any bytes since we're trying to write too far
+     ahead  */
+  if (sseqno > b->head_seqno + b->data_len)
+    return -1;
+  if (len == 0) return 0;
+
+  get_ptr_off_1(b, sseqno, len, &writeptr, &w_len);
+
+  memcpy(writeptr, data, w_len);
+  data += w_len;
+
+  if (w_len != len) {
+    writeptr = b->data_start;
+    w_len = min(len - w_len, b->data_head - b->data_start);
+    memcpy(writeptr, data, w_len);
+  }
+
+  return 0;
+}
+
+#ifdef PC             
+void circ_buf_dump(void *buf) {
+  struct circ_buf *b = (struct circ_buf *)buf;
+  uint8_t *d;
+  int i;
+/*   printf("circ buf: %p\n\tmap: %p\n\tmap_len: %i\n\tdata_start: %p\n\t" */
+/*          "data_head: %p\n\tdata_len: %i\n\thead_seqno: %i\n",  */
+/*          b, b->map, */
+/*          b->map_len, b->data_start, b->data_head, b->data_len, b->head_seqno); */
+  for (d = b->data_start; d < b->data_start + b->data_len; d++) {
+    if (d == b->data_head) putc('|', stdout);
+    printf("%2.x ", *d);
+  }
+  putc('\n', stdout);
+}
+#endif