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