sicslowmac.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2008, Swedish Institute of Computer Science.
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  * 1. Redistributions of source code must retain the above copyright
00009  *    notice, this list of conditions and the following disclaimer.
00010  * 2. Redistributions in binary form must reproduce the above copyright
00011  *    notice, this list of conditions and the following disclaimer in the
00012  *    documentation and/or other materials provided with the distribution.
00013  * 3. Neither the name of the Institute nor the names of its contributors
00014  *    may be used to endorse or promote products derived from this software
00015  *    without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
00018  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
00021  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00022  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00023  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00024  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00025  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00026  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00027  * SUCH DAMAGE.
00028  *
00029  * This file is part of the Contiki operating system.
00030  *
00031  * $Id: sicslowmac.c,v 1.8 2010/06/14 19:19:17 adamdunkels Exp $
00032  */
00033 
00034 
00035 /**
00036  * \file
00037  *         MAC interface for packaging radio packets into 802.15.4 frames
00038  *
00039  * \author
00040  *         Adam Dunkels <adam@sics.se>
00041  *         Eric Gnoske <egnoske@gmail.com>
00042  *         Blake Leverett <bleverett@gmail.com>
00043  *         Niclas Finne <nfi@sics.se>
00044  *         Joakim Eriksson <joakime@sics.se>
00045  */
00046 
00047 #include <string.h>
00048 #include "net/mac/sicslowmac.h"
00049 #include "net/mac/frame802154.h"
00050 #include "net/packetbuf.h"
00051 #include "net/netstack.h"
00052 #include "lib/random.h"
00053 
00054 #define DEBUG 0
00055 
00056 #if DEBUG
00057 #include <stdio.h>
00058 #define PRINTF(...) printf(__VA_ARGS__)
00059 #define PRINTADDR(addr) PRINTF(" %02x%02x:%02x%02x:%02x%02x:%02x%02x ", ((uint8_t *)addr)[0], ((uint8_t *)addr)[1], ((uint8_t *)addr)[2], ((uint8_t *)addr)[3], ((uint8_t *)addr)[4], ((uint8_t *)addr)[5], ((uint8_t *)addr)[6], ((uint8_t *)addr)[7])
00060 #else
00061 #define PRINTF(...)
00062 #define PRINTADDR(addr)
00063 #endif
00064 
00065 /**  \brief The sequence number (0x00 - 0xff) added to the transmitted
00066  *   data or MAC command frame. The default is a random value within
00067  *   the range.
00068  */
00069 static uint8_t mac_dsn;
00070 
00071 /**  \brief The 16-bit identifier of the PAN on which the device is
00072  *   sending to.  If this value is 0xffff, the device is not
00073  *   associated.
00074  */
00075 static uint16_t mac_dst_pan_id = IEEE802154_PANID;
00076 
00077 /**  \brief The 16-bit identifier of the PAN on which the device is
00078  *   operating.  If this value is 0xffff, the device is not
00079  *   associated.
00080  */
00081 static uint16_t mac_src_pan_id = IEEE802154_PANID;
00082 
00083 /*---------------------------------------------------------------------------*/
00084 static int
00085 is_broadcast_addr(uint8_t mode, uint8_t *addr)
00086 {
00087   int i = mode == FRAME802154_SHORTADDRMODE ? 2 : 8;
00088   while(i-- > 0) {
00089     if(addr[i] != 0xff) {
00090       return 0;
00091     }
00092   }
00093   return 1;
00094 }
00095 /*---------------------------------------------------------------------------*/
00096 static void
00097 send_packet(mac_callback_t sent, void *ptr)
00098 {
00099   frame802154_t params;
00100   uint8_t len;
00101 
00102   /* init to zeros */
00103   memset(&params, 0, sizeof(params));
00104 
00105   /* Build the FCF. */
00106   params.fcf.frame_type = FRAME802154_DATAFRAME;
00107   params.fcf.security_enabled = 0;
00108   params.fcf.frame_pending = 0;
00109   params.fcf.ack_required = packetbuf_attr(PACKETBUF_ATTR_RELIABLE);
00110   params.fcf.panid_compression = 0;
00111 
00112   /* Insert IEEE 802.15.4 (2003) version bit. */
00113   params.fcf.frame_version = FRAME802154_IEEE802154_2003;
00114 
00115   /* Increment and set the data sequence number. */
00116   params.seq = mac_dsn++;
00117 
00118   /* Complete the addressing fields. */
00119   /**
00120      \todo For phase 1 the addresses are all long. We'll need a mechanism
00121      in the rime attributes to tell the mac to use long or short for phase 2.
00122   */
00123   params.fcf.src_addr_mode = FRAME802154_LONGADDRMODE;
00124   params.dest_pid = mac_dst_pan_id;
00125 
00126   /*
00127    *  If the output address is NULL in the Rime buf, then it is broadcast
00128    *  on the 802.15.4 network.
00129    */
00130   if(rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), &rimeaddr_null)) {
00131     /* Broadcast requires short address mode. */
00132     params.fcf.dest_addr_mode = FRAME802154_SHORTADDRMODE;
00133     params.dest_addr[0] = 0xFF;
00134     params.dest_addr[1] = 0xFF;
00135 
00136   } else {
00137     rimeaddr_copy((rimeaddr_t *)&params.dest_addr,
00138                   packetbuf_addr(PACKETBUF_ADDR_RECEIVER));
00139     params.fcf.dest_addr_mode = FRAME802154_LONGADDRMODE;
00140   }
00141 
00142   /* Set the source PAN ID to the global variable. */
00143   params.src_pid = mac_src_pan_id;
00144 
00145   /*
00146    * Set up the source address using only the long address mode for
00147    * phase 1.
00148    */
00149   rimeaddr_copy((rimeaddr_t *)&params.src_addr, &rimeaddr_node_addr);
00150 
00151   params.payload = packetbuf_dataptr();
00152   params.payload_len = packetbuf_datalen();
00153   len = frame802154_hdrlen(&params);
00154   if(packetbuf_hdralloc(len)) {
00155     int ret;
00156     frame802154_create(&params, packetbuf_hdrptr(), len);
00157 
00158     PRINTF("6MAC-UT: %2X", params.fcf.frame_type);
00159     PRINTADDR(params.dest_addr.u8);
00160     PRINTF("%u %u (%u)\n", len, packetbuf_datalen(), packetbuf_totlen());
00161 
00162     ret = NETSTACK_RADIO.send(packetbuf_hdrptr(), packetbuf_totlen());
00163     if(sent) {
00164       switch(ret) {
00165       case RADIO_TX_OK:
00166         sent(ptr, MAC_TX_OK, 1);
00167         break;
00168       case RADIO_TX_ERR:
00169         sent(ptr, MAC_TX_ERR, 1);
00170         break;
00171       }
00172     }
00173   } else {
00174     PRINTF("6MAC-UT: too large header: %u\n", len);
00175   }
00176 }
00177 /*---------------------------------------------------------------------------*/
00178 static void
00179 input_packet(void)
00180 {
00181   frame802154_t frame;
00182   int len;
00183 
00184   len = packetbuf_datalen();
00185 
00186   if(frame802154_parse(packetbuf_dataptr(), len, &frame) &&
00187      packetbuf_hdrreduce(len - frame.payload_len)) {
00188     if(frame.fcf.dest_addr_mode) {
00189       if(frame.dest_pid != mac_src_pan_id &&
00190          frame.dest_pid != FRAME802154_BROADCASTPANDID) {
00191         /* Not broadcast or for our PAN */
00192         PRINTF("6MAC: for another pan %u\n", frame.dest_pid);
00193         return;
00194       }
00195       if(!is_broadcast_addr(frame.fcf.dest_addr_mode, frame.dest_addr)) {
00196         packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, (rimeaddr_t *)&frame.dest_addr);
00197         if(!rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER),
00198                          &rimeaddr_node_addr)) {
00199           /* Not for this node */
00200           PRINTF("6MAC: not for us\n");
00201           return;
00202         }
00203       }
00204     }
00205     packetbuf_set_addr(PACKETBUF_ADDR_SENDER, (rimeaddr_t *)&frame.src_addr);
00206 
00207     PRINTF("6MAC-IN: %2X", frame.fcf.frame_type);
00208     PRINTADDR(packetbuf_addr(PACKETBUF_ADDR_SENDER));
00209     PRINTADDR(packetbuf_addr(PACKETBUF_ADDR_RECEIVER));
00210     PRINTF("%u\n", packetbuf_datalen());
00211     NETSTACK_MAC.input();
00212   } else {
00213     PRINTF("6MAC: failed to parse hdr\n");
00214   }
00215 }
00216 /*---------------------------------------------------------------------------*/
00217 static int
00218 on(void)
00219 {
00220   return NETSTACK_RADIO.on();
00221 }
00222 /*---------------------------------------------------------------------------*/
00223 static int
00224 off(int keep_radio_on)
00225 {
00226   if(keep_radio_on) {
00227     return NETSTACK_RADIO.on();
00228   } else {
00229     return NETSTACK_RADIO.off();
00230   }
00231 }
00232 /*---------------------------------------------------------------------------*/
00233 static void
00234 init(void)
00235 {
00236   mac_dsn = random_rand() % 256;
00237 
00238   NETSTACK_RADIO.on();
00239 }
00240 /*---------------------------------------------------------------------------*/
00241 static unsigned short
00242 channel_check_interval(void)
00243 {
00244   return 0;
00245 }
00246 /*---------------------------------------------------------------------------*/
00247 const struct rdc_driver sicslowmac_driver = {
00248   "sicslowmac",
00249   init,
00250   send_packet,
00251   input_packet,
00252   on,
00253   off,
00254   channel_check_interval
00255 };
00256 /*---------------------------------------------------------------------------*/

Generated on Mon Apr 11 14:23:29 2011 for Contiki 2.5 by  doxygen 1.6.1