Contiki 2.5
sicslowmac.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2008, Swedish Institute of Computer Science.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the Institute nor the names of its contributors
14  * may be used to endorse or promote products derived from this software
15  * without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * This file is part of the Contiki operating system.
30  *
31  * $Id: sicslowmac.c,v 1.9 2010/06/14 19:19:17 adamdunkels Exp $
32  */
33 
34 
35 /**
36  * \file
37  * Example glue code between the existing MAC code and the
38  * Contiki mac interface
39  *
40  * \author
41  * Adam Dunkels <adam@sics.se>
42  * Eric Gnoske <egnoske@gmail.com>
43  * Blake Leverett <bleverett@gmail.com>
44  *
45  * \addtogroup rf230mac
46  */
47 
48 #include <stdlib.h>
49 #include <stdbool.h>
50 #include <string.h>
51 #include <stdio.h>
52 #include <avr/eeprom.h>
53 #include <util/delay.h>
54 #include "net/packetbuf.h"
55 #include "zmac.h"
56 #include "mac.h"
57 #include "frame.h"
58 #include "radio.h"
59 #include "tcpip.h"
60 #include "sicslowmac.h"
61 #include "sicslowpan.h"
62 #include "ieee-15-4-manager.h"
63 
64 /* Macros */
65 #define DEBUG 0
66 #define MAX_EVENTS 10
67 
68 #if DEBUG
69 #define PRINTF(...) printf(__VA_ARGS__)
70 #define SICSLOW_CORRECTION_DELAY 70
71 #else
72 #define PRINTF(...)
73 #define SICSLOW_CORRECTION_DELAY 7
74 #endif
75 
76 #ifdef JACKDAW
77 #include "sicslow_ethernet.h"
78 #define LOG_FRAME(x,y) mac_logTXtoEthernet(x,y)
79 #else
80 #define LOG_FRAME(x,y)
81 #endif
82 
83 /* Globals */
84 static struct mac_driver mac_driver_struct;
85 static struct mac_driver *pmac_driver = &mac_driver_struct;
87 static parsed_frame_t *parsed_frame;
88 
89 /* The core mac layer has a pointer to the driver name in the first field.
90  * It calls the radio driver with radio->send, which is the first field of the radio driver.
91  * This glue directs radio->send to the custom mac layer.
92  */
93 const struct mac_driver sicslowmac_driver = {
94  (char *)sicslowmac_dataRequest, //Remove compiler warning.
95  /* read_packet, */
96  /* set_receive_function, */
97  /* on, */
98  /* off, */
99 };
100 
101 static struct {
102  uint8_t head;
103  uint8_t tail;
104  event_object_t event_object[MAX_EVENTS];
105 } event_queue;
106 
107 /* Prototypes */
108 static void setinput(void (*r)(const struct mac_driver *d));
109 void (*pinput)(const struct mac_driver *r);
110 void sicslowmac_unknownIndication(void);
111 
112 
113 void (*sicslowmac_snifferhook)(const struct mac_driver *r) = NULL;
114 
115 
116 /*---------------------------------------------------------------------------*/
117 /**
118  * \brief Checks for any pending events in the queue.
119  *
120  * \return True if there is a pending event, else false.
121  */
122 uint8_t
124 {
125  return (event_queue.head != event_queue.tail);
126 }
127 /*---------------------------------------------------------------------------*/
128 /**
129  * \brief Puts an event into the queue of events.
130  *
131  * \param object is a pointer to the event to add to queue.
132  */
133 void
134 mac_put_event(event_object_t *object)
135 {
136  uint8_t newhead;
137 
138  if ((event_queue.head + 1) % MAX_EVENTS == event_queue.tail){
139  /* queue full, get outta here */
140  return;
141  }
142 
143  newhead = event_queue.head;
144 
145  /* store in queue */
146  event_queue.event_object[newhead] = *object;
147 
148  /* calculate new head index */
149  newhead++;
150  if (newhead >= MAX_EVENTS){
151  newhead = 0;
152  }
153  event_queue.head = newhead;
154 }
155 /*---------------------------------------------------------------------------*/
156 /**
157  * \brief Pulls an event from the event queue.
158  * Assumes that there is an event in the queue. See mac_event_pending().
159  *
160  * \return Pointer to the event object, or NULL in the event of empty queue.
161  */
162 event_object_t
164 {
165  event_object_t *object = NULL;
166  volatile uint8_t newtail;
167 
168  newtail = event_queue.tail;
169 
170  object = &(event_queue.event_object[newtail]);
171 
172  /* calculate new tail */
173  newtail++;
174  if (newtail >= MAX_EVENTS){
175  newtail = 0;
176  }
177 
178  event_queue.tail = newtail;
179 
180  return(object);
181 }
182 
183 void mac_pollhandler(void)
184 {
185  mac_task(0, NULL);
186 }
187 
188 /*---------------------------------------------------------------------------*/
189 /**
190  * \brief This is the main loop task for the MAC. Called by the
191  * main application loop.
192  */
193 void
194 mac_task(process_event_t ev, process_data_t data)
195 {
196  /* check for event in queue */
197  event_object_t *event;
198 
199  if(mac_event_pending()){
200 
201  event = mac_get_event();
202 
203  /* Handle events from radio */
204  if (event){
205 
206  if (event->event == MAC_EVENT_RX){
207  /* got a frame, find out with kind of frame */
208  parsed_frame = (parsed_frame_t *)event->data;
209  if (parsed_frame->fcf->frameType == DATAFRAME){
210  sicslowmac_dataIndication();
211  } else {
212 
213  /* Hook to cath unknown frames */
214  sicslowmac_unknownIndication();
215  }
216 
217 
218  /* Frame no longer in use */
219  parsed_frame->in_use = false;
220  }
221 
222  if (event->event == MAC_EVENT_DROPPED){
223  /* Frame was dropped */
224  PRINTF("sicslowmac: Frame Dropped!\n");
225  }
226  }
227  }
228 }
229 /*---------------------------------------------------------------------------*/
230 void
231 setinput(void (*r)(const struct mac_driver *d))
232 {
233  pinput = r;
234 }
235 /*---------------------------------------------------------------------------*/
236 static uint8_t dest_reversed[UIP_LLADDR_LEN];
237 static uint8_t src_reversed[UIP_LLADDR_LEN];
238 
239 # define MSB(u16) (((uint8_t* )&u16)[1])
240 # define LSB(u16) (((uint8_t* )&u16)[0])
241 
242 void
243 sicslowmac_dataIndication(void)
244 {
245  packetbuf_clear();
246 
247 
248  #if UIP_LLADDR_LEN == 8
249  /* Finally, get the stuff into the rime buffer.... */
250  packetbuf_copyfrom(parsed_frame->payload, parsed_frame->payload_length);
251  packetbuf_set_datalen(parsed_frame->payload_length);
252 
253  memcpy(dest_reversed, (uint8_t *)parsed_frame->dest_addr, UIP_LLADDR_LEN);
254  memcpy(src_reversed, (uint8_t *)parsed_frame->src_addr, UIP_LLADDR_LEN);
255 
256  /* Change addresses to expected byte order */
257  byte_reverse((uint8_t *)dest_reversed, UIP_LLADDR_LEN);
258  byte_reverse((uint8_t *)src_reversed, UIP_LLADDR_LEN);
259 
260  packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, (const rimeaddr_t *)dest_reversed);
261  packetbuf_set_addr(PACKETBUF_ADDR_SENDER, (const rimeaddr_t *)src_reversed);
262 
263  #elif UIP_CONF_USE_RUM
264  /* Finally, get the stuff into the rime buffer.... */
265  packetbuf_copyfrom(parsed_frame->payload + UIP_DATA_RUM_OFFSET, parsed_frame->payload_length - UIP_DATA_RUM_OFFSET);
266  packetbuf_set_datalen(parsed_frame->payload_length + UIP_DATA_RUM_OFFSET);
267 
268  dest_reversed[0] = MSB(parsed_frame->dest_pid);
269  dest_reversed[1] = LSB(parsed_frame->dest_pid);
270  dest_reversed[2] = 0;
271  dest_reversed[3] = 0;
272  dest_reversed[4] = MSB(parsed_frame->payload[0]); //FinalDestAddr
273  dest_reversed[5] = LSB(parsed_frame->payload[1]);
274 
275  src_reversed[0] = MSB(parsed_frame->src_pid);
276  src_reversed[1] = LSB(parsed_frame->src_pid);
277  src_reversed[2] = 0;
278  src_reversed[3] = 0;
279  src_reversed[4] = MSB(parsed_frame->payload[2]); //originAddr
280  src_reversed[5] = LSB(parsed_frame->payload[3]);
281 
282  #else
283  /* Finally, get the stuff into the rime buffer.... */
284  packetbuf_copyfrom(parsed_frame->payload, parsed_frame->payload_length);
285  packetbuf_set_datalen(parsed_frame->payload_length);
286 
287  dest_reversed[0] = MSB(parsed_frame->dest_pid);
288  dest_reversed[1] = LSB(parsed_frame->dest_pid);
289  dest_reversed[2] = 0;
290  dest_reversed[3] = 0;
291  dest_reversed[4] = MSB(parsed_frame->dest_addr->addr16);
292  dest_reversed[5] = LSB(parsed_frame->dest_addr->addr16);
293 
294  src_reversed[0] = MSB(parsed_frame->src_pid);
295  src_reversed[1] = LSB(parsed_frame->src_pid);
296  src_reversed[2] = 0;
297  src_reversed[3] = 0;
298  src_reversed[4] = MSB(parsed_frame->src_addr->addr16);
299  src_reversed[5] = LSB(parsed_frame->src_addr->addr16);
300 
301  packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, (const rimeaddr_t *)dest_reversed);
302  packetbuf_set_addr(PACKETBUF_ADDR_SENDER, (const rimeaddr_t *)src_reversed);
303 
304  #endif
305 
306  PRINTF("sicslowmac: hand off frame to sicslowpan \n");
307  pinput(pmac_driver);
308 }
309 
310 void
311 sicslowmac_unknownIndication(void)
312 {
313  if (sicslowmac_snifferhook) {
314 
315  packetbuf_clear();
316 
317  /* Finally, get the stuff into the rime buffer.... */
318  packetbuf_copyfrom(parsed_frame->payload, parsed_frame->payload_length);
319  packetbuf_set_datalen(parsed_frame->payload_length);
320 
321  #if UIP_LLADDR_LEN == 8
322  memcpy(dest_reversed, (uint8_t *)parsed_frame->dest_addr, UIP_LLADDR_LEN);
323  memcpy(src_reversed, (uint8_t *)parsed_frame->src_addr, UIP_LLADDR_LEN);
324 
325  /* Change addresses to expected byte order */
326  byte_reverse((uint8_t *)dest_reversed, UIP_LLADDR_LEN);
327  byte_reverse((uint8_t *)src_reversed, UIP_LLADDR_LEN);
328 
329  packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, (const rimeaddr_t *)dest_reversed);
330  packetbuf_set_addr(PACKETBUF_ADDR_SENDER, (const rimeaddr_t *)src_reversed);
331 
332  #elif UIP_CONF_USE_RUM
333 
334  dest_reversed[0] = MSB(parsed_frame->dest_pid);
335  dest_reversed[1] = LSB(parsed_frame->dest_pid);
336  dest_reversed[2] = 0;
337  dest_reversed[3] = 0;
338  dest_reversed[4] = MSB(parsed_frame->payload[0]); //FinalDestAddr
339  dest_reversed[5] = LSB(parsed_frame->payload[1]);
340 
341  src_reversed[0] = MSB(parsed_frame->src_pid);
342  src_reversed[1] = LSB(parsed_frame->src_pid);
343  src_reversed[2] = 0;
344  src_reversed[3] = 0;
345  src_reversed[4] = MSB(parsed_frame->payload[2]); //originAddr
346  src_reversed[5] = LSB(parsed_frame->payload[3]);
347 
348  #else
349 
350  dest_reversed[0] = MSB(parsed_frame->dest_pid);
351  dest_reversed[1] = LSB(parsed_frame->dest_pid);
352  dest_reversed[2] = 0;
353  dest_reversed[3] = 0;
354  dest_reversed[4] = MSB(parsed_frame->dest_addr->addr16);
355  dest_reversed[5] = LSB(parsed_frame->dest_addr->addr16);
356 
357  src_reversed[0] = MSB(parsed_frame->src_pid);
358  src_reversed[1] = LSB(parsed_frame->src_pid);
359  src_reversed[2] = 0;
360  src_reversed[3] = 0;
361  src_reversed[4] = MSB(parsed_frame->src_addr->addr16);
362  src_reversed[5] = LSB(parsed_frame->src_addr->addr16);
363 
364  packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, (const rimeaddr_t *)dest_reversed);
365  packetbuf_set_addr(PACKETBUF_ADDR_SENDER, (const rimeaddr_t *)src_reversed);
366 
367  #endif
368 
369  PRINTF("sicslowmac: hand off frame to sniffer \n");
370 
371  sicslowmac_snifferhook(pmac_driver);
372  }
373 
374 }
375 
376 /*---------------------------------------------------------------------------*/
377 /**
378  * \brief This is the implementation of the 15.4 MAC Data Request
379  * primitive.
380  *
381  * \return Integer denoting success or failure.
382  * \retval 0 Failure.
383  * \retval 1 Success.
384  *
385  * The data request primitive creates the frame header based
386  * on static and dynamic data. The static data will be refined
387  * in phase II of the project. The frame payload and length are
388  * retrieved from the rime buffer and rime length respectively.
389  *
390  * When the header and payload are assembled into the
391  * frame_create_params structure, the frame is created
392  * by a call to frame_tx_create and then transmited via
393  * radio_send_data.
394  */
395 /*---------------------------------------------------------------------------*/
396 int
398 {
399 
400  _delay_ms(SICSLOW_CORRECTION_DELAY);
401 
402  /* create structure to store result. */
403  frame_create_params_t params;
404  frame_result_t result;
405 
406  /* Save the msduHandle in a global variable. */
407  msduHandle = packetbuf_attr(PACKETBUF_ATTR_PACKET_ID);
408 
409  /* Build the FCF. */
410  params.fcf.frameType = DATAFRAME;
411  params.fcf.securityEnabled = false;
412  params.fcf.framePending = false;
413  params.fcf.ackRequired = packetbuf_attr(PACKETBUF_ATTR_RELIABLE);
414  params.fcf.panIdCompression = false;
415 
416  /* Insert IEEE 802.15.4 (2003) version bit. */
417  params.fcf.frameVersion = IEEE802154_2003;
418 
419  /* Increment and set the data sequence number. */
420  params.seq = macDSN++;
421 
422  /* Complete the addressing fields. */
423  /**
424  \todo For phase 1 the addresses are all long. We'll need a mechanism
425  in the rime attributes to tell the mac to use long or short for phase 2.
426  */
427  params.fcf.srcAddrMode = LONGADDRMODE;
428  params.dest_pid = ieee15_4ManagerAddress.get_dst_panid();
429 
430  /*
431  * If the output address is NULL in the Rime buf, then it is broadcast
432  * on the 802.15.4 network.
433  */
434  if(rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), &rimeaddr_null) ) {
435  /* Broadcast requires short address mode. */
436  params.fcf.destAddrMode = SHORTADDRMODE;
437  params.dest_pid = BROADCASTPANDID;
438  params.dest_addr.addr16 = BROADCASTADDR;
439 
440  } else {
441 
442  /* Phase 1.5 - end nodes send to anyone? */
443  memcpy(&params.dest_addr, (uint8_t *)packetbuf_addr(PACKETBUF_ADDR_RECEIVER), LONG_ADDR_LEN);
444 
445  /* Change from sicslowpan byte arrangement to sicslowmac */
446  byte_reverse((uint8_t*)&params.dest_addr.addr64, LONG_ADDR_LEN);
447 
448  /* Phase 1 - end nodes only sends to pan coordinator node. */
449  /* params.dest_addr.addr64 = ieee15_4ManagerAddress.get_coord_long_addr(); */
450  params.fcf.destAddrMode = LONGADDRMODE;
451  }
452 
453  /* Set the source PAN ID to the global variable. */
454  params.src_pid = ieee15_4ManagerAddress.get_src_panid();
455 
456  /*
457  * Set up the source address using only the long address mode for
458  * phase 1.
459  */
460  params.src_addr.addr64 = ieee15_4ManagerAddress.get_long_addr();
461 
462  /* Copy the payload data. */
463  params.payload_len = packetbuf_datalen();
464  params.payload = packetbuf_dataptr();
465 
466  /* Create transmission frame. */
467  frame_tx_create(&params, &result);
468 
469  /* Log if needed */
470  LOG_FRAME(&params, &result);
471 
472  /* Retry up to this many times to send the packet if radio is busy */
473  uint8_t retry_count = 3;
474 
475  while(retry_count) {
476 
477  PRINTF("sicslowmac: sending packet of length %d to radio, result:", result.length);
478 
479 
480 
481  /* Send data to radio. */
482  radio_status_t rv = radio_send_data(result.length, result.frame);
483 
484  if (rv == RADIO_SUCCESS) {
485  PRINTF(" Success\n");
486 
487  return 1; /* True says that the packet could be sent */
488  }
489 
490 
491  if (rv != RADIO_WRONG_STATE) {
492  PRINTF(" Failed\n");
493  return 0;
494  }
495 
496  PRINTF(" Radio busy, retrying\n");
497 
498  /** \todo: Fix delay in sicslowmac so they do not block receiving */
499 
500  //We have blocking delay here, it is safest this way. BUT doesn't solve the
501  //problem of TX when you are RXing.. as the RX code can't execute!
502  if (retry_count == 3) {
503  _delay_ms(10);
504  } else if (retry_count == 2) {
505  _delay_ms(50);
506  } else if (retry_count == 1) {
507  _delay_ms(200);
508  }
509 
510  retry_count--;
511  }
512 
513  PRINTF("sicslowmac: Unable to send packet, dropped\n");
514  return 0;
515 
516 }
517 /*---------------------------------------------------------------------------*/
518 /**
519  * \brief Stub function that will be implemented in phase 2 to cause
520  * end nodes to sleep.
521  */
522 int
523 mac_wake(void)
524 {
525  return 1;
526 }
527 /*---------------------------------------------------------------------------*/
528 /**
529  * \brief Stub function that will be implemented in phase 2 to cause
530  * end nodes to sleep.
531  */
532 int
534 {
535  return 1;
536 }
537 /*---------------------------------------------------------------------------*/
538 const struct mac_driver *
539 sicslowmac_init(const struct radio_driver *d)
540 {
541  /* AD: commented out the radio_driver code for now.*/
542  /* radio = d;
543  radio->set_receive_function(input_packet);
544  radio->on();*/
545 
546  return &sicslowmac_driver;
547 }
548 /*---------------------------------------------------------------------------*/
549 /**
550  * \brief This is the implementation of the 15.4 MAC Reset Request
551  * primitive.
552  * \param setDefaultPIB True if the default PIB values should be set.
553  * \return Integer denoting success or failure.
554  * \retval 0 Failure.
555  * \retval 1 Success.
556  *
557  * Sets all PIB values to default.
558  */
559 void
560 sicslowmac_resetRequest (bool setDefaultPIB)
561 {
562  if(setDefaultPIB){
563  /* initialize all of the MAC PIB variables to their default values */
564  macCoordShortAddress = 0xffff;
565  macDSN = rand() % 256;
566  macSrcPANId = SOURCE_PAN_ID;
567  macDstPANId = DEST_PAN_ID;
568  macShortAddress = 0xffff;
569  /* Setup the address of this device by reading a stored address from eeprom. */
570  /** \todo This might be read from the serial eeprom onboard Raven. */
572  eeprom_read_block ((void *)&macLongAddr, EEPROMMACADDRESS, 8);
573 
574  byte_reverse((uint8_t *) &macLongAddr, 8);
575 
576 
578  }
579 }
580 
581 parsed_frame_t * sicslowmac_get_frame(void)
582 {
583  return parsed_frame;
584 }
585 
586 /*---------------------------------------------------------------------------*/
587 struct mac_driver * sicslowmac_get_driver(void)
588 {
589  return pmac_driver;
590 }
591 /*---------------------------------------------------------------------------*/
592 PROCESS(mac_process, "802.15.4 MAC process");
593 PROCESS_THREAD(mac_process, ev, data)
594 {
595 
596  PROCESS_POLLHANDLER(mac_pollhandler());
597 
598 
599  PROCESS_BEGIN();
600 
601  radio_status_t return_value;
602 
603  /* init radio */
604  /** \todo: this screws up if calosc is set to TRUE, find out why? */
605  return_value = radio_init(false, NULL, NULL, NULL);
606 
607 #if DEBUG
608  if (return_value == RADIO_SUCCESS) {
609  printf("Radio init successful.\n");
610  } else {
611  printf("Radio init failed with return: %d\n", return_value);
612  }
613 #endif
614 
615  uint8_t eeprom_channel;
616  uint8_t eeprom_check;
617 
618  eeprom_channel = eeprom_read_byte((uint8_t *)9);
619  eeprom_check = eeprom_read_byte((uint8_t *)10);
620 
621  if ((eeprom_channel < 11) || (eeprom_channel > 26) || ((uint8_t)eeprom_channel != (uint8_t)~eeprom_check)) {
622 #if UIP_CONF_USE_RUM
623  eeprom_channel = 19; //Default
624 #else
625  eeprom_channel = 24; //Default
626 #endif
627  }
628 
629  radio_set_operating_channel(eeprom_channel);
630  radio_use_auto_tx_crc(true);
632 
633  mac_init();
634 
635  /* Set up MAC function pointers and sicslowpan callback. */
636  pmac_driver->set_receive_function = setinput;
637  pmac_driver->send = sicslowmac_dataRequest;
638  sicslowpan_init(pmac_driver);
639 
640  ieee_15_4_init(&ieee15_4ManagerAddress);
641 
643 
644  while(1) {
645  PROCESS_YIELD();
646  mac_task(ev, data);
647 
648  }
649 
650  PROCESS_END();
651 }
652 
653 void byte_reverse(uint8_t * bytes, uint8_t num)
654 {
655  uint8_t tempbyte;
656 
657  uint8_t i, j;
658 
659  i = 0;
660  j = num - 1;
661 
662  while(i < j) {
663  tempbyte = bytes[i];
664  bytes[i] = bytes[j];
665  bytes[j] = tempbyte;
666 
667  j--;
668  i++;
669  }
670 
671  return;
672 }