diff --git a/core/dev/cc2420.c b/core/dev/cc2420.c index 1e2749236..687c2b7cb 100644 --- a/core/dev/cc2420.c +++ b/core/dev/cc2420.c @@ -28,7 +28,7 @@ * * This file is part of the Contiki operating system. * - * @(#)$Id: cc2420.c,v 1.37 2010/01/14 23:32:05 adamdunkels Exp $ + * @(#)$Id: cc2420.c,v 1.38 2010/02/18 21:48:39 adamdunkels Exp $ */ /* * This code is almost device independent and should be easy to port. @@ -52,11 +52,13 @@ #include "net/rime/packetbuf.h" #include "net/rime/rimestats.h" +#include "net/netstack.h" #include "sys/timetable.h" #define WITH_SEND_CCA 0 +#include "cc2420-arch-sfd.h" #if CC2420_CONF_TIMESTAMPS #include "net/rime/timesynch.h" @@ -112,30 +114,41 @@ static unsigned long total_time_for_transmission, total_transmission_len; static int num_transmissions; #endif /* CC2420_CONF_TIMESTAMPS */ +int cc2420_packets_seen, cc2420_packets_read; + +static uint8_t volatile pending; + /*---------------------------------------------------------------------------*/ PROCESS(cc2420_process, "CC2420 driver"); /*---------------------------------------------------------------------------*/ -static void (* receiver_callback)(const struct radio_driver *); int cc2420_on(void); int cc2420_off(void); -int cc2420_read(void *buf, unsigned short bufsize); +static int cc2420_read(void *buf, unsigned short bufsize); -int cc2420_send(const void *data, unsigned short len); - -void cc2420_set_receiver(void (* recv)(const struct radio_driver *d)); +static int cc2420_prepare(const void *data, unsigned short len); +static int cc2420_transmit(unsigned short len); +static int cc2420_send(const void *data, unsigned short len); +static int cc2420_receiving_packet(void); +static int pending_packet(void); +static int cc2420_cca(void); signed char cc2420_last_rssi; uint8_t cc2420_last_correlation; const struct radio_driver cc2420_driver = { + cc2420_init, + cc2420_prepare, + cc2420_transmit, cc2420_send, cc2420_read, - cc2420_set_receiver, + cc2420_cca, + cc2420_receiving_packet, + pending_packet, cc2420_on, cc2420_off, }; @@ -257,13 +270,7 @@ set_txpower(uint8_t power) #define FIFOP_THR(n) ((n) & 0x7f) #define RXBPF_LOCUR (1 << 13); /*---------------------------------------------------------------------------*/ -void -cc2420_set_receiver(void (* recv)(const struct radio_driver *)) -{ - receiver_callback = recv; -} -/*---------------------------------------------------------------------------*/ -void +int cc2420_init(void) { uint16_t reg; @@ -315,10 +322,11 @@ cc2420_init(void) cc2420_set_channel(26); process_start(&cc2420_process, NULL); + return 1; } /*---------------------------------------------------------------------------*/ -int -cc2420_send(const void *payload, unsigned short payload_len) +static int +cc2420_transmit(unsigned short payload_len) { int i, txpower; uint8_t total_len; @@ -328,6 +336,7 @@ cc2420_send(const void *payload, unsigned short payload_len) #if CC2420_CONF_CHECKSUM uint16_t checksum; #endif /* CC2420_CONF_CHECKSUM */ + GET_LOCK(); txpower = 0; @@ -338,32 +347,8 @@ cc2420_send(const void *payload, unsigned short payload_len) set_txpower(packetbuf_attr(PACKETBUF_ATTR_RADIO_TXPOWER) - 1); } - PRINTF("cc2420: sending %d bytes\n", payload_len); - - RIMESTATS_ADD(lltx); - - /* Wait for any previous transmission to finish. */ - while(status() & BV(CC2420_TX_ACTIVE)); - - /* Write packet to TX FIFO. */ - strobe(CC2420_SFLUSHTX); - -#if CC2420_CONF_CHECKSUM - checksum = crc16_data(payload, payload_len, 0); -#endif /* CC2420_CONF_CHECKSUM */ total_len = payload_len + AUX_LEN; - FASTSPI_WRITE_FIFO(&total_len, 1); - FASTSPI_WRITE_FIFO(payload, payload_len); -#if CC2420_CONF_CHECKSUM - FASTSPI_WRITE_FIFO(&checksum, CHECKSUM_LEN); -#endif /* CC2420_CONF_CHECKSUM */ - -#if CC2420_CONF_TIMESTAMPS - timestamp.authority_level = timesynch_authority_level(); - timestamp.time = timesynch_time(); - FASTSPI_WRITE_FIFO(×tamp, TIMESTAMP_LEN); -#endif /* CC2420_CONF_TIMESTAMPS */ - + /* The TX FIFO can only hold one packet. Make sure to not overrun * FIFO by waiting for transmission to start here and synchronizing * with the CC2420_TX_ACTIVE check in cc2420_send. @@ -387,12 +372,6 @@ cc2420_send(const void *payload, unsigned short payload_len) for(i = LOOP_20_SYMBOLS; i > 0; i--) { if(SFD_IS_1) { - if(!(status() & BV(CC2420_TX_ACTIVE))) { - /* SFD went high yet we are not transmitting! - * => We started receiving a packet right now */ - return RADIO_TX_ERR; - } - #if CC2420_CONF_TIMESTAMPS rtimer_clock_t txtime = timesynch_time(); #endif /* CC2420_CONF_TIMESTAMPS */ @@ -435,7 +414,7 @@ cc2420_send(const void *payload, unsigned short payload_len) } RELEASE_LOCK(); - return RADIO_TX_OK; + return 0; } } @@ -450,7 +429,56 @@ cc2420_send(const void *payload, unsigned short payload_len) } RELEASE_LOCK(); - return RADIO_TX_ERR; /* Transmission never started! */ + return -3; /* Transmission never started! */ +} +/*---------------------------------------------------------------------------*/ +static int +cc2420_prepare(const void *payload, unsigned short payload_len) +{ + uint8_t total_len; +#if CC2420_CONF_TIMESTAMPS + struct timestamp timestamp; +#endif /* CC2420_CONF_TIMESTAMPS */ +#if CC2420_CONF_CHECKSUM + uint16_t checksum; +#endif /* CC2420_CONF_CHECKSUM */ + GET_LOCK(); + + PRINTF("cc2420: sending %d bytes\n", payload_len); + + RIMESTATS_ADD(lltx); + + /* Wait for any previous transmission to finish. */ + while(status() & BV(CC2420_TX_ACTIVE)); + + /* Write packet to TX FIFO. */ + strobe(CC2420_SFLUSHTX); + +#if CC2420_CONF_CHECKSUM + checksum = crc16_data(payload, payload_len, 0); +#endif /* CC2420_CONF_CHECKSUM */ + total_len = payload_len + AUX_LEN; + FASTSPI_WRITE_FIFO(&total_len, 1); + FASTSPI_WRITE_FIFO(payload, payload_len); +#if CC2420_CONF_CHECKSUM + FASTSPI_WRITE_FIFO(&checksum, CHECKSUM_LEN); +#endif /* CC2420_CONF_CHECKSUM */ + +#if CC2420_CONF_TIMESTAMPS + timestamp.authority_level = timesynch_authority_level(); + timestamp.time = timesynch_time(); + FASTSPI_WRITE_FIFO(×tamp, TIMESTAMP_LEN); +#endif /* CC2420_CONF_TIMESTAMPS */ + + RELEASE_LOCK(); + return 0; +} +/*---------------------------------------------------------------------------*/ +static int +cc2420_send(const void *payload, unsigned short payload_len) +{ + cc2420_prepare(payload, payload_len); + return cc2420_transmit(payload_len); } /*---------------------------------------------------------------------------*/ int @@ -534,8 +562,8 @@ cc2420_set_channel(int c) /*---------------------------------------------------------------------------*/ void cc2420_set_pan_addr(unsigned pan, - unsigned addr, - const uint8_t *ieee_addr) + unsigned addr, + const uint8_t *ieee_addr) { uint16_t f = 0; /* @@ -572,10 +600,8 @@ int cc2420_interrupt(void) { #if CC2420_CONF_TIMESTAMPS - if(!interrupt_time_set) { - interrupt_time = timesynch_time(); - interrupt_time_set = 1; - } + interrupt_time = timesynch_time(); + interrupt_time_set = 1; #endif /* CC2420_CONF_TIMESTAMPS */ CLEAR_FIFOP_INT(); @@ -584,11 +610,16 @@ cc2420_interrupt(void) timetable_clear(&cc2420_timetable); TIMETABLE_TIMESTAMP(cc2420_timetable, "interrupt"); #endif /* CC2420_TIMETABLE_PROFILING */ + + pending = 1; + + cc2420_packets_seen++; return 1; } /*---------------------------------------------------------------------------*/ PROCESS_THREAD(cc2420_process, ev, data) { + int len; PROCESS_BEGIN(); PRINTF("cc2420_process: started\n"); @@ -599,25 +630,28 @@ PROCESS_THREAD(cc2420_process, ev, data) TIMETABLE_TIMESTAMP(cc2420_timetable, "poll"); #endif /* CC2420_TIMETABLE_PROFILING */ - if(receiver_callback != NULL) { - PRINTF("cc2420_process: calling receiver callback\n"); - receiver_callback(&cc2420_driver); + pending = 0; + + PRINTF("cc2420_process: calling receiver callback\n"); + + packetbuf_clear(); + len = cc2420_read(packetbuf_dataptr(), PACKETBUF_SIZE); + if(len > 0) { + packetbuf_set_datalen(len); + NETSTACK_RDC.input(); #if CC2420_TIMETABLE_PROFILING TIMETABLE_TIMESTAMP(cc2420_timetable, "end"); timetable_aggregate_compute_detailed(&aggregate_time, - &cc2420_timetable); + &cc2420_timetable); timetable_clear(&cc2420_timetable); #endif /* CC2420_TIMETABLE_PROFILING */ - } else { - PRINTF("cc2420_process not receiving function\n"); - flushrx(); } } PROCESS_END(); } /*---------------------------------------------------------------------------*/ -int +static int cc2420_read(void *buf, unsigned short bufsize) { uint8_t footer[2]; @@ -630,12 +664,23 @@ cc2420_read(void *buf, unsigned short bufsize) #endif /* CC2420_CONF_TIMESTAMPS */ if(!FIFOP_IS_1) { - /* If FIFO is 0, there is no packet in the RXFIFO. */ + /* If FIFOP is 0, there is no packet in the RXFIFO. */ return 0; } +#if CC2420_CONF_TIMESTAMPS + if(interrupt_time_set) { + cc2420_time_of_arrival = interrupt_time; + interrupt_time_set = 0; + } else { + cc2420_time_of_arrival = 0; + } + cc2420_time_of_departure = 0; +#endif /* CC2420_CONF_TIMESTAMPS */ GET_LOCK(); + cc2420_packets_read++; + getrxbyte(&len); if(len > CC2420_MAX_PACKET_LEN) { @@ -647,6 +692,7 @@ cc2420_read(void *buf, unsigned short bufsize) } if(len <= AUX_LEN) { + printf("len <= AUX_LEN\n"); flushrx(); RIMESTATS_ADD(tooshort); RELEASE_LOCK(); @@ -654,6 +700,7 @@ cc2420_read(void *buf, unsigned short bufsize) } if(len - AUX_LEN > bufsize) { + printf("len - AUX_LEN > bufsize\n"); flushrx(); RIMESTATS_ADD(toolong); RELEASE_LOCK(); @@ -690,19 +737,12 @@ cc2420_read(void *buf, unsigned short bufsize) RIMESTATS_ADD(llrx); #if CC2420_CONF_TIMESTAMPS - if(interrupt_time_set) { - cc2420_time_of_arrival = interrupt_time; - cc2420_time_of_departure = - t.time + - setup_time_for_transmission + - (total_time_for_transmission * (len - 2)) / total_transmission_len; - - cc2420_authority_level_of_sender = t.authority_level; - interrupt_time_set = 0; - } else { - /* Bypass timesynch */ - cc2420_authority_level_of_sender = timesynch_authority_level(); - } + cc2420_time_of_departure = + t.time + + setup_time_for_transmission + + (total_time_for_transmission * (len - 2)) / total_transmission_len; + + cc2420_authority_level_of_sender = t.authority_level; packetbuf_set_attr(PACKETBUF_ATTR_TIMESTAMP, t.time); #endif /* CC2420_CONF_TIMESTAMPS */ @@ -720,6 +760,7 @@ cc2420_read(void *buf, unsigned short bufsize) flushrx(); } else if(FIFOP_IS_1) { /* Another packet has been received and needs attention. */ + /* printf("attention\n");*/ process_poll(&cc2420_process); } @@ -768,3 +809,67 @@ cc2420_rssi(void) return rssi; } /*---------------------------------------------------------------------------*/ +static int +cc2420_cca(void) +{ + int cca; + int radio_was_off = 0; + + /* If the radio is locked by an underlying thread (because we are + being invoked through an interrupt), we preted that the coast is + clear (i.e., no packet is currently being transmitted by a + neighbor). */ + if(locked) { + return 1; + } + + if(!receive_on) { + radio_was_off = 1; + cc2420_on(); + } + while(!(status() & BV(CC2420_RSSI_VALID))) { + /* printf("cc2420_rssi: RSSI not valid.\n"); */ + } + + cca = CCA_IS_1; + + if(radio_was_off) { + cc2420_off(); + } + return cca; +} +/*---------------------------------------------------------------------------*/ +int +cc2420_receiving_packet(void) +{ + return SFD_IS_1; +} +/*---------------------------------------------------------------------------*/ +static int +pending_packet(void) +{ + return pending; +} +/*---------------------------------------------------------------------------*/ +void +cc2420_ugly_hack_send_only_one_symbol(void) +{ + uint8_t len; + GET_LOCK(); + + /* Write packet to TX FIFO. */ + strobe(CC2420_SFLUSHTX); + + len = 1; + FASTSPI_WRITE_FIFO(&len, 1); + FASTSPI_WRITE_FIFO(&len, 1); + + strobe(CC2420_STXON); + while(!SFD_IS_1); + + /* Turn radio off immediately after sending the first symbol. */ + strobe(CC2420_SRFOFF); + RELEASE_LOCK(); + return; +} +/*---------------------------------------------------------------------------*/ diff --git a/core/dev/cc2420.h b/core/dev/cc2420.h index 817034d7d..6aac22b78 100644 --- a/core/dev/cc2420.h +++ b/core/dev/cc2420.h @@ -28,7 +28,7 @@ * * This file is part of the Contiki operating system. * - * $Id: cc2420.h,v 1.7 2008/07/02 09:05:40 adamdunkels Exp $ + * $Id: cc2420.h,v 1.8 2010/02/18 21:48:39 adamdunkels Exp $ */ /** @@ -44,7 +44,7 @@ #include "contiki.h" #include "dev/radio.h" -void cc2420_init(void); +int cc2420_init(void); #define CC2420_MAX_PACKET_LEN 127 diff --git a/core/dev/radio.h b/core/dev/radio.h index 1d52a3f6e..36b437ba5 100644 --- a/core/dev/radio.h +++ b/core/dev/radio.h @@ -42,7 +42,7 @@ * * This file is part of the Contiki operating system. * - * $Id: radio.h,v 1.6 2009/11/13 08:59:22 fros4943 Exp $ + * $Id: radio.h,v 1.7 2010/02/18 21:48:39 adamdunkels Exp $ */ /** @@ -59,14 +59,30 @@ * The structure of a device driver for a radio in Contiki. */ struct radio_driver { - /** Send a packet */ + + int (* init)(void); + + /** Prepare the radio with a packet to be sent. */ + int (* prepare)(const void *payload, unsigned short payload_len); + + /** Send the packet that has previously been prepared. */ + int (* transmit)(unsigned short transmit_len); + + /** Prepare & transmit a packet. */ int (* send)(const void *payload, unsigned short payload_len); /** Read a received packet into a buffer. */ int (* read)(void *buf, unsigned short buf_len); - /** Set a function to be called when a packet has been received. */ - void (* set_receive_function)(void (*f)(const struct radio_driver *d)); + /** Perform a Clear-Channel Assessment (CCA) to find out if there is + a packet in the air or not. */ + int (* channel_clear)(void); + + /** Check if the radio driver is currently receiving a packet */ + int (* receiving_packet)(void); + + /** Check if the radio driver has just received a packet */ + int (* pending_packet)(void); /** Turn the radio on. */ int (* on)(void); @@ -83,5 +99,6 @@ enum { #endif /* __RADIO_H__ */ + /** @} */ /** @} */ diff --git a/core/net/mac/Makefile.mac b/core/net/mac/Makefile.mac index 6c5dd71bb..3e89ecb50 100644 --- a/core/net/mac/Makefile.mac +++ b/core/net/mac/Makefile.mac @@ -1,2 +1,2 @@ -CONTIKI_SOURCEFILES += cxmac.c xmac.c nullmac.c lpp.c frame802154.c sicslowmac.c -CONTIKI_SOURCEFILES += framer.c framer-nullmac.c framer-802154.c csma.c +CONTIKI_SOURCEFILES += cxmac.c xmac.c nullmac.c lpp.c frame802154.c sicslowmac.c nullrdc.c mac.c +CONTIKI_SOURCEFILES += framer.c framer-nullmac.c framer-802154.c csma.c contikimac.c phase.c diff --git a/core/net/mac/contikimac.c b/core/net/mac/contikimac.c index c786bfca2..35b0f4198 100644 --- a/core/net/mac/contikimac.c +++ b/core/net/mac/contikimac.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, Swedish Institute of Computer Science. + * Copyright (c) 2010, Swedish Institute of Computer Science. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -28,12 +28,12 @@ * * This file is part of the Contiki operating system. * - * $Id: contikimac.c,v 1.1 2010/02/18 21:26:15 adamdunkels Exp $ + * $Id: contikimac.c,v 1.2 2010/02/18 21:48:39 adamdunkels Exp $ */ /** * \file - * The Contiki power-saving MAC protocol (C-MAC) + * The Contiki power-saving MAC protocol (ContikiMAC) * \author * Adam Dunkels * Niclas Finne diff --git a/core/net/mac/contikimac.h b/core/net/mac/contikimac.h index ceb84ac3c..f1148791c 100644 --- a/core/net/mac/contikimac.h +++ b/core/net/mac/contikimac.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, Swedish Institute of Computer Science. + * Copyright (c) 2010, Swedish Institute of Computer Science. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -28,12 +28,12 @@ * * This file is part of the Contiki operating system. * - * $Id: contikimac.h,v 1.1 2010/02/18 21:26:15 adamdunkels Exp $ + * $Id: contikimac.h,v 1.2 2010/02/18 21:48:39 adamdunkels Exp $ */ /** * \file - * The Contiki power-saving MAC protocol + * The Contiki power-saving MAC protocol (ContikiMAC) * \author * Adam Dunkels */ diff --git a/core/net/mac/csma.c b/core/net/mac/csma.c index 432caff18..3f96b559e 100644 --- a/core/net/mac/csma.c +++ b/core/net/mac/csma.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, Swedish Institute of Computer Science. + * Copyright (c) 2010, Swedish Institute of Computer Science. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -28,7 +28,7 @@ * * This file is part of the Contiki operating system. * - * $Id: csma.c,v 1.5 2010/02/03 01:17:54 adamdunkels Exp $ + * $Id: csma.c,v 1.6 2010/02/18 21:48:39 adamdunkels Exp $ */ /** @@ -47,170 +47,235 @@ #include "lib/random.h" +#include "net/netstack.h" + #include "lib/list.h" #include "lib/memb.h" #include +#define DEBUG 0 +#if DEBUG +#include +#define PRINTF(...) printf(__VA_ARGS__) +#else /* DEBUG */ +#define PRINTF(...) +#endif /* DEBUG */ + struct queued_packet { struct queued_packet *next; struct queuebuf *buf; struct ctimer retransmit_timer; - uint8_t retransmits; + mac_callback_t sent; + void *cptr; + uint8_t transmissions; }; -#define MAX_QUEUED_PACKETS 4 -LIST(packet_list); +#define MAX_RETRANSMITS 2 + +#define MAX_QUEUED_PACKETS 8 MEMB(packet_memb, struct queued_packet, MAX_QUEUED_PACKETS); -static const struct mac_driver *mac; -static void (* receiver_callback)(const struct mac_driver *); - -const struct mac_driver *csma_init(const struct mac_driver *psc); /*---------------------------------------------------------------------------*/ #if CSMA_CONF_REXMIT +static void +free_packet(struct queued_packet *q) +{ + queuebuf_free(q->buf); + memb_free(&packet_memb, q); +} + +static void retransmit_packet(void *ptr); + +static void +packet_sent(void *ptr, int status, int num_transmissions) +{ + struct queued_packet *q = ptr; + clock_time_t time = 0; + mac_callback_t sent; + void *cptr; + int num_tx; + + sent = q->sent; + cptr = q->cptr; + num_tx = q->transmissions; + + if(status != MAC_TX_OK) { + switch(status) { + case MAC_TX_COLLISION: + PRINTF("csma: rexmit collision %d\n", q->transmissions); + break; + case MAC_TX_NOACK: + PRINTF("csma: rexmit noack %d\n", q->transmissions); + break; + default: + PRINTF("csma: rexmit err %d, %d\n", ret, q->transmissions); + } + + time = NETSTACK_RDC.channel_check_interval(); + if(time == 0) { + time = CLOCK_SECOND; + } + time = time + (random_rand() % (q->transmissions * 3 * time)); + + if(q->transmissions - 1 < MAX_RETRANSMITS) { + ctimer_set(&q->retransmit_timer, time, + retransmit_packet, q); + } else { + PRINTF("csma: drop after %d\n", q->transmissions); + free_packet(q); + mac_call_sent_callback(sent, ptr, status, num_tx); + } + } else { + PRINTF("csma: rexmit ok %d\n", q->transmissions); + free_packet(q); + mac_call_sent_callback(sent, ptr, status, num_tx); + } +} + static void retransmit_packet(void *ptr) { - int ret; struct queued_packet *q = ptr; queuebuf_to_packetbuf(q->buf); - ret = mac->send(); - - queuebuf_free(q->buf); - list_remove(packet_list, q); - memb_free(&packet_memb, q); + q->transmissions++; + NETSTACK_RDC.send(packet_sent, q); } /*---------------------------------------------------------------------------*/ -static int -send_packet(void) +static void +sent_packet_1(void *ptr, int status, int num_transmissions) { - struct queuebuf *buf; - int ret; + struct queued_packet *q = ptr; clock_time_t time; rimeaddr_t receiver; - - /* Remember packet for later. */ + rimeaddr_copy(&receiver, packetbuf_addr(PACKETBUF_ADDR_RECEIVER)); - buf = queuebuf_new_from_packetbuf(); - ret = mac->send(); - /* if(ret != MAC_TX_OK) { - printf("CSMA: err %d\n", ret); - }*/ + if(rimeaddr_cmp(&receiver, &rimeaddr_null)) { + PRINTF("broadcast/"); + } + if(status != MAC_TX_OK) { + switch(status) { + case MAC_TX_COLLISION: + PRINTF("csma: collision\n"); + break; + case MAC_TX_NOACK: + PRINTF("csma: noack\n"); + break; + default: + PRINTF("csma: err %d\n", ret); + } + } else { + PRINTF("csma: ok\n"); + } + /* Check if we saw a collission, and if we have a queuebuf with the packet available. Only retransmit unicast packets. Retransmit only once, for now. */ - if((ret == MAC_TX_COLLISION || ret == MAC_TX_NOACK) && - buf != NULL && !rimeaddr_cmp(&receiver, &rimeaddr_null)) { - struct queued_packet *q; - - q = memb_alloc(&packet_memb); - if(q == NULL) { - queuebuf_free(buf); - return ret; + if((status == MAC_TX_COLLISION || status == MAC_TX_NOACK) && + !rimeaddr_cmp(&receiver, &rimeaddr_null)) { + /* If the packet couldn't be sent because of a collision or the + lack of an ACK, we let the other transmissions get through + before we try again. */ + time = NETSTACK_RDC.channel_check_interval(); + if(time == 0) { + time = CLOCK_SECOND; } - q->buf = buf; - q->retransmits = 0; + time = time + (random_rand() % (3 * time)); - if(ret == MAC_TX_COLLISION) { - /* If the packet wasn't sent because of a collission, we let the - other packet get through before we try again. */ - time = mac->channel_check_interval(); - if(time == 0) { - time = CLOCK_SECOND; - } - time = time + (random_rand() % (3 * time)); - } else { - /* If the packet didn't get an ACK, we retransmit immediately. */ - time = 0; - } - ctimer_set(&q->retransmit_timer, time, retransmit_packet, q); - list_add(packet_list, q); } else { - queuebuf_free(buf); + mac_callback_t sent; + void *cptr; + int num_tx; + + sent = q->sent; + cptr = q->cptr; + num_tx = q->transmissions; + free_packet(q); + mac_call_sent_callback(sent, ptr, status, num_tx); } - return ret; +} +/*---------------------------------------------------------------------------*/ +static void +send_packet(mac_callback_t sent, void *ptr) +{ + struct queued_packet *q; + + /* Remember packet for later. */ + q = memb_alloc(&packet_memb); + if(q != NULL) { + q->buf = queuebuf_new_from_packetbuf(); + if(q != NULL) { + q->transmissions = 1; + q->sent = sent; + q->cptr = ptr; + NETSTACK_RDC.send(sent_packet_1, q); + return; + } + memb_free(&packet_memb, q); + } + PRINTF("csma: could not allocate queuebuf, will drop if collision or noack\n"); + NETSTACK_RDC.send(sent, ptr); } #else /* CSMA_CONF_REXMIT */ -static int -send_packet(void) +static void +send_packet(mac_callback_t sent, void *ptr) { - return mac->send(); + NETSTACK_RDC.send(NULL, NULL); } #endif /* CSMA_CONF_REXMIT */ /*---------------------------------------------------------------------------*/ static void -input_packet(const struct mac_driver *d) +input_packet(void) { - if(receiver_callback) { - receiver_callback(&csma_driver); - } -} -/*---------------------------------------------------------------------------*/ -static int -read_packet(void) -{ - int len; - len = mac->read(); - return len; -} -/*---------------------------------------------------------------------------*/ -static void -set_receive_function(void (* recv)(const struct mac_driver *)) -{ - receiver_callback = recv; + NETSTACK_NETWORK.input(); } /*---------------------------------------------------------------------------*/ static int on(void) { - return mac->on(); + return NETSTACK_RDC.on(); } /*---------------------------------------------------------------------------*/ static int off(int keep_radio_on) { - return mac->off(keep_radio_on); + return NETSTACK_RDC.off(keep_radio_on); } /*---------------------------------------------------------------------------*/ static unsigned short channel_check_interval(void) { - if(mac->channel_check_interval) { - return mac->channel_check_interval(); + if(NETSTACK_RDC.channel_check_interval) { + return NETSTACK_RDC.channel_check_interval(); } return 0; } /*---------------------------------------------------------------------------*/ #define NAMEBUF_LEN 16 static char namebuf[NAMEBUF_LEN]; +static void +init(void) +{ + memb_init(&packet_memb); + + /* PRINTF("CSMA with MAC %s, channel check rate %d Hz\n", mac->name, + CLOCK_SECOND / channel_check_interval());*/ + memcpy(namebuf, "CSMA ", 5); + memcpy(namebuf + 5, NETSTACK_RDC.name, NAMEBUF_LEN - 6); +} +/*---------------------------------------------------------------------------*/ const struct mac_driver csma_driver = { namebuf, - NULL, + init, send_packet, - read_packet, - set_receive_function, + input_packet, on, off, channel_check_interval, }; /*---------------------------------------------------------------------------*/ -const struct mac_driver * -csma_init(const struct mac_driver *psc) -{ - memb_init(&packet_memb); - list_init(packet_list); - mac = psc; - mac->set_receive_function(input_packet); - /* printf("CSMA with MAC %s, channel check rate %d Hz\n", mac->name, - CLOCK_SECOND / channel_check_interval());*/ - memcpy(namebuf, "CSMA ", 5); - memcpy(namebuf + 5, psc->name, NAMEBUF_LEN - 6); - return &csma_driver; -} -/*---------------------------------------------------------------------------*/ diff --git a/core/net/mac/cxmac.c b/core/net/mac/cxmac.c index 246dba06b..cfab6f77a 100644 --- a/core/net/mac/cxmac.c +++ b/core/net/mac/cxmac.c @@ -28,7 +28,7 @@ * * This file is part of the Contiki operating system. * - * $Id: cxmac.c,v 1.9 2010/02/03 16:44:43 adamdunkels Exp $ + * $Id: cxmac.c,v 1.10 2010/02/18 21:48:39 adamdunkels Exp $ */ /** @@ -43,6 +43,7 @@ #include "dev/leds.h" #include "dev/radio.h" #include "dev/watchdog.h" +#include "net/netstack.h" #include "lib/random.h" #include "net/mac/framer.h" #include "net/mac/cxmac.h" @@ -157,8 +158,6 @@ static volatile unsigned char someone_is_sending = 0; static volatile unsigned char we_are_sending = 0; static volatile unsigned char radio_is_on = 0; -static const struct radio_driver *radio; - #undef LEDS_ON #undef LEDS_OFF #undef LEDS_TOGGLE @@ -193,8 +192,6 @@ static int announcement_radio_txpower; for announcements from neighbors. */ static uint8_t is_listening; -static void (* receiver_callback)(const struct mac_driver *); - #if CXMAC_CONF_COMPOWER static struct compower_activity current_packet; #endif /* CXMAC_CONF_COMPOWER */ @@ -224,19 +221,13 @@ static rtimer_clock_t stream_until; #define MIN(a, b) ((a) < (b)? (a) : (b)) #endif /* MIN */ -/*---------------------------------------------------------------------------*/ -static void -set_receive_function(void (* recv)(const struct mac_driver *)) -{ - receiver_callback = recv; -} /*---------------------------------------------------------------------------*/ static void on(void) { if(cxmac_is_on && radio_is_on == 0) { radio_is_on = 1; - radio->on(); + NETSTACK_RADIO.on(); LEDS_ON(LEDS_RED); } } @@ -247,7 +238,7 @@ off(void) if(cxmac_is_on && radio_is_on != 0 && is_listening == 0 && is_streaming == 0) { radio_is_on = 0; - radio->off(); + NETSTACK_RADIO.off(); LEDS_OFF(LEDS_RED); } } @@ -571,7 +562,7 @@ send_packet(void) rtimer_clock_t now = RTIMER_NOW(); /* See if we got an ACK */ packetbuf_clear(); - len = radio->read(packetbuf_dataptr(), PACKETBUF_SIZE); + len = NETSTACK_RADIO.read(packetbuf_dataptr(), PACKETBUF_SIZE); if(len > 0) { packetbuf_set_datalen(len); if(framer_get()->parse()) { @@ -602,16 +593,16 @@ send_packet(void) if(is_broadcast) { #if WITH_STROBE_BROADCAST - radio->send(strobe, strobe_len); + NETSTACK_RADIO.send(strobe, strobe_len); #else /* restore the packet to send */ queuebuf_to_packetbuf(packet); - radio->send(packetbuf_hdrptr(), packetbuf_totlen()); + NETSTACK_RADIO.send(packetbuf_hdrptr(), packetbuf_totlen()); #endif off(); } else { rtimer_clock_t wt; - radio->send(strobe, strobe_len); + NETSTACK_RADIO.send(strobe, strobe_len); #if 1 /* Turn off the radio for a while to let the other side respond. We don't need to keep our radio on when we know @@ -649,7 +640,7 @@ send_packet(void) /* Send the data packet. */ if((is_broadcast || got_strobe_ack || is_streaming) && collisions == 0) { - radio->send(packetbuf_hdrptr(), packetbuf_totlen()); + NETSTACK_RADIO.send(packetbuf_hdrptr(), packetbuf_totlen()); } #if WITH_ENCOUNTER_OPTIMIZATION @@ -693,42 +684,27 @@ send_packet(void) } /*---------------------------------------------------------------------------*/ -static int -qsend_packet(void) +static void +qsend_packet(mac_callback_t sent, void *ptr) { + int ret; if(someone_is_sending) { PRINTF("cxmac: should queue packet, now just dropping %d %d %d %d.\n", waiting_for_packet, someone_is_sending, we_are_sending, radio_is_on); RIMESTATS_ADD(sendingdrop); - return MAC_TX_COLLISION; + ret = MAC_TX_COLLISION; } else { PRINTF("cxmac: send immediately.\n"); - return send_packet(); + ret = send_packet(); } + + mac_call_sent_callback(sent, ptr, ret, 1); } /*---------------------------------------------------------------------------*/ static void -input_packet(const struct radio_driver *d) -{ - if(receiver_callback) { - receiver_callback(&cxmac_driver); - } -} -/*---------------------------------------------------------------------------*/ -static int -read_packet(void) +input_packet(void) { struct cxmac_hdr *hdr; - uint8_t len; - - packetbuf_clear(); - - len = radio->read(packetbuf_dataptr(), PACKETBUF_SIZE); - if(len == 0) { - return 0; - } - - packetbuf_set_datalen(len); if(framer_get()->parse()) { hdr = packetbuf_dataptr(); @@ -763,7 +739,8 @@ read_packet(void) waiting_for_packet = 0; PRINTDEBUG("cxmac: data(%u)\n", packetbuf_datalen()); - return packetbuf_datalen(); + NETSTACK_MAC.input(); + return; } else { PRINTDEBUG("cxmac: data not for us\n"); } @@ -790,7 +767,7 @@ read_packet(void) someone_is_sending = 1; waiting_for_packet = 1; on(); - radio->send(packetbuf_hdrptr(), packetbuf_totlen()); + NETSTACK_RADIO.send(packetbuf_hdrptr(), packetbuf_totlen()); PRINTDEBUG("cxmac: send strobe ack %u\n", packetbuf_totlen()); } else { PRINTF("cxmac: failed to send strobe ack\n"); @@ -809,7 +786,7 @@ read_packet(void) /* We are done processing the strobe and we therefore return to the caller. */ - return RIME_OK; + return; #if CXMAC_CONF_ANNOUNCEMENTS } else if(hdr->type == TYPE_ANNOUNCEMENT) { packetbuf_hdrreduce(sizeof(struct cxmac_hdr)); @@ -824,7 +801,6 @@ read_packet(void) } else { PRINTF("cxmac: failed to parse (%u)\n", packetbuf_totlen()); } - return 0; } /*---------------------------------------------------------------------------*/ #if CXMAC_CONF_ANNOUNCEMENTS @@ -850,7 +826,7 @@ send_announcement(void *ptr) packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, &rimeaddr_null); packetbuf_set_attr(PACKETBUF_ATTR_RADIO_TXPOWER, announcement_radio_txpower); if(framer_get()->create()) { - radio->send(packetbuf_hdrptr(), packetbuf_totlen()); + NETSTACK_RADIO.send(packetbuf_hdrptr(), packetbuf_totlen()); } } } @@ -883,8 +859,8 @@ cxmac_set_announcement_radio_txpower(int txpower) #endif /* CXMAC_CONF_ANNOUNCEMENTS */ } /*---------------------------------------------------------------------------*/ -const struct mac_driver * -cxmac_init(const struct radio_driver *d) +void +cxmac_init(void) { radio_is_on = 0; waiting_for_packet = 0; @@ -893,8 +869,6 @@ cxmac_init(const struct radio_driver *d) (void (*)(struct rtimer *, void *))powercycle, NULL);*/ cxmac_is_on = 1; - radio = d; - radio->set_receive_function(input_packet); #if WITH_ENCOUNTER_OPTIMIZATION list_init(encounter_list); @@ -908,7 +882,6 @@ cxmac_init(const struct radio_driver *d) #endif /* CXMAC_CONF_ANNOUNCEMENTS */ CSCHEDULE_POWERCYCLE(DEFAULT_OFF_TIME); - return &cxmac_driver; } /*---------------------------------------------------------------------------*/ static int @@ -926,9 +899,9 @@ turn_off(int keep_radio_on) { cxmac_is_on = 0; if(keep_radio_on) { - return radio->on(); + return NETSTACK_RADIO.on(); } else { - return radio->off(); + return NETSTACK_RADIO.off(); } } /*---------------------------------------------------------------------------*/ @@ -943,8 +916,7 @@ const struct mac_driver cxmac_driver = "CX-MAC", cxmac_init, qsend_packet, - read_packet, - set_receive_function, + input_packet, turn_on, turn_off, channel_check_interval, diff --git a/core/net/mac/cxmac.h b/core/net/mac/cxmac.h index fd76b8416..e9d9605b2 100644 --- a/core/net/mac/cxmac.h +++ b/core/net/mac/cxmac.h @@ -28,7 +28,7 @@ * * This file is part of the Contiki operating system. * - * $Id: cxmac.h,v 1.3 2010/01/31 18:44:23 adamdunkels Exp $ + * $Id: cxmac.h,v 1.4 2010/02/18 21:48:39 adamdunkels Exp $ */ /** @@ -60,10 +60,5 @@ struct cxmac_config { extern const struct mac_driver cxmac_driver; -const struct mac_driver *cxmac_init(const struct radio_driver *d); - -extern struct cxmac_config cxmac_config; - -void cxmac_set_announcement_radio_txpower(int txpower); #endif /* __CXMAC_H__ */ diff --git a/core/net/mac/lpp.c b/core/net/mac/lpp.c index 2c681111a..66e367347 100644 --- a/core/net/mac/lpp.c +++ b/core/net/mac/lpp.c @@ -28,7 +28,7 @@ * * This file is part of the Contiki operating system. * - * $Id: lpp.c,v 1.30 2010/02/02 23:28:58 adamdunkels Exp $ + * $Id: lpp.c,v 1.31 2010/02/18 21:48:39 adamdunkels Exp $ */ /** @@ -55,6 +55,7 @@ #include "lib/memb.h" #include "lib/random.h" #include "net/rime.h" +#include "net/netstack.h" #include "net/mac/mac.h" #include "net/mac/lpp.h" #include "net/rime/packetbuf.h" @@ -73,7 +74,7 @@ #define PRINTF(...) #endif -#define WITH_ACK_OPTIMIZATION 0 +#define WITH_ACK_OPTIMIZATION 1 #define WITH_PROBE_AFTER_RECEPTION 0 #define WITH_PROBE_AFTER_TRANSMISSION 0 #define WITH_ENCOUNTER_OPTIMIZATION 1 @@ -142,8 +143,6 @@ static uint8_t lpp_is_on; static struct compower_activity current_packet; -static const struct radio_driver *radio; -static void (* receiver_callback)(const struct mac_driver *); static struct pt dutycycle_pt; static struct ctimer timer; @@ -156,6 +155,9 @@ struct queue_list_item { struct queuebuf *packet; struct ctimer removal_timer; struct compower_activity compower; + mac_callback_t sent_callback; + void *sent_callback_ptr; + uint8_t num_transmissions; #if WITH_PENDING_BROADCAST uint8_t broadcast_flag; #endif /* WITH_PENDING_BROADCAST */ @@ -192,7 +194,7 @@ static struct ctimer stream_probe_timer, stream_off_timer; static void turn_radio_on(void) { - radio->on(); + NETSTACK_RADIO.on(); /* leds_on(LEDS_YELLOW);*/ } /*---------------------------------------------------------------------------*/ @@ -200,7 +202,7 @@ static void turn_radio_off(void) { if(lpp_is_on && is_streaming == 0) { - radio->off(); + NETSTACK_RADIO.off(); } /* leds_off(LEDS_YELLOW);*/ } @@ -348,12 +350,16 @@ static void remove_queued_packet(void *item) { struct queue_list_item *i = item; + mac_callback_t sent; + void *ptr; + int num_transmissions = 0; + int status; PRINTF("%d.%d: removing queued packet\n", rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1]); - ctimer_stop(&i->removal_timer); + ctimer_stop(&i->removal_timer); queuebuf_free(i->packet); list_remove(pending_packets_list, i); list_remove(queued_packets_list, i); @@ -364,7 +370,16 @@ remove_queued_packet(void *item) compower_accumulate(&i->compower); } + sent = i->sent_callback; + ptr = i->sent_callback_ptr; + num_transmissions = i->num_transmissions; memb_free(&queued_packets_memb, i); + if(num_transmissions == 0) { + status = MAC_TX_ERR; + } else { + status = MAC_TX_OK; + } + mac_call_sent_callback(sent, ptr, status, num_transmissions); } /*---------------------------------------------------------------------------*/ #if WITH_PENDING_BROADCAST @@ -423,7 +438,7 @@ send_probe(void) /* XXX should first check access to the medium (CCA - Clear Channel Assessment) and add LISTEN_TIME to off_time_adjustment if there is a packet in the air. */ - radio->send(packetbuf_hdrptr(), packetbuf_totlen()); + NETSTACK_RADIO.send(packetbuf_hdrptr(), packetbuf_totlen()); compower_accumulate(&compower_idle_activity); } @@ -579,8 +594,8 @@ restart_dutycycle(clock_time_t initial_wait) * immediately. * */ -static int -send_packet(void) +static void +send_packet(mac_callback_t sent, void *ptr) { struct lpp_hdr hdr; clock_time_t timeout; @@ -604,8 +619,9 @@ send_packet(void) #if WITH_ACK_OPTIMIZATION if(packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) == PACKETBUF_ATTR_PACKET_TYPE_ACK) { /* Send ACKs immediately. */ - radio->send(packetbuf_hdrptr(), packetbuf_totlen()); - return 1; + NETSTACK_RADIO.send(packetbuf_hdrptr(), packetbuf_totlen()); + mac_call_sent_callback(sent, ptr, MAC_TX_OK, 1); + return; } #endif /* WITH_ACK_OPTIMIZATION */ @@ -618,10 +634,15 @@ send_packet(void) struct queue_list_item *i; i = memb_alloc(&queued_packets_memb); if(i != NULL) { + i->sent_callback = sent; + i->sent_callback_ptr = ptr; + i->num_transmissions = 0; i->packet = queuebuf_new_from_packetbuf(); if(i->packet == NULL) { memb_free(&queued_packets_memb, i); - return 0; + printf("null packet\n"); + mac_call_sent_callback(sent, ptr, MAC_TX_ERR, 0); + return; } else { if(is_broadcast) { timeout = PACKET_LIFETIME; @@ -651,9 +672,11 @@ send_packet(void) turn_radio_on_for_neighbor(&hdr.receiver, i); } + } else { + printf("i == NULL\n"); + mac_call_sent_callback(sent, ptr, MAC_TX_ERR, 0); } } - return 1; } /*---------------------------------------------------------------------------*/ /** @@ -662,204 +685,192 @@ send_packet(void) * destination address of the queued packet (if any), the queued packet * is sent. */ -static int -read_packet(void) +static void +input_packet(void) { - int len; struct lpp_hdr *hdr; clock_time_t reception_time; reception_time = clock_time(); - - packetbuf_clear(); - len = radio->read(packetbuf_dataptr(), PACKETBUF_SIZE); - if(len > sizeof(struct lpp_hdr)) { - packetbuf_set_datalen(len); - hdr = packetbuf_dataptr(); - packetbuf_hdrreduce(sizeof(struct lpp_hdr)); - /* PRINTF("got packet type %d\n", hdr->type);*/ - if(hdr->type == TYPE_PROBE) { - /* Parse incoming announcements */ - struct announcement_msg *adata = packetbuf_dataptr(); - int i; + hdr = packetbuf_dataptr(); + packetbuf_hdrreduce(sizeof(struct lpp_hdr)); + /* PRINTF("got packet type %d\n", hdr->type);*/ + + if(hdr->type == TYPE_PROBE) { + /* Parse incoming announcements */ + struct announcement_msg *adata = packetbuf_dataptr(); + int i; - /* PRINTF("%d.%d: probe from %d.%d with %d announcements\n", - rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], - hdr->sender.u8[0], hdr->sender.u8[1], adata->num);*/ + /* PRINTF("%d.%d: probe from %d.%d with %d announcements\n", + rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], + hdr->sender.u8[0], hdr->sender.u8[1], adata->num);*/ - for(i = 0; i < adata->num; ++i) { - /* PRINTF("%d.%d: announcement %d: %d\n", + for(i = 0; i < adata->num; ++i) { + /* PRINTF("%d.%d: announcement %d: %d\n", rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], adata->data[i].id, adata->data[i].value);*/ - announcement_heard(&hdr->sender, - adata->data[i].id, - adata->data[i].value); - } + announcement_heard(&hdr->sender, + adata->data[i].id, + adata->data[i].value); + } - /* Register the encounter with the sending node. We now know the - neighbor's phase. */ - register_encounter(&hdr->sender, reception_time); + /* Register the encounter with the sending node. We now know the + neighbor's phase. */ + register_encounter(&hdr->sender, reception_time); - /* Go through the list of packets to be sent to see if any of - them match the sender of the probe, or if they are a - broadcast packet that should be sent. */ - if(list_length(queued_packets_list) > 0) { - struct queue_list_item *i; - for(i = list_head(queued_packets_list); i != NULL; i = i->next) { - struct lpp_hdr *qhdr; + /* Go through the list of packets to be sent to see if any of + them match the sender of the probe, or if they are a + broadcast packet that should be sent. */ + if(list_length(queued_packets_list) > 0) { + struct queue_list_item *i; + for(i = list_head(queued_packets_list); i != NULL; i = i->next) { + struct lpp_hdr *qhdr; - qhdr = queuebuf_dataptr(i->packet); - if(rimeaddr_cmp(&qhdr->receiver, &hdr->sender) || - rimeaddr_cmp(&qhdr->receiver, &rimeaddr_null)) { - queuebuf_to_packetbuf(i->packet); + qhdr = queuebuf_dataptr(i->packet); + if(rimeaddr_cmp(&qhdr->receiver, &hdr->sender) || + rimeaddr_cmp(&qhdr->receiver, &rimeaddr_null)) { + queuebuf_to_packetbuf(i->packet); #if WITH_PENDING_BROADCAST - if(i->broadcast_flag == BROADCAST_FLAG_NONE || - i->broadcast_flag == BROADCAST_FLAG_SEND) { - radio->send(queuebuf_dataptr(i->packet), - queuebuf_datalen(i->packet)); - PRINTF("%d.%d: got a probe from %d.%d, sent packet to %d.%d\n", + if(i->broadcast_flag == BROADCAST_FLAG_NONE || + i->broadcast_flag == BROADCAST_FLAG_SEND) { + i->num_transmissions = 1; + NETSTACK_RADIO.send(queuebuf_dataptr(i->packet), + queuebuf_datalen(i->packet)); + PRINTF("%d.%d: got a probe from %d.%d, sent packet to %d.%d\n", rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], - hdr->sender.u8[0], hdr->sender.u8[1], - qhdr->receiver.u8[0], qhdr->receiver.u8[1]); + hdr->sender.u8[0], hdr->sender.u8[1], + qhdr->receiver.u8[0], qhdr->receiver.u8[1]); - } else { - PRINTF("%d.%d: got a probe from %d.%d, did not send packet\n", - rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], - hdr->sender.u8[0], hdr->sender.u8[1]); - } + } else { + PRINTF("%d.%d: got a probe from %d.%d, did not send packet\n", + rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], + hdr->sender.u8[0], hdr->sender.u8[1]); + } #else /* WITH_PENDING_BROADCAST */ - radio->send(queuebuf_dataptr(i->packet), - queuebuf_datalen(i->packet)); - PRINTF("%d.%d: got a probe from %d.%d, sent packet to %d.%d\n", - rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], - hdr->sender.u8[0], hdr->sender.u8[1], - qhdr->receiver.u8[0], qhdr->receiver.u8[1]); + i->num_transmissions = 1; + NETSTACK_RADIO.send(queuebuf_dataptr(i->packet), + queuebuf_datalen(i->packet)); + PRINTF("%d.%d: got a probe from %d.%d, sent packet to %d.%d\n", + rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], + hdr->sender.u8[0], hdr->sender.u8[1], + qhdr->receiver.u8[0], qhdr->receiver.u8[1]); #endif /* WITH_PENDING_BROADCAST */ - /* Attribute the energy spent on listening for the probe - to this packet transmission. */ - compower_accumulate(&i->compower); + /* Attribute the energy spent on listening for the probe + to this packet transmission. */ + compower_accumulate(&i->compower); - /* If the packet was not a broadcast packet, we dequeue it - now. Broadcast packets should be transmitted to all - neighbors, and are dequeued by the dutycycling function - instead, after the appropriate time. */ - if(!rimeaddr_cmp(&qhdr->receiver, &rimeaddr_null)) { - remove_queued_packet(i); + /* If the packet was not a broadcast packet, we dequeue it + now. Broadcast packets should be transmitted to all + neighbors, and are dequeued by the dutycycling function + instead, after the appropriate time. */ + if(!rimeaddr_cmp(&qhdr->receiver, &rimeaddr_null)) { + remove_queued_packet(i); #if WITH_PROBE_AFTER_TRANSMISSION - /* Send a probe packet to catch any reply from the other node. */ - restart_dutycycle(PROBE_AFTER_TRANSMISSION_TIME); + /* Send a probe packet to catch any reply from the other node. */ + restart_dutycycle(PROBE_AFTER_TRANSMISSION_TIME); #endif /* WITH_PROBE_AFTER_TRANSMISSION */ #if WITH_STREAMING - if(is_streaming) { - ctimer_set(&stream_probe_timer, STREAM_PROBE_TIME, - send_stream_probe, NULL); - } + if(is_streaming) { + ctimer_set(&stream_probe_timer, STREAM_PROBE_TIME, + send_stream_probe, NULL); + } #endif /* WITH_STREAMING */ - } + } #if WITH_ACK_OPTIMIZATION - if(packetbuf_attr(PACKETBUF_ATTR_RELIABLE) || - packetbuf_attr(PACKETBUF_ATTR_ERELIABLE)) { - /* We're sending a packet that needs an ACK, so we keep - the radio on in anticipation of the ACK. */ - turn_radio_on(); - } + if(packetbuf_attr(PACKETBUF_ATTR_RELIABLE) || + packetbuf_attr(PACKETBUF_ATTR_ERELIABLE)) { + /* We're sending a packet that needs an ACK, so we keep + the radio on in anticipation of the ACK. */ + turn_radio_on(); + } #endif /* WITH_ACK_OPTIMIZATION */ - } - } - } - - } else if(hdr->type == TYPE_DATA) { - if(!rimeaddr_cmp(&hdr->receiver, &rimeaddr_null)) { - if(!rimeaddr_cmp(&hdr->receiver, &rimeaddr_node_addr)) { - /* Not broadcast or for us */ - PRINTF("%d.%d: data not for us from %d.%d\n", - rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], - hdr->sender.u8[0], hdr->sender.u8[1]); - return 0; } - packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, &hdr->receiver); } - packetbuf_set_addr(PACKETBUF_ADDR_SENDER, &hdr->sender); + } - PRINTF("%d.%d: got data from %d.%d\n", - rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], - hdr->sender.u8[0], hdr->sender.u8[1]); + } else if(hdr->type == TYPE_DATA) { + if(!rimeaddr_cmp(&hdr->receiver, &rimeaddr_null)) { + if(!rimeaddr_cmp(&hdr->receiver, &rimeaddr_node_addr)) { + /* Not broadcast or for us */ + PRINTF("%d.%d: data not for us from %d.%d\n", + rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], + hdr->sender.u8[0], hdr->sender.u8[1]); + return; + } + packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, &hdr->receiver); + } + packetbuf_set_addr(PACKETBUF_ADDR_SENDER, &hdr->sender); - /* Accumulate the power consumption for the packet reception. */ - compower_accumulate(¤t_packet); - /* Convert the accumulated power consumption for the received - packet to packet attributes so that the higher levels can - keep track of the amount of energy spent on receiving the - packet. */ - compower_attrconv(¤t_packet); + PRINTF("%d.%d: got data from %d.%d\n", + rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], + hdr->sender.u8[0], hdr->sender.u8[1]); + + /* Accumulate the power consumption for the packet reception. */ + compower_accumulate(¤t_packet); + /* Convert the accumulated power consumption for the received + packet to packet attributes so that the higher levels can + keep track of the amount of energy spent on receiving the + packet. */ + compower_attrconv(¤t_packet); - /* Clear the accumulated power consumption so that it is ready - for the next packet. */ - compower_clear(¤t_packet); + /* Clear the accumulated power consumption so that it is ready + for the next packet. */ + compower_clear(¤t_packet); #if WITH_PENDING_BROADCAST - if(rimeaddr_cmp(&hdr->receiver, &rimeaddr_null)) { - /* This is a broadcast packet. Check the list of pending - packets to see if we are currently sending a broadcast. If - so, we refrain from sending our broadcast until one sleep - cycle period, so that the other broadcaster will have - finished sending. */ + if(rimeaddr_cmp(&hdr->receiver, &rimeaddr_null)) { + /* This is a broadcast packet. Check the list of pending + packets to see if we are currently sending a broadcast. If + so, we refrain from sending our broadcast until one sleep + cycle period, so that the other broadcaster will have + finished sending. */ - struct queue_list_item *i; - for(i = list_head(queued_packets_list); i != NULL; i = i->next) { - /* If the packet is a broadcast packet that is not yet - ready to be sent, we do not send it. */ - if(i->broadcast_flag == BROADCAST_FLAG_PENDING) { - PRINTF("Someone else is sending, pending -> waiting\n"); - set_broadcast_flag(i, BROADCAST_FLAG_WAITING); - } - } - } -#endif /* WITH_PENDING_BROADCAST */ - - -#if WITH_PROBE_AFTER_RECEPTION - /* XXX send probe after receiving a packet to facilitate data - streaming. We must first copy the contents of the packetbuf into - a queuebuf to avoid overwriting the data with the probe packet. */ - if(rimeaddr_cmp(&hdr->receiver, &rimeaddr_node_addr)) { - struct queuebuf *q; - q = queuebuf_new_from_packetbuf(); - if(q != NULL) { - send_probe(); - queuebuf_to_packetbuf(q); - queuebuf_free(q); + struct queue_list_item *i; + for(i = list_head(queued_packets_list); i != NULL; i = i->next) { + /* If the packet is a broadcast packet that is not yet + ready to be sent, we do not send it. */ + if(i->broadcast_flag == BROADCAST_FLAG_PENDING) { + PRINTF("Someone else is sending, pending -> waiting\n"); + set_broadcast_flag(i, BROADCAST_FLAG_WAITING); } } + } +#endif /* WITH_PENDING_BROADCAST */ + + +#if WITH_PROBE_AFTER_RECEPTION + /* XXX send probe after receiving a packet to facilitate data + streaming. We must first copy the contents of the packetbuf into + a queuebuf to avoid overwriting the data with the probe packet. */ + if(rimeaddr_cmp(&hdr->receiver, &rimeaddr_node_addr)) { + struct queuebuf *q; + q = queuebuf_new_from_packetbuf(); + if(q != NULL) { + send_probe(); + queuebuf_to_packetbuf(q); + queuebuf_free(q); + } + } #endif /* WITH_PROBE_AFTER_RECEPTION */ #if WITH_ADAPTIVE_OFF_TIME - off_time = LOWEST_OFF_TIME; - restart_dutycycle(off_time); + off_time = LOWEST_OFF_TIME; + restart_dutycycle(off_time); #endif /* WITH_ADAPTIVE_OFF_TIME */ - - } - len = packetbuf_datalen(); + NETSTACK_MAC.input(); } - return len; -} -/*---------------------------------------------------------------------------*/ -static void -set_receive_function(void (* recv)(const struct mac_driver *)) -{ - receiver_callback = recv; } /*---------------------------------------------------------------------------*/ static int @@ -888,30 +899,9 @@ channel_check_interval(void) return OFF_TIME + LISTEN_TIME; } /*---------------------------------------------------------------------------*/ -const struct mac_driver lpp_driver = { - "LPP", - lpp_init, - send_packet, - read_packet, - set_receive_function, - on, - off, - channel_check_interval, -}; -/*---------------------------------------------------------------------------*/ static void -input_packet(const struct radio_driver *d) +init(void) { - if(receiver_callback) { - receiver_callback(&lpp_driver); - } -} -/*---------------------------------------------------------------------------*/ -const struct mac_driver * -lpp_init(const struct radio_driver *d) -{ - radio = d; - radio->set_receive_function(input_packet); restart_dutycycle(random_rand() % OFF_TIME); lpp_is_on = 1; @@ -921,6 +911,15 @@ lpp_init(const struct radio_driver *d) memb_init(&queued_packets_memb); list_init(queued_packets_list); list_init(pending_packets_list); - return &lpp_driver; } /*---------------------------------------------------------------------------*/ +const struct mac_driver lpp_driver = { + "LPP", + init, + send_packet, + input_packet, + on, + off, + channel_check_interval, +}; +/*---------------------------------------------------------------------------*/ diff --git a/core/net/mac/mac.c b/core/net/mac/mac.c new file mode 100644 index 000000000..199c6a389 --- /dev/null +++ b/core/net/mac/mac.c @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2010, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + * + * $Id: mac.c,v 1.1 2010/02/18 21:48:39 adamdunkels Exp $ + */ + +#include "net/mac/mac.h" + +#include + +/*---------------------------------------------------------------------------*/ +void +mac_call_sent_callback(mac_callback_t sent, void *ptr, int status, int num_tx) +{ + /* printf("mac_callback_t %p ptr %p status %d num_tx %d\n", + sent, ptr, status, num_tx);*/ + /* switch(status) { + case MAC_TX_COLLISION: + printf("mac: collision after %d tx\n", num_tx); + break; + case MAC_TX_NOACK: + printf("mac: noack after %d tx\n", num_tx); + break; + case MAC_TX_OK: + printf("mac: sent after %d tx\n", num_tx); + break; + default: + printf("mac: error %d after %d tx\n", status, num_tx); + }*/ + + if(sent) { + sent(ptr, status, num_tx); + } +} +/*---------------------------------------------------------------------------*/ diff --git a/core/net/mac/mac.h b/core/net/mac/mac.h index 4d6344ac3..49f615a18 100644 --- a/core/net/mac/mac.h +++ b/core/net/mac/mac.h @@ -28,7 +28,7 @@ * * This file is part of the Contiki operating system. * - * $Id: mac.h,v 1.11 2010/02/03 16:45:12 adamdunkels Exp $ + * $Id: mac.h,v 1.12 2010/02/18 21:48:39 adamdunkels Exp $ */ /** @@ -44,6 +44,11 @@ #include "contiki-conf.h" #include "dev/radio.h" + +typedef void (* mac_callback_t)(void *ptr, int status, int transmissions); + +void mac_call_sent_callback(mac_callback_t sent, void *ptr, int status, int num_tx); + /** * The structure of a MAC protocol driver in Contiki. */ @@ -51,17 +56,14 @@ struct mac_driver { char *name; /** Initialize the MAC driver */ - const struct mac_driver *(* init)(const struct radio_driver *r); + void (* init)(void); /** Send a packet from the Rime buffer */ - int (* send)(void); - - /** Read a received packet into the Rime buffer. */ - int (* read)(void); - - /** Set a function to be called when a packet has been received. */ - void (* set_receive_function)(void (*f)(const struct mac_driver *d)); + void (* send)(mac_callback_t sent_callback, void *ptr); + /** Callback for getting notified of incoming packet. */ + void (* input)(void); + /** Turn the MAC layer on. */ int (* on)(void); diff --git a/core/net/mac/nullmac.c b/core/net/mac/nullmac.c index 02153f660..e191daaa7 100644 --- a/core/net/mac/nullmac.c +++ b/core/net/mac/nullmac.c @@ -28,7 +28,7 @@ * * This file is part of the Contiki operating system. * - * $Id: nullmac.c,v 1.13 2010/01/25 11:43:32 adamdunkels Exp $ + * $Id: nullmac.c,v 1.14 2010/02/18 21:48:39 adamdunkels Exp $ */ /** @@ -40,57 +40,31 @@ #include "net/mac/nullmac.h" #include "net/rime/packetbuf.h" +#include "net/netstack.h" -static const struct radio_driver *radio; -static void (* receiver_callback)(const struct mac_driver *); /*---------------------------------------------------------------------------*/ -static int -send_packet(void) +static void +send_packet(mac_callback_t sent, void *ptr) { - if(radio->send(packetbuf_hdrptr(), packetbuf_totlen()) == RADIO_TX_OK) { - return MAC_TX_OK; - } - return MAC_TX_ERR; + NETSTACK_RDC.send(sent, ptr); } /*---------------------------------------------------------------------------*/ static void -input_packet(const struct radio_driver *d) +packet_input(void) { - if(receiver_callback) { - receiver_callback(&nullmac_driver); - } -} -/*---------------------------------------------------------------------------*/ -static int -read_packet(void) -{ - int len; - packetbuf_clear(); - len = radio->read(packetbuf_dataptr(), PACKETBUF_SIZE); - packetbuf_set_datalen(len); - return len; -} -/*---------------------------------------------------------------------------*/ -static void -set_receive_function(void (* recv)(const struct mac_driver *)) -{ - receiver_callback = recv; + NETSTACK_NETWORK.input(); } /*---------------------------------------------------------------------------*/ static int on(void) { - return radio->on(); + return NETSTACK_RDC.on(); } /*---------------------------------------------------------------------------*/ static int off(int keep_radio_on) { - if(keep_radio_on) { - return radio->on(); - } else { - return radio->off(); - } + return NETSTACK_RDC.off(keep_radio_on); } /*---------------------------------------------------------------------------*/ static unsigned short @@ -99,23 +73,18 @@ channel_check_interval(void) return 0; } /*---------------------------------------------------------------------------*/ +static void +init(void) +{ +} +/*---------------------------------------------------------------------------*/ const struct mac_driver nullmac_driver = { "nullmac", - nullmac_init, + init, send_packet, - read_packet, - set_receive_function, + packet_input, on, off, channel_check_interval, }; /*---------------------------------------------------------------------------*/ -const struct mac_driver * -nullmac_init(const struct radio_driver *d) -{ - radio = d; - radio->set_receive_function(input_packet); - radio->on(); - return &nullmac_driver; -} -/*---------------------------------------------------------------------------*/ diff --git a/core/net/mac/nullmac.h b/core/net/mac/nullmac.h index a6f32964b..3ddc1a9b3 100644 --- a/core/net/mac/nullmac.h +++ b/core/net/mac/nullmac.h @@ -28,7 +28,7 @@ * * This file is part of the Contiki operating system. * - * $Id: nullmac.h,v 1.3 2007/10/23 20:57:37 adamdunkels Exp $ + * $Id: nullmac.h,v 1.4 2010/02/18 21:48:39 adamdunkels Exp $ */ /** @@ -46,6 +46,5 @@ extern const struct mac_driver nullmac_driver; -const struct mac_driver *nullmac_init(const struct radio_driver *r); #endif /* __NULLMAC_H__ */ diff --git a/core/net/mac/nullrdc.c b/core/net/mac/nullrdc.c new file mode 100644 index 000000000..f30be8f25 --- /dev/null +++ b/core/net/mac/nullrdc.c @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2007, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + * + * $Id: nullrdc.c,v 1.1 2010/02/18 21:48:39 adamdunkels Exp $ + */ + +/** + * \file + * A MAC protocol that does not do anything. + * \author + * Adam Dunkels + */ + +#include "net/mac/nullrdc.h" +#include "net/rime/packetbuf.h" +#include "net/netstack.h" + +/*---------------------------------------------------------------------------*/ +static void +send_packet(mac_callback_t sent, void *ptr) +{ + int ret; + if(NETSTACK_RADIO.send(packetbuf_hdrptr(), packetbuf_totlen()) == RADIO_TX_OK) { + ret = MAC_TX_OK; + } else { + ret = MAC_TX_ERR; + } + mac_call_sent_callback(sent, ptr, ret, 1); +} +/*---------------------------------------------------------------------------*/ +static void +packet_input(void) +{ + NETSTACK_MAC.input(); +} +/*---------------------------------------------------------------------------*/ +static int +on(void) +{ + return NETSTACK_RADIO.on(); +} +/*---------------------------------------------------------------------------*/ +static int +off(int keep_radio_on) +{ + if(keep_radio_on) { + return NETSTACK_RADIO.on(); + } else { + return NETSTACK_RADIO.off(); + } +} +/*---------------------------------------------------------------------------*/ +static unsigned short +channel_check_interval(void) +{ + return 0; +} +/*---------------------------------------------------------------------------*/ +static void +init(void) +{ + on(); +} +/*---------------------------------------------------------------------------*/ +const struct mac_driver nullrdc_driver = { + "nullrdc", + init, + send_packet, + packet_input, + on, + off, + channel_check_interval, +}; +/*---------------------------------------------------------------------------*/ diff --git a/core/net/mac/nullrdc.h b/core/net/mac/nullrdc.h new file mode 100644 index 000000000..f2e9f3729 --- /dev/null +++ b/core/net/mac/nullrdc.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2007, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + * + * $Id: nullrdc.h,v 1.1 2010/02/18 21:48:39 adamdunkels Exp $ + */ + +/** + * \file + * A MAC protocol implementation that does not do anything. + * \author + * Adam Dunkels + */ + +#ifndef __NULLRDC_H__ +#define __NULLRDC_H__ + +#include "net/mac/mac.h" +#include "dev/radio.h" + +extern const struct mac_driver nullrdc_driver; + + +#endif /* __NULLRDC_H__ */ diff --git a/core/net/mac/sicslowmac.c b/core/net/mac/sicslowmac.c index 1d629c58a..5ed776af5 100644 --- a/core/net/mac/sicslowmac.c +++ b/core/net/mac/sicslowmac.c @@ -28,7 +28,7 @@ * * This file is part of the Contiki operating system. * - * $Id: sicslowmac.c,v 1.4 2009/09/18 16:37:17 nifi Exp $ + * $Id: sicslowmac.c,v 1.5 2010/02/18 21:48:39 adamdunkels Exp $ */ @@ -48,6 +48,7 @@ #include "net/mac/sicslowmac.h" #include "net/mac/frame802154.h" #include "net/rime/packetbuf.h" +#include "net/netstack.h" #include "lib/random.h" #define DEBUG 0 @@ -79,8 +80,6 @@ static uint16_t mac_dst_pan_id = IEEE802154_PANID; */ static uint16_t mac_src_pan_id = IEEE802154_PANID; -static const struct radio_driver *radio; -static void (* receiver_callback)(const struct mac_driver *); /*---------------------------------------------------------------------------*/ static int is_broadcast_addr(uint8_t mode, uint8_t *addr) @@ -94,8 +93,8 @@ is_broadcast_addr(uint8_t mode, uint8_t *addr) return 1; } /*---------------------------------------------------------------------------*/ -static int -send_packet(void) +static void +send_packet(mac_callback_t sent, void *ptr) { frame802154_t params; uint8_t len; @@ -131,11 +130,12 @@ send_packet(void) if(rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), &rimeaddr_null)) { /* Broadcast requires short address mode. */ params.fcf.dest_addr_mode = FRAME802154_SHORTADDRMODE; - params.dest_addr.u8[0] = 0xFF; - params.dest_addr.u8[1] = 0xFF; + params.dest_addr[0] = 0xFF; + params.dest_addr[1] = 0xFF; } else { - rimeaddr_copy(¶ms.dest_addr, packetbuf_addr(PACKETBUF_ADDR_RECEIVER)); + rimeaddr_copy((rimeaddr_t *)¶ms.dest_addr, + packetbuf_addr(PACKETBUF_ADDR_RECEIVER)); params.fcf.dest_addr_mode = FRAME802154_LONGADDRMODE; } @@ -146,115 +146,104 @@ send_packet(void) * Set up the source address using only the long address mode for * phase 1. */ - rimeaddr_copy(¶ms.src_addr, &rimeaddr_node_addr); + rimeaddr_copy((rimeaddr_t *)¶ms.src_addr, &rimeaddr_node_addr); params.payload = packetbuf_dataptr(); params.payload_len = packetbuf_datalen(); len = frame802154_hdrlen(¶ms); if(packetbuf_hdralloc(len)) { + int ret; frame802154_create(¶ms, packetbuf_hdrptr(), len); PRINTF("6MAC-UT: %2X", params.fcf.frame_type); PRINTADDR(params.dest_addr.u8); PRINTF("%u %u (%u)\n", len, packetbuf_datalen(), packetbuf_totlen()); - return radio->send(packetbuf_hdrptr(), packetbuf_totlen()); + ret = NETSTACK_RADIO.send(packetbuf_hdrptr(), packetbuf_totlen()); + if(sent) { + switch(ret) { + case RADIO_TX_OK: + sent(ptr, MAC_TX_OK, 1); + break; + case RADIO_TX_ERR: + sent(ptr, MAC_TX_ERR, 1); + break; + } + } } else { PRINTF("6MAC-UT: too large header: %u\n", len); } - return 0; } /*---------------------------------------------------------------------------*/ static void -input_packet(const struct radio_driver *d) -{ - if(receiver_callback) { - receiver_callback(&sicslowmac_driver); - } -} -/*---------------------------------------------------------------------------*/ -static int -read_packet(void) +input_packet(void) { frame802154_t frame; int len; - packetbuf_clear(); - len = radio->read(packetbuf_dataptr(), PACKETBUF_SIZE); - if(len > 0) { - packetbuf_set_datalen(len); - if(frame802154_parse(packetbuf_dataptr(), len, &frame) && - packetbuf_hdrreduce(len - frame.payload_len)) { - if(frame.fcf.dest_addr_mode) { - if(frame.dest_pid != mac_src_pan_id && - frame.dest_pid != FRAME802154_BROADCASTPANDID) { - /* Not broadcast or for our PAN */ - PRINTF("6MAC: for another pan %u\n", frame.dest_pid); - return 0; - } - if(!is_broadcast_addr(frame.fcf.dest_addr_mode, frame.dest_addr.u8)) { - packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, &frame.dest_addr); - if(!rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), - &rimeaddr_node_addr)) { - /* Not for this node */ - PRINTF("6MAC: not for us\n"); - return 0; - } + + len = packetbuf_datalen(); + + if(frame802154_parse(packetbuf_dataptr(), len, &frame) && + packetbuf_hdrreduce(len - frame.payload_len)) { + if(frame.fcf.dest_addr_mode) { + if(frame.dest_pid != mac_src_pan_id && + frame.dest_pid != FRAME802154_BROADCASTPANDID) { + /* Not broadcast or for our PAN */ + PRINTF("6MAC: for another pan %u\n", frame.dest_pid); + return; + } + if(!is_broadcast_addr(frame.fcf.dest_addr_mode, frame.dest_addr)) { + packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, (rimeaddr_t *)&frame.dest_addr); + if(!rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), + &rimeaddr_node_addr)) { + /* Not for this node */ + PRINTF("6MAC: not for us\n"); + return; } } - packetbuf_set_addr(PACKETBUF_ADDR_SENDER, &frame.src_addr); - - PRINTF("6MAC-IN: %2X", frame.fcf.frame_type); - PRINTADDR(packetbuf_addr(PACKETBUF_ADDR_SENDER)); - PRINTADDR(packetbuf_addr(PACKETBUF_ADDR_RECEIVER)); - PRINTF("%u\n", packetbuf_datalen()); - return packetbuf_datalen(); - } else { - PRINTF("6MAC: failed to parse hdr\n"); } + packetbuf_set_addr(PACKETBUF_ADDR_SENDER, (rimeaddr_t *)&frame.src_addr); + + PRINTF("6MAC-IN: %2X", frame.fcf.frame_type); + PRINTADDR(packetbuf_addr(PACKETBUF_ADDR_SENDER)); + PRINTADDR(packetbuf_addr(PACKETBUF_ADDR_RECEIVER)); + PRINTF("%u\n", packetbuf_datalen()); + NETSTACK_MAC.input(); + } else { + PRINTF("6MAC: failed to parse hdr\n"); } - return 0; -} -/*---------------------------------------------------------------------------*/ -static void -set_receive_function(void (* recv)(const struct mac_driver *)) -{ - receiver_callback = recv; } /*---------------------------------------------------------------------------*/ static int on(void) { - return radio->on(); + return NETSTACK_RADIO.on(); } /*---------------------------------------------------------------------------*/ static int off(int keep_radio_on) { if(keep_radio_on) { - return radio->on(); + return NETSTACK_RADIO.on(); } else { - return radio->off(); + return NETSTACK_RADIO.off(); } } /*---------------------------------------------------------------------------*/ +static void +init(void) +{ + mac_dsn = random_rand() % 256; + + NETSTACK_RADIO.on(); +} +/*---------------------------------------------------------------------------*/ const struct mac_driver sicslowmac_driver = { "sicslowmac", - sicslowmac_init, + init, send_packet, - read_packet, - set_receive_function, + input_packet, on, off, }; /*---------------------------------------------------------------------------*/ -const struct mac_driver * -sicslowmac_init(const struct radio_driver *d) -{ - mac_dsn = random_rand() % 256; - - radio = d; - radio->set_receive_function(input_packet); - radio->on(); - return &sicslowmac_driver; -} -/*---------------------------------------------------------------------------*/ diff --git a/core/net/mac/xmac.c b/core/net/mac/xmac.c index a6b2eb4a1..de2df1c47 100644 --- a/core/net/mac/xmac.c +++ b/core/net/mac/xmac.c @@ -28,7 +28,7 @@ * * This file is part of the Contiki operating system. * - * $Id: xmac.c,v 1.52 2010/02/03 01:17:32 adamdunkels Exp $ + * $Id: xmac.c,v 1.53 2010/02/18 21:48:39 adamdunkels Exp $ */ /** @@ -44,6 +44,7 @@ #include "dev/radio.h" #include "dev/watchdog.h" #include "lib/random.h" +#include "net/netstack.h" #include "net/mac/framer.h" #include "net/mac/xmac.h" #include "net/rime.h" @@ -157,8 +158,6 @@ static volatile unsigned char someone_is_sending = 0; static volatile unsigned char we_are_sending = 0; static volatile unsigned char radio_is_on = 0; -static const struct radio_driver *radio; - #undef LEDS_ON #undef LEDS_OFF #undef LEDS_TOGGLE @@ -193,8 +192,6 @@ static int announcement_radio_txpower; for announcements from neighbors. */ static uint8_t is_listening; -static void (* receiver_callback)(const struct mac_driver *); - #if XMAC_CONF_COMPOWER static struct compower_activity current_packet; #endif /* XMAC_CONF_COMPOWER */ @@ -224,19 +221,13 @@ static rtimer_clock_t stream_until; #define MIN(a, b) ((a) < (b)? (a) : (b)) #endif /* MIN */ -/*---------------------------------------------------------------------------*/ -static void -set_receive_function(void (* recv)(const struct mac_driver *)) -{ - receiver_callback = recv; -} /*---------------------------------------------------------------------------*/ static void on(void) { if(xmac_is_on && radio_is_on == 0) { radio_is_on = 1; - radio->on(); + NETSTACK_RADIO.on(); LEDS_ON(LEDS_RED); } } @@ -247,7 +238,7 @@ off(void) if(xmac_is_on && radio_is_on != 0 && is_listening == 0 && is_streaming == 0) { radio_is_on = 0; - radio->off(); + NETSTACK_RADIO.off(); LEDS_OFF(LEDS_RED); } } @@ -566,7 +557,7 @@ send_packet(void) rtimer_clock_t now = RTIMER_NOW(); /* See if we got an ACK */ packetbuf_clear(); - len = radio->read(packetbuf_dataptr(), PACKETBUF_SIZE); + len = NETSTACK_RADIO.read(packetbuf_dataptr(), PACKETBUF_SIZE); if(len > 0) { packetbuf_set_datalen(len); if(framer_get()->parse()) { @@ -597,16 +588,16 @@ send_packet(void) if(is_broadcast) { #if WITH_STROBE_BROADCAST - radio->send(strobe, strobe_len); + NETSTACK_RADIO.send(strobe, strobe_len); #else /* restore the packet to send */ queuebuf_to_packetbuf(packet); - radio->send(packetbuf_hdrptr(), packetbuf_totlen()); + NETSTACK_RADIO.send(packetbuf_hdrptr(), packetbuf_totlen()); #endif off(); } else { rtimer_clock_t wt; - radio->send(strobe, strobe_len); + NETSTACK_RADIO.send(strobe, strobe_len); #if 1 /* Turn off the radio for a while to let the other side respond. We don't need to keep our radio on when we know @@ -644,7 +635,7 @@ send_packet(void) /* Send the data packet. */ if((is_broadcast || got_strobe_ack || is_streaming) && collisions == 0) { - radio->send(packetbuf_hdrptr(), packetbuf_totlen()); + NETSTACK_RADIO.send(packetbuf_hdrptr(), packetbuf_totlen()); } #if WITH_ENCOUNTER_OPTIMIZATION @@ -688,42 +679,28 @@ send_packet(void) } /*---------------------------------------------------------------------------*/ -static int -qsend_packet(void) +static void +qsend_packet(mac_callback_t sent, void *ptr) { + int ret; + if(someone_is_sending) { PRINTF("xmac: should queue packet, now just dropping %d %d %d %d.\n", waiting_for_packet, someone_is_sending, we_are_sending, radio_is_on); RIMESTATS_ADD(sendingdrop); - return MAC_TX_COLLISION; + ret = MAC_TX_COLLISION; } else { PRINTF("xmac: send immediately.\n"); - return send_packet(); + ret = send_packet(); } + + mac_call_sent_callback(sent, ptr, ret, 1); } /*---------------------------------------------------------------------------*/ static void -input_packet(const struct radio_driver *d) -{ - if(receiver_callback) { - receiver_callback(&xmac_driver); - } -} -/*---------------------------------------------------------------------------*/ -static int -read_packet(void) +input_packet(void) { struct xmac_hdr *hdr; - uint8_t len; - - packetbuf_clear(); - - len = radio->read(packetbuf_dataptr(), PACKETBUF_SIZE); - if(len == 0) { - return 0; - } - - packetbuf_set_datalen(len); if(framer_get()->parse()) { hdr = packetbuf_dataptr(); @@ -758,7 +735,8 @@ read_packet(void) waiting_for_packet = 0; PRINTDEBUG("xmac: data(%u)\n", packetbuf_datalen()); - return packetbuf_datalen(); + NETSTACK_MAC.input(); + return; } else { PRINTDEBUG("xmac: data not for us\n"); } @@ -785,7 +763,7 @@ read_packet(void) someone_is_sending = 1; waiting_for_packet = 1; on(); - radio->send(packetbuf_hdrptr(), packetbuf_totlen()); + NETSTACK_RADIO.send(packetbuf_hdrptr(), packetbuf_totlen()); PRINTDEBUG("xmac: send strobe ack %u\n", packetbuf_totlen()); } else { PRINTF("xmac: failed to send strobe ack\n"); @@ -804,7 +782,7 @@ read_packet(void) /* We are done processing the strobe and we therefore return to the caller. */ - return RIME_OK; + return; #if XMAC_CONF_ANNOUNCEMENTS } else if(hdr->type == TYPE_ANNOUNCEMENT) { packetbuf_hdrreduce(sizeof(struct xmac_hdr)); @@ -819,7 +797,6 @@ read_packet(void) } else { PRINTF("xmac: failed to parse (%u)\n", packetbuf_totlen()); } - return 0; } /*---------------------------------------------------------------------------*/ #if XMAC_CONF_ANNOUNCEMENTS @@ -845,7 +822,7 @@ send_announcement(void *ptr) packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, &rimeaddr_null); packetbuf_set_attr(PACKETBUF_ATTR_RADIO_TXPOWER, announcement_radio_txpower); if(framer_get()->create()) { - radio->send(packetbuf_hdrptr(), packetbuf_totlen()); + NETSTACK_RADIO.send(packetbuf_hdrptr(), packetbuf_totlen()); } } } @@ -878,8 +855,8 @@ xmac_set_announcement_radio_txpower(int txpower) #endif /* XMAC_CONF_ANNOUNCEMENTS */ } /*---------------------------------------------------------------------------*/ -const struct mac_driver * -xmac_init(const struct radio_driver *d) +static void +init(void) { radio_is_on = 0; waiting_for_packet = 0; @@ -888,8 +865,6 @@ xmac_init(const struct radio_driver *d) (void (*)(struct rtimer *, void *))powercycle, NULL); xmac_is_on = 1; - radio = d; - radio->set_receive_function(input_packet); #if WITH_ENCOUNTER_OPTIMIZATION list_init(encounter_list); @@ -901,7 +876,6 @@ xmac_init(const struct radio_driver *d) ctimer_set(&announcement_cycle_ctimer, ANNOUNCEMENT_TIME, cycle_announcement, NULL); #endif /* XMAC_CONF_ANNOUNCEMENTS */ - return &xmac_driver; } /*---------------------------------------------------------------------------*/ static int @@ -918,9 +892,9 @@ turn_off(int keep_radio_on) { xmac_is_on = 0; if(keep_radio_on) { - return radio->on(); + return NETSTACK_RADIO.on(); } else { - return radio->off(); + return NETSTACK_RADIO.off(); } } /*---------------------------------------------------------------------------*/ @@ -933,10 +907,9 @@ channel_check_interval(void) const struct mac_driver xmac_driver = { "X-MAC", - xmac_init, + init, qsend_packet, - read_packet, - set_receive_function, + input_packet, turn_on, turn_off, channel_check_interval, diff --git a/core/net/mac/xmac.h b/core/net/mac/xmac.h index 38b7a075a..8e78a2ba3 100644 --- a/core/net/mac/xmac.h +++ b/core/net/mac/xmac.h @@ -28,7 +28,7 @@ * * This file is part of the Contiki operating system. * - * $Id: xmac.h,v 1.7 2009/03/23 21:06:26 adamdunkels Exp $ + * $Id: xmac.h,v 1.8 2010/02/18 21:48:39 adamdunkels Exp $ */ /** @@ -60,10 +60,6 @@ struct xmac_config { extern const struct mac_driver xmac_driver; -const struct mac_driver *xmac_init(const struct radio_driver *d); - -extern struct xmac_config xmac_config; - void xmac_set_announcement_radio_txpower(int txpower); #endif /* __XMAC_H__ */ diff --git a/core/net/netstack.h b/core/net/netstack.h new file mode 100644 index 000000000..9c44e03e7 --- /dev/null +++ b/core/net/netstack.h @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2010, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + * + * $Id: netstack.h,v 1.1 2010/02/18 21:50:33 adamdunkels Exp $ + */ + +/** + * \file + * Include file for the Contiki low-layer network stack (NETSTACK) + * \author + * Adam Dunkels + */ + +#ifndef NETSTACK_H +#define NETSTACK_H + +#include "contiki-conf.h" + +#ifndef NETSTACK_NETWORK +#ifdef NETSTACK_CONF_NETWORK +#define NETSTACK_NETWORK NETSTACK_CONF_NETWORK +#else /* NETSTACK_CONF_NETWORK */ +#define NETSTACK_NETWORK rime_driver +#endif /* NETSTACK_CONF_NETWORK */ +#endif /* NETSTACK_NETWORK */ + +#ifndef NETSTACK_MAC +#ifdef NETSTACK_CONF_MAC +#define NETSTACK_MAC NETSTACK_CONF_MAC +#else /* NETSTACK_CONF_MAC */ +#define NETSTACK_MAC nullrdc_driver +#endif /* NETSTACK_CONF_MAC */ +#endif /* NETSTACK_MAC */ + +#ifndef NETSTACK_RDC +#ifdef NETSTACK_CONF_RDC +#define NETSTACK_RDC NETSTACK_CONF_RDC +#else /* NETSTACK_CONF_RDC */ +#define NETSTACK_RDC nullmac_driver +#endif /* NETSTACK_CONF_RDC */ +#endif /* NETSTACK_RDC */ + +#ifndef NETSTACK_RADIO +#ifdef NETSTACK_CONF_RADIO +#define NETSTACK_RADIO NETSTACK_CONF_RADIO +#else /* NETSTACK_CONF_RADIO */ +#define NETSTACK_RADIO cc2420_driver +#endif /* NETSTACK_CONF_RADIO */ +#endif /* NETSTACK_RADIO */ + +#include "net/mac/mac.h" +#include "dev/radio.h" + +extern const struct mac_driver NETSTACK_NETWORK; +extern const struct mac_driver NETSTACK_RDC; +extern const struct mac_driver NETSTACK_MAC; +extern const struct radio_driver NETSTACK_RADIO; + +#endif /* NETSTACK_H */ diff --git a/core/net/rime.h b/core/net/rime.h index db46f21d3..4ecd25801 100644 --- a/core/net/rime.h +++ b/core/net/rime.h @@ -33,7 +33,7 @@ * * This file is part of the Contiki operating system. * - * $Id: rime.h,v 1.24 2009/11/13 09:10:25 fros4943 Exp $ + * $Id: rime.h,v 1.25 2010/02/18 21:48:39 adamdunkels Exp $ */ /** @@ -76,7 +76,7 @@ * This function should be called from the system boot up * code to initialize Rime. */ -void rime_init(const struct mac_driver *); +int rime_init(void); /** * \brief Send an incoming packet to Rime @@ -106,7 +106,7 @@ void rime_input(void); void rime_driver_send(void); void rime_set_output(void (*output_function)(void)); -int rime_output(void); +void rime_output(void); extern const struct mac_driver *rime_mac; @@ -122,6 +122,7 @@ static struct rime_sniffer name = { NULL, input_callback, output_callback } void rime_sniffer_add(struct rime_sniffer *s); void rime_sniffer_remove(struct rime_sniffer *s); +extern const struct mac_driver rime_driver; /* Generic Rime return values. */ enum { diff --git a/core/net/rime/chameleon.c b/core/net/rime/chameleon.c index e35385744..ce7a99a14 100644 --- a/core/net/rime/chameleon.c +++ b/core/net/rime/chameleon.c @@ -28,7 +28,7 @@ * * This file is part of the Contiki operating system. * - * $Id: chameleon.c,v 1.7 2009/11/13 09:14:52 fros4943 Exp $ + * $Id: chameleon.c,v 1.8 2010/02/18 21:48:39 adamdunkels Exp $ */ /** @@ -141,10 +141,8 @@ chameleon_output(struct channel *c) printhdr(packetbuf_hdrptr(), packetbuf_hdrlen()); #endif /* DEBUG */ if(ret) { - if (rime_output() == RIME_OK) { - return 1; - } - return 0; + rime_output(); + return 1; } } return 0; diff --git a/core/net/rime/rime-udp.c b/core/net/rime/rime-udp.c index d5c4376cc..88fc99879 100644 --- a/core/net/rime/rime-udp.c +++ b/core/net/rime/rime-udp.c @@ -28,7 +28,7 @@ * * This file is part of the Contiki operating system. * - * $Id: rime-udp.c,v 1.4 2009/06/24 16:31:49 nvt-se Exp $ + * $Id: rime-udp.c,v 1.5 2010/02/18 21:48:39 adamdunkels Exp $ */ /** @@ -103,8 +103,8 @@ PROCESS_THREAD(rime_udp_process, ev, data) PROCESS_END(); } /*---------------------------------------------------------------------------*/ -static int -send_packet(void) +static void +send_packet(mac_callback_t sent_callback, void *ptr) { const rimeaddr_t *addr; @@ -115,6 +115,7 @@ send_packet(void) if(rimeaddr_cmp(&rimeaddr_null, addr)) { uip_udp_packet_send(broadcast_conn, packetbuf_hdrptr(), packetbuf_totlen()); + mac_call_sent_callback(sent_callback, ptr, MAC_TX_OK, 1); } else { uip_ip6addr(&unicast_conn->ripaddr, 0xfe80, 0, 0, 0, 0, 0, 0, 0); uip_netif_addr_autoconf_set(&unicast_conn->ripaddr, (uip_lladdr_t *)addr); @@ -122,11 +123,11 @@ send_packet(void) packetbuf_hdrptr(), packetbuf_totlen()); uip_create_unspecified(&unicast_conn->ripaddr); } - return 1; + return; } /*---------------------------------------------------------------------------*/ static int -read_packet(void) +input_packet(void) { packetbuf_set_datalen(uip_datalen()); return uip_datalen(); @@ -150,20 +151,26 @@ off(int keep_radio_on) return 0; } /*---------------------------------------------------------------------------*/ -const struct mac_driver rime_udp_driver = { - "rime-udp", - rime_udp_init, - send_packet, - read_packet, - set_receive_function, - on, - off, -}; -/*---------------------------------------------------------------------------*/ -const struct mac_driver * -rime_udp_init(const struct radio_driver *d) +static unsigned short +check_interval(void) { - process_start(&rime_udp_process, NULL); - return &rime_udp_driver; + return 0; } /*---------------------------------------------------------------------------*/ +static int +init(void) +{ + process_start(&rime_udp_process, NULL); + return 1; +} +/*---------------------------------------------------------------------------*/ +const struct mac_driver rime_udp_driver = { + "rime-udp", + init, + send_packet, + input_packet, + on, + off, + check_interval, +}; +/*---------------------------------------------------------------------------*/ diff --git a/core/net/rime/rime-udp.h b/core/net/rime/rime-udp.h index e87a43427..1e3f544ee 100644 --- a/core/net/rime/rime-udp.h +++ b/core/net/rime/rime-udp.h @@ -28,7 +28,7 @@ * * This file is part of the Contiki operating system. * - * $Id: rime-udp.h,v 1.1 2009/04/06 13:13:26 nvt-se Exp $ + * $Id: rime-udp.h,v 1.2 2010/02/18 21:48:39 adamdunkels Exp $ */ /** @@ -46,6 +46,4 @@ extern const struct mac_driver rime_udp_driver; -const struct mac_driver *rime_udp_init(const struct radio_driver *r); - #endif /* __UDPMAC_H__ */ diff --git a/core/net/rime/rime.c b/core/net/rime/rime.c index 84b859e51..4064cb74b 100644 --- a/core/net/rime/rime.c +++ b/core/net/rime/rime.c @@ -33,7 +33,7 @@ * * This file is part of the Contiki operating system. * - * $Id: rime.c,v 1.24 2010/02/03 20:38:33 adamdunkels Exp $ + * $Id: rime.c,v 1.25 2010/02/18 21:48:39 adamdunkels Exp $ */ /** @@ -43,6 +43,15 @@ * Adam Dunkels */ +#define DEBUG 0 +#if DEBUG +#include +#define PRINTF(...) printf(__VA_ARGS__) +#else +#define PRINTF(...) +#endif + +#include "net/netstack.h" #include "net/rime.h" #include "net/rime/chameleon.h" #include "net/rime/neighbor.h" @@ -90,31 +99,27 @@ rime_sniffer_remove(struct rime_sniffer *s) } /*---------------------------------------------------------------------------*/ static void -input(const struct mac_driver *r) +input(void) { - int len; struct rime_sniffer *s; - len = rime_mac->read(); - if(len > 0) { - for(s = list_head(sniffers); s != NULL; s = s->next) { - if(s->input_callback != NULL) { - s->input_callback(); - } + + for(s = list_head(sniffers); s != NULL; s = s->next) { + if(s->input_callback != NULL) { + s->input_callback(); } - RIMESTATS_ADD(rx); - chameleon_input(); } + RIMESTATS_ADD(rx); + chameleon_input(); } /*---------------------------------------------------------------------------*/ -void -rime_init(const struct mac_driver *m) +static void +init(void) { queuebuf_init(); packetbuf_clear(); announcement_init(); - rime_mac = m; - rime_mac->set_receive_function(input); + rime_mac = &NETSTACK_MAC; chameleon_init(&chameleon_bitopt); #if ! RIME_CONF_NO_POLITE_ANNOUCEMENTS /* XXX This is initializes the transmission of announcements but it @@ -131,26 +136,50 @@ rime_init(const struct mac_driver *m) #endif /* ! RIME_CONF_NO_POLITE_ANNOUCEMENTS */ } /*---------------------------------------------------------------------------*/ -int +static void +packet_sent(void *ptr, int status, int num_tx) +{ + switch(status) { + case MAC_TX_COLLISION: + PRINTF("rime: collision after %d tx\n", num_tx); + break; + case MAC_TX_NOACK: + PRINTF("rime: noack after %d tx\n", num_tx); + break; + case MAC_TX_OK: + PRINTF("rime: sent after %d tx\n", num_tx); + break; + default: + PRINTF("rime: error %d after %d tx\n", status, num_tx); + } + + if(status == MAC_TX_OK) { + struct rime_sniffer *s; + /* Call sniffers, but only if the packet was sent. */ + for(s = list_head(sniffers); s != NULL; s = s->next) { + if(s->output_callback != NULL) { + s->output_callback(); + } + } + } +} +/*---------------------------------------------------------------------------*/ +void rime_output(void) { - struct rime_sniffer *s; - RIMESTATS_ADD(tx); packetbuf_compact(); - if(rime_mac) { - if(rime_mac->send() == MAC_TX_OK) { - /* Call sniffers, but only if the packet was sent. */ - for(s = list_head(sniffers); s != NULL; s = s->next) { - if(s->output_callback != NULL) { - s->output_callback(); - } - } - return RIME_OK; - } - } - return RIME_ERR; + NETSTACK_MAC.send(packet_sent, NULL); } /*---------------------------------------------------------------------------*/ +const struct mac_driver rime_driver = { + "Rime", + init, + NULL, + input, + NULL, + NULL, + NULL, +}; /** @} */ diff --git a/core/net/sicslowpan.c b/core/net/sicslowpan.c index c0634a920..87b960148 100644 --- a/core/net/sicslowpan.c +++ b/core/net/sicslowpan.c @@ -32,7 +32,7 @@ * * This file is part of the Contiki operating system. * - * $Id: sicslowpan.c,v 1.17 2010/02/08 21:59:21 adamdunkels Exp $ + * $Id: sicslowpan.c,v 1.18 2010/02/18 21:48:39 adamdunkels Exp $ */ /** * \file @@ -54,6 +54,7 @@ #include "net/uip-netif.h" #include "net/rime.h" #include "net/sicslowpan.h" +#include "net/netstack.h" #define DEBUG 0 #if DEBUG @@ -1110,11 +1111,9 @@ send_packet(rimeaddr_t *dest) */ packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, dest); - if(sicslowpan_mac != NULL) { - /** \todo: Fix sending delays so they aren't blocking, or even better would - * be to figure out how to get rid of delays entirely */ - sicslowpan_mac->send(); - } + /* XXX we should provide a callback function that is called when the + packet is sent. For now, we just supply a NULL pointer. */ + NETSTACK_MAC.send(NULL, NULL); /* If we are sending multiple packets in a row, we need to let the watchdog know that we are still alive. */ @@ -1295,7 +1294,7 @@ output(uip_lladdr_t *localdest) * (it is a SHALL in the RFC 4944 and should never happen) */ static void -input(const struct mac_driver *r) +input(void) { /* size of the IP packet (read from fragment) */ u16_t frag_size = 0; @@ -1306,12 +1305,6 @@ input(const struct mac_driver *r) u16_t frag_tag = 0; #endif /*SICSLOWPAN_CONF_FRAG*/ -#ifdef SICSLOWPAN_CONF_CONVENTIONAL_MAC - if(r->read() <= 0) { - return; - } -#endif /* SICSLOWPAN_CONF_CONVENTIONAL_MAC */ - /* init */ uncomp_hdr_len = 0; rime_hdr_len = 0; @@ -1477,7 +1470,6 @@ input(const struct mac_driver *r) #if SICSLOWPAN_CONF_FRAG } #endif /* SICSLOWPAN_CONF_FRAG */ - return; } /** @} */ @@ -1485,14 +1477,11 @@ input(const struct mac_driver *r) /* \brief 6lowpan init function (called by the MAC layer) */ /*--------------------------------------------------------------------*/ void -sicslowpan_init(const struct mac_driver *m) +sicslowpan_init(void) { /* remember the mac driver */ - sicslowpan_mac = m; + sicslowpan_mac = &NETSTACK_MAC; - /* Set our input function as the receive function of the MAC. */ - sicslowpan_mac->set_receive_function(input); - /* * Set out output function as the function to be called from uIP to * send a packet. @@ -1529,4 +1518,14 @@ sicslowpan_init(const struct mac_driver *m) #endif /*SICSLOWPAN_CONF_COMPRESSION == SICSLOWPAN_CONF_COMPRESSION_HC01*/ } /*--------------------------------------------------------------------*/ +const struct mac_driver sicslowpan_driver = { + "Rime", + sicslowpan_init, + NULL, + input, + NULL, + NULL, + NULL, +}; +/*--------------------------------------------------------------------*/ /** @} */ diff --git a/core/net/sicslowpan.h b/core/net/sicslowpan.h index 8acadda74..e4830909f 100644 --- a/core/net/sicslowpan.h +++ b/core/net/sicslowpan.h @@ -33,7 +33,7 @@ * * This file is part of the Contiki operating system. * - * $Id: sicslowpan.h,v 1.5 2010/01/28 13:50:51 adamdunkels Exp $ + * $Id: sicslowpan.h,v 1.6 2010/02/18 21:48:39 adamdunkels Exp $ */ /** * \file @@ -249,11 +249,7 @@ struct sicslowpan_addr_context { /** @} */ -/** - * \brief 6lowpan init function - * \param m is the MAC layer "driver" - */ -void sicslowpan_init(const struct mac_driver *m); +extern const struct mac_driver sicslowpan_driver; extern const struct mac_driver *sicslowpan_mac; #endif /* __SICSLOWPAN_H__ */ diff --git a/platform/sky/contiki-conf.h b/platform/sky/contiki-conf.h index c7dc5a406..f068871cd 100644 --- a/platform/sky/contiki-conf.h +++ b/platform/sky/contiki-conf.h @@ -1,33 +1,42 @@ /* -*- C -*- */ -/* @(#)$Id: contiki-conf.h,v 1.71 2010/02/08 22:12:29 adamdunkels Exp $ */ +/* @(#)$Id: contiki-conf.h,v 1.72 2010/02/18 21:48:39 adamdunkels Exp $ */ #ifndef CONTIKI_CONF_H #define CONTIKI_CONF_H -/* Specifies the default MAC driver */ -#define MAC_CONF_CSMA 1 - -#define XMAC_CONF_COMPOWER 1 -#define CXMAC_CONF_COMPOWER 1 - - #if WITH_UIP6 -#define MAC_CONF_DRIVER cxmac_driver -#define MAC_CONF_CHANNEL_CHECK_RATE 8 + +/* Network setup for IPv6 */ +#define NETSTACK_CONF_NETWORK sicslowpan_driver +#define NETSTACK_CONF_MAC csma_driver +#define NETSTACK_CONF_RDC contikimac_driver +#define NETSTACK_CONF_RADIO cc2420_driver + +#define CC2420_CONF_AUTOACK 1 +#define MAC_CONF_CHANNEL_CHECK_RATE 8 #define RIME_CONF_NO_POLITE_ANNOUCEMENTS 0 -#define CXMAC_CONF_ANNOUNCEMENTS 0 -#define XMAC_CONF_ANNOUNCEMENTS 0 +#define CXMAC_CONF_ANNOUNCEMENTS 0 +#define XMAC_CONF_ANNOUNCEMENTS 0 + #else /* WITH_UIP6 */ -#define MAC_CONF_DRIVER xmac_driver -#define MAC_CONF_CHANNEL_CHECK_RATE 4 -#define TIMESYNCH_CONF_ENABLED 1 -#define CC2420_CONF_TIMESTAMPS 1 -#define CC2420_CONF_CHECKSUM 0 -#define RIME_CONF_NO_POLITE_ANNOUCEMENTS 1 -#define XMAC_CONF_ANNOUNCEMENTS 1 -#define CXMAC_CONF_ANNOUNCEMENTS 1 + +/* Network setup for non-IPv6 (rime). */ + +#define NETSTACK_CONF_NETWORK rime_driver +#define NETSTACK_CONF_MAC csma_driver +#define NETSTACK_CONF_RDC contikimac_driver +#define NETSTACK_CONF_RADIO cc2420_driver + +#define CC2420_CONF_AUTOACK 1 +#define MAC_CONF_CHANNEL_CHECK_RATE 8 +#define RIME_CONF_NO_POLITE_ANNOUCEMENTS 0 +#define CXMAC_CONF_ANNOUNCEMENTS 0 +#define XMAC_CONF_ANNOUNCEMENTS 0 + +#define XMAC_CONF_COMPOWER 1 +#define CXMAC_CONF_COMPOWER 1 #endif /* WITH_UIP6 */ #define QUEUEBUF_CONF_NUM 16 diff --git a/platform/sky/contiki-sky-main.c b/platform/sky/contiki-sky-main.c index 188f8a490..cedc426a3 100644 --- a/platform/sky/contiki-sky-main.c +++ b/platform/sky/contiki-sky-main.c @@ -26,7 +26,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)$Id: contiki-sky-main.c,v 1.68 2010/02/06 10:00:49 adamdunkels Exp $ + * @(#)$Id: contiki-sky-main.c,v 1.69 2010/02/18 21:48:39 adamdunkels Exp $ */ #include @@ -48,7 +48,7 @@ #include "dev/watchdog.h" #include "dev/xmem.h" #include "lib/random.h" -#include "net/mac/csma.h" +#include "net/netstack.h" #include "net/mac/frame802154.h" #include "net/mac/framer-802154.h" #include "net/mac/framer-nullmac.h" @@ -108,29 +108,6 @@ static uint8_t is_gateway; #include "experiment-setup.h" #endif -#if WITH_NULLMAC -#define MAC_DRIVER nullmac_driver -#endif /* WITH_NULLMAC */ - -#ifndef MAC_DRIVER -#ifdef MAC_CONF_DRIVER -#define MAC_DRIVER MAC_CONF_DRIVER -#else -#define MAC_DRIVER xmac_driver -#endif /* MAC_CONF_DRIVER */ -#endif /* MAC_DRIVER */ - -#ifndef MAC_CSMA -#ifdef MAC_CONF_CSMA -#define MAC_CSMA MAC_CONF_CSMA -#else -#define MAC_CSMA 1 -#endif /* MAC_CONF_CSMA */ -#endif /* MAC_CSMA */ - - -extern const struct mac_driver MAC_DRIVER; - /*---------------------------------------------------------------------------*/ #if 0 int @@ -264,8 +241,23 @@ main(int argc, char **argv) ctimer_init(); + set_rime_addr(); + cc2420_init(); - cc2420_set_pan_addr(IEEE802154_PANID, 0 /*XXX*/, ds2411_id); + { + uint8_t longaddr[8]; + uint16_t shortaddr; + + shortaddr = (rimeaddr_node_addr.u8[0] << 8) + + rimeaddr_node_addr.u8[1]; + memset(longaddr, 0, sizeof(longaddr)); + rimeaddr_copy((rimeaddr_t *)&longaddr, &rimeaddr_node_addr); + printf("MAC %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x ", + longaddr[0], longaddr[1], longaddr[2], longaddr[3], + longaddr[4], longaddr[5], longaddr[6], longaddr[7]); + + cc2420_set_pan_addr(IEEE802154_PANID, shortaddr, longaddr); + } cc2420_set_channel(RF_CHANNEL); printf(CONTIKI_VERSION_STRING " started. "); @@ -274,10 +266,10 @@ main(int argc, char **argv) } else { printf("Node id is not set.\n"); } - set_rime_addr(); - printf("MAC %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", + + /* printf("MAC %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", ds2411_id[0], ds2411_id[1], ds2411_id[2], ds2411_id[3], - ds2411_id[4], ds2411_id[5], ds2411_id[6], ds2411_id[7]); + ds2411_id[4], ds2411_id[5], ds2411_id[6], ds2411_id[7]);*/ framer_set(&framer_802154); @@ -289,11 +281,10 @@ main(int argc, char **argv) /* Setup X-MAC for 802.15.4 */ queuebuf_init(); -#if MAC_CSMA - sicslowpan_init(csma_init(MAC_DRIVER.init(&cc2420_driver))); -#else /* MAC_CSMA */ - sicslowpan_init(MAC_DRIVER.init(&cc2420_driver)); -#endif /* MAC_CSMA */ + NETSTACK_RDC.init(); + NETSTACK_MAC.init(); + NETSTACK_NETWORK.init(); + printf(" %s, channel check rate %d Hz, radio channel %u\n", sicslowpan_mac->name, CLOCK_SECOND / (sicslowpan_mac->channel_check_interval() == 0? 1: @@ -315,7 +306,7 @@ main(int argc, char **argv) uip_netif_physical_if.addresses[0].ipaddr.u8[15]); } - if(0) { + if(1) { uip_ipaddr_t ipaddr; int i; uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0); @@ -335,11 +326,11 @@ main(int argc, char **argv) uip_router_register(&rimeroute); #endif /* UIP_CONF_ROUTER */ #else /* WITH_UIP6 */ -#if MAC_CSMA - rime_init(csma_init(MAC_DRIVER.init(&cc2420_driver))); -#else /* MAC_CSMA */ - rime_init(MAC_DRIVER.init(&cc2420_driver)); -#endif /* MAC_CSMA */ + + NETSTACK_RDC.init(); + NETSTACK_MAC.init(); + NETSTACK_NETWORK.init(); + printf(" %s, channel check rate %d Hz, radio channel %u\n", rime_mac->name, CLOCK_SECOND / (rime_mac->channel_check_interval() == 0? 1: