45 #include "contiki-net.h"
52 #ifdef QUEUEBUF_CONF_REF_NUM
53 #define QUEUEBUF_REF_NUM QUEUEBUF_CONF_REF_NUM
55 #define QUEUEBUF_REF_NUM 2
62 struct queuebuf *next;
68 enum {IN_RAM, IN_CFS} location;
71 struct queuebuf_data *ram_ptr;
79 struct queuebuf_data {
82 struct packetbuf_attr attrs[PACKETBUF_NUM_ATTRS];
83 struct packetbuf_addr addrs[PACKETBUF_NUM_ADDRS];
93 MEMB(bufmem,
struct queuebuf, QUEUEBUF_NUM);
94 MEMB(refbufmem,
struct queuebuf_ref, QUEUEBUF_REF_NUM);
95 MEMB(buframmem,
struct queuebuf_data, QUEUEBUFRAM_NUM);
103 #define NQBUF_FILES 4
104 #define NQBUF_PER_FILE 256
105 #define QBUF_FILE_SIZE (NQBUF_PER_FILE*sizeof(struct queuebuf_data))
106 #define NQBUF_ID (NQBUF_PER_FILE * NQBUF_FILES)
115 static struct queuebuf_data tmpdata;
117 static struct queuebuf *tmpdata_qbuf =
NULL;
119 static int next_swap_id = 0;
121 static struct qbuf_file qbuf_files[NQBUF_FILES];
123 static struct ctimer renew_timer;
135 #define PRINTF(...) printf(__VA_ARGS__)
140 #ifdef QUEUEBUF_CONF_STATS
141 #define QUEUEBUF_STATS QUEUEBUF_CONF_STATS
143 #define QUEUEBUF_STATS 0
147 uint8_t queuebuf_len, queuebuf_ref_len, queuebuf_max_len;
153 qbuf_renew_file(
int file)
157 name[0] =
'a' + file;
159 if(qbuf_files[file].renewable == 1) {
160 PRINTF(
"qbuf_renew_file: removing file %d\n", file);
165 PRINTF(
"qbuf_renew_file: cfs open error\n");
167 qbuf_files[file].fd = ret;
168 qbuf_files[file].usage = 0;
169 qbuf_files[file].renewable = 0;
174 qbuf_renew_all(
void *unused)
177 for(i=0; i<NQBUF_FILES; i++) {
178 if(qbuf_files[i].renewable == 1) {
186 queuebuf_remove_from_file(
int swap_id)
190 fileid = swap_id / NQBUF_PER_FILE;
191 qbuf_files[fileid].usage--;
194 if(qbuf_files[fileid].usage == 0 && fileid != next_swap_id / NQBUF_PER_FILE) {
195 qbuf_files[fileid].renewable = 1;
200 if(tmpdata_qbuf->swap_id == swap_id) {
201 tmpdata_qbuf->swap_id = -1;
207 get_new_swap_id(
void)
210 int swap_id = next_swap_id;
211 fileid = swap_id / NQBUF_PER_FILE;
212 if(swap_id % NQBUF_PER_FILE == 0) {
213 if(qbuf_files[fileid].renewable) {
214 qbuf_renew_file(fileid);
216 if(qbuf_files[fileid].usage>0) {
220 qbuf_files[fileid].usage++;
221 next_swap_id = (next_swap_id+1) % NQBUF_ID;
227 queuebuf_flush_tmpdata(
void)
232 queuebuf_remove_from_file(tmpdata_qbuf->swap_id);
233 tmpdata_qbuf->swap_id = get_new_swap_id();
234 if(tmpdata_qbuf->swap_id == -1) {
237 fileid = tmpdata_qbuf->swap_id / NQBUF_PER_FILE;
238 offset = (tmpdata_qbuf->swap_id % NQBUF_PER_FILE) *
sizeof(
struct queuebuf_data);
239 fd = qbuf_files[fileid].fd;
242 PRINTF(
"queuebuf_flush_tmpdata: cfs seek error\n");
245 ret = cfs_write(fd, &tmpdata,
sizeof(
struct queuebuf_data));
247 PRINTF(
"queuebuf_flush_tmpdata: cfs write error\n");
255 static struct queuebuf_data *
256 queuebuf_load_to_ram(
struct queuebuf *b)
260 if(b->location == IN_RAM) {
263 if(tmpdata_qbuf && tmpdata_qbuf->swap_id == b->swap_id) {
268 fileid = b->swap_id / NQBUF_PER_FILE;
269 offset = (b->swap_id % NQBUF_PER_FILE) *
sizeof(
struct queuebuf_data);
270 fd = qbuf_files[fileid].fd;
273 PRINTF(
"queuebuf_load_to_ram: cfs seek error\n");
275 ret = cfs_read(fd, &tmpdata,
sizeof(
struct queuebuf_data));
277 PRINTF(
"queuebuf_load_to_ram: cfs read error\n");
285 static struct queuebuf_data *
286 queuebuf_load_to_ram(
struct queuebuf *b)
297 for(i=0; i<NQBUF_FILES; i++) {
298 qbuf_files[i].renewable = 1;
306 queuebuf_max_len = QUEUEBUF_NUM;
311 queuebuf_numfree(
void)
314 return memb_numfree(&refbufmem);
316 return memb_numfree(&bufmem);
322 queuebuf_new_from_packetbuf_debug(
const char *file,
int line)
325 queuebuf_new_from_packetbuf(
void)
328 struct queuebuf *buf;
329 struct queuebuf_ref *rbuf;
341 PRINTF(
"queuebuf_new_from_packetbuf: could not allocate a reference queuebuf\n");
343 return (
struct queuebuf *)rbuf;
345 struct queuebuf_data *buframptr;
357 if(buf->ram_ptr !=
NULL) {
358 buf->location = IN_RAM;
359 buframptr = buf->ram_ptr;
361 buf->location = IN_CFS;
364 buframptr = &tmpdata;
367 if(buf->ram_ptr ==
NULL) {
368 PRINTF(
"queuebuf_new_from_packetbuf: could not queuebuf data\n");
372 buframptr = buf->ram_ptr;
376 packetbuf_attr_copyto(buframptr->attrs, buframptr->addrs);
379 if(buf->location == IN_CFS) {
380 if(queuebuf_flush_tmpdata() == -1) {
390 PRINTF(
"queuebuf len %d\n", queuebuf_len);
391 printf(
"#A q=%d\n", queuebuf_len);
392 if(queuebuf_len == queuebuf_max_len + 1) {
400 PRINTF(
"queuebuf_new_from_packetbuf: could not allocate a queuebuf\n");
407 queuebuf_update_attr_from_packetbuf(
struct queuebuf *buf)
409 struct queuebuf_data *buframptr = queuebuf_load_to_ram(buf);
410 packetbuf_attr_copyto(buframptr->attrs, buframptr->addrs);
412 if(buf->location == IN_CFS) {
413 queuebuf_flush_tmpdata();
419 queuebuf_update_from_packetbuf(
struct queuebuf *buf)
421 struct queuebuf_data *buframptr = queuebuf_load_to_ram(buf);
422 packetbuf_attr_copyto(buframptr->attrs, buframptr->addrs);
425 if(buf->location == IN_CFS) {
426 queuebuf_flush_tmpdata();
432 queuebuf_free(
struct queuebuf *buf)
434 if(memb_inmemb(&bufmem, buf)) {
436 if(buf->location == IN_RAM) {
439 queuebuf_remove_from_file(buf->swap_id);
447 printf(
"#A q=%d\n", queuebuf_len);
452 }
else if(memb_inmemb(&refbufmem, buf)) {
461 queuebuf_to_packetbuf(
struct queuebuf *b)
463 struct queuebuf_ref *r;
464 if(memb_inmemb(&bufmem, b)) {
465 struct queuebuf_data *buframptr = queuebuf_load_to_ram(b);
467 packetbuf_attr_copyfrom(buframptr->attrs, buframptr->addrs);
468 }
else if(memb_inmemb(&refbufmem, b)) {
469 r = (
struct queuebuf_ref *)b;
478 queuebuf_dataptr(
struct queuebuf *b)
480 struct queuebuf_ref *r;
482 if(memb_inmemb(&bufmem, b)) {
483 struct queuebuf_data *buframptr = queuebuf_load_to_ram(b);
484 return buframptr->data;
485 }
else if(memb_inmemb(&refbufmem, b)) {
486 r = (
struct queuebuf_ref *)b;
493 queuebuf_datalen(
struct queuebuf *b)
495 struct queuebuf_data *buframptr = queuebuf_load_to_ram(b);
496 return buframptr->len;
500 queuebuf_addr(
struct queuebuf *b, uint8_t type)
502 struct queuebuf_data *buframptr = queuebuf_load_to_ram(b);
503 return &buframptr->addrs[type - PACKETBUF_ADDR_FIRST].addr;
507 queuebuf_attr(
struct queuebuf *b, uint8_t type)
509 struct queuebuf_data *buframptr = queuebuf_load_to_ram(b);
510 return buframptr->attrs[type].val;
514 queuebuf_debug_print(
void)
518 printf(
"queuebuf_list: ");
521 printf(
"%s,%d,%lu ", q->file, q->line, q->time);
Linked list manipulation routines.
int packetbuf_hdralloc(int size)
Extend the header of the packetbuf, for outbound packets.
int packetbuf_copyfrom(const void *from, uint16_t len)
Copy from external data into the packetbuf.
void memb_init(struct memb *m)
Initialize a memory block that was declared with MEMB().
int cfs_open(const char *name, int flags)
Open a file.
cfs_offset_t cfs_seek(int fd, cfs_offset_t offset, int whence)
Seek to a specified position in an open file.
#define CFS_WRITE
Specify that cfs_open() should open a file for writing.
void * list_item_next(void *item)
Get the next item following this item.
char memb_free(struct memb *m, void *ptr)
Deallocate a memory block from a memory block previously declared with MEMB().
void * memb_alloc(struct memb *m)
Allocate a memory block from a block of memory declared with MEMB().
#define NULL
The null pointer.
#define CFS_READ
Specify that cfs_open() should open a file for reading.
void list_remove(list_t list, void *item)
Remove a specific element from a list.
uint16_t packetbuf_datalen(void)
Get the length of the data in the packetbuf.
CCIF clock_time_t clock_time(void)
Get the current clock time.
void ctimer_set(struct ctimer *c, clock_time_t t, void(*f)(void *), void *ptr)
Set a callback timer.
int cfs_remove(const char *name)
Remove a file.
void * packetbuf_hdrptr(void)
Get a pointer to the header in the packetbuf, for outbound packets.
void * packetbuf_reference_ptr(void)
Get a pointer to external data referenced by the packetbuf.
void * list_head(list_t list)
Get a pointer to the first element of a list.
#define MEMB(name, structure, num)
Declare a memory block.
#define PACKETBUF_HDR_SIZE
The size of the packetbuf header, in bytes.
int packetbuf_copyto(void *to)
Copy the entire packetbuf to an external buffer.
void list_add(list_t list, void *item)
Add an item at the end of a list.
int packetbuf_copyto_hdr(uint8_t *to)
Copy the header portion of the packetbuf to an external buffer.
#define LIST(name)
Declare a linked list.
void packetbuf_clear(void)
Clear and reset the packetbuf.
#define PACKETBUF_SIZE
The size of the packetbuf, in bytes.
#define CFS_SEEK_SET
Specify that cfs_seek() should compute the offset from the beginning of the file. ...
int packetbuf_is_reference(void)
Check if the packetbuf references external data.