Contiki 2.6
|
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(¶ms, 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 *)¶ms.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 *)¶ms.src_addr, &rimeaddr_node_addr); 00151 00152 params.payload = packetbuf_dataptr(); 00153 params.payload_len = packetbuf_datalen(); 00154 len = frame802154_hdrlen(¶ms); 00155 if(packetbuf_hdralloc(len)) { 00156 int ret; 00157 frame802154_create(¶ms, 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 /*---------------------------------------------------------------------------*/