Contiki 2.6

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/queuebuf.h"
00052 #include "net/netstack.h"
00053 #include "lib/random.h"
00054 
00055 #define DEBUG 0
00056 
00057 #if DEBUG
00058 #include <stdio.h>
00059 #define PRINTF(...) printf(__VA_ARGS__)
00060 #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])
00061 #else
00062 #define PRINTF(...)
00063 #define PRINTADDR(addr)
00064 #endif
00065 
00066 /**  \brief The sequence number (0x00 - 0xff) added to the transmitted
00067  *   data or MAC command frame. The default is a random value within
00068  *   the range.
00069  */
00070 static uint8_t mac_dsn;
00071 
00072 /**  \brief The 16-bit identifier of the PAN on which the device is
00073  *   sending to.  If this value is 0xffff, the device is not
00074  *   associated.
00075  */
00076 static uint16_t mac_dst_pan_id = IEEE802154_PANID;
00077 
00078 /**  \brief The 16-bit identifier of the PAN on which the device is
00079  *   operating.  If this value is 0xffff, the device is not
00080  *   associated.
00081  */
00082 static uint16_t mac_src_pan_id = IEEE802154_PANID;
00083 
00084 /*---------------------------------------------------------------------------*/
00085 static int
00086 is_broadcast_addr(uint8_t mode, uint8_t *addr)
00087 {
00088   int i = mode == FRAME802154_SHORTADDRMODE ? 2 : 8;
00089   while(i-- > 0) {
00090     if(addr[i] != 0xff) {
00091       return 0;
00092     }
00093   }
00094   return 1;
00095 }
00096 /*---------------------------------------------------------------------------*/
00097 static void
00098 send_packet(mac_callback_t sent, void *ptr)
00099 {
00100   frame802154_t params;
00101   uint8_t len;
00102 
00103   /* init to zeros */
00104   memset(&params, 0, sizeof(params));
00105 
00106   /* Build the FCF. */
00107   params.fcf.frame_type = FRAME802154_DATAFRAME;
00108   params.fcf.security_enabled = 0;
00109   params.fcf.frame_pending = 0;
00110   params.fcf.ack_required = packetbuf_attr(PACKETBUF_ATTR_RELIABLE);
00111   params.fcf.panid_compression = 0;
00112 
00113   /* Insert IEEE 802.15.4 (2003) version bit. */
00114   params.fcf.frame_version = FRAME802154_IEEE802154_2003;
00115 
00116   /* Increment and set the data sequence number. */
00117   params.seq = mac_dsn++;
00118 
00119   /* Complete the addressing fields. */
00120   /**
00121      \todo For phase 1 the addresses are all long. We'll need a mechanism
00122      in the rime attributes to tell the mac to use long or short for phase 2.
00123   */
00124   params.fcf.src_addr_mode = FRAME802154_LONGADDRMODE;
00125   params.dest_pid = mac_dst_pan_id;
00126 
00127   /*
00128    *  If the output address is NULL in the Rime buf, then it is broadcast
00129    *  on the 802.15.4 network.
00130    */
00131   if(rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), &rimeaddr_null)) {
00132     /* Broadcast requires short address mode. */
00133     params.fcf.dest_addr_mode = FRAME802154_SHORTADDRMODE;
00134     params.dest_addr[0] = 0xFF;
00135     params.dest_addr[1] = 0xFF;
00136 
00137   } else {
00138     rimeaddr_copy((rimeaddr_t *)&params.dest_addr,
00139                   packetbuf_addr(PACKETBUF_ADDR_RECEIVER));
00140     params.fcf.dest_addr_mode = FRAME802154_LONGADDRMODE;
00141   }
00142 
00143   /* Set the source PAN ID to the global variable. */
00144   params.src_pid = mac_src_pan_id;
00145 
00146   /*
00147    * Set up the source address using only the long address mode for
00148    * phase 1.
00149    */
00150   rimeaddr_copy((rimeaddr_t *)&params.src_addr, &rimeaddr_node_addr);
00151 
00152   params.payload = packetbuf_dataptr();
00153   params.payload_len = packetbuf_datalen();
00154   len = frame802154_hdrlen(&params);
00155   if(packetbuf_hdralloc(len)) {
00156     int ret;
00157     frame802154_create(&params, packetbuf_hdrptr(), len);
00158 
00159     PRINTF("6MAC-UT: %2X", params.fcf.frame_type);
00160     PRINTADDR(params.dest_addr.u8);
00161     PRINTF("%u %u (%u)\n", len, packetbuf_datalen(), packetbuf_totlen());
00162 
00163     ret = NETSTACK_RADIO.send(packetbuf_hdrptr(), packetbuf_totlen());
00164     if(sent) {
00165       switch(ret) {
00166       case RADIO_TX_OK:
00167         sent(ptr, MAC_TX_OK, 1);
00168         break;
00169       case RADIO_TX_ERR:
00170         sent(ptr, MAC_TX_ERR, 1);
00171         break;
00172       }
00173     }
00174   } else {
00175     PRINTF("6MAC-UT: too large header: %u\n", len);
00176   }
00177 }
00178 /*---------------------------------------------------------------------------*/
00179 void
00180 send_list(mac_callback_t sent, void *ptr, struct rdc_buf_list *buf_list)
00181 {
00182   if(buf_list != NULL) {
00183     queuebuf_to_packetbuf(buf_list->buf);
00184     send_packet(sent, ptr);
00185   }
00186 }
00187 /*---------------------------------------------------------------------------*/
00188 static void
00189 input_packet(void)
00190 {
00191   frame802154_t frame;
00192   int len;
00193 
00194   len = packetbuf_datalen();
00195 
00196   if(frame802154_parse(packetbuf_dataptr(), len, &frame) &&
00197      packetbuf_hdrreduce(len - frame.payload_len)) {
00198     if(frame.fcf.dest_addr_mode) {
00199       if(frame.dest_pid != mac_src_pan_id &&
00200          frame.dest_pid != FRAME802154_BROADCASTPANDID) {
00201         /* Not broadcast or for our PAN */
00202         PRINTF("6MAC: for another pan %u\n", frame.dest_pid);
00203         return;
00204       }
00205       if(!is_broadcast_addr(frame.fcf.dest_addr_mode, frame.dest_addr)) {
00206         packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, (rimeaddr_t *)&frame.dest_addr);
00207         if(!rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER),
00208                          &rimeaddr_node_addr)) {
00209           /* Not for this node */
00210           PRINTF("6MAC: not for us\n");
00211           return;
00212         }
00213       }
00214     }
00215     packetbuf_set_addr(PACKETBUF_ADDR_SENDER, (rimeaddr_t *)&frame.src_addr);
00216 
00217     PRINTF("6MAC-IN: %2X", frame.fcf.frame_type);
00218     PRINTADDR(packetbuf_addr(PACKETBUF_ADDR_SENDER));
00219     PRINTADDR(packetbuf_addr(PACKETBUF_ADDR_RECEIVER));
00220     PRINTF("%u\n", packetbuf_datalen());
00221     NETSTACK_MAC.input();
00222   } else {
00223     PRINTF("6MAC: failed to parse hdr\n");
00224   }
00225 }
00226 /*---------------------------------------------------------------------------*/
00227 static int
00228 on(void)
00229 {
00230   return NETSTACK_RADIO.on();
00231 }
00232 /*---------------------------------------------------------------------------*/
00233 static int
00234 off(int keep_radio_on)
00235 {
00236   if(keep_radio_on) {
00237     return NETSTACK_RADIO.on();
00238   } else {
00239     return NETSTACK_RADIO.off();
00240   }
00241 }
00242 /*---------------------------------------------------------------------------*/
00243 static void
00244 init(void)
00245 {
00246   mac_dsn = random_rand() % 256;
00247 
00248   NETSTACK_RADIO.on();
00249 }
00250 /*---------------------------------------------------------------------------*/
00251 static unsigned short
00252 channel_check_interval(void)
00253 {
00254   return 0;
00255 }
00256 /*---------------------------------------------------------------------------*/
00257 const struct rdc_driver sicslowmac_driver = {
00258   "sicslowmac",
00259   init,
00260   send_packet,
00261   send_list,
00262   input_packet,
00263   on,
00264   off,
00265   channel_check_interval
00266 };
00267 /*---------------------------------------------------------------------------*/