Blame view

RIOT/sys/net/gnrc/link_layer/lwmac/timeout.c 4.18 KB
a752c7ab   elopes   add first test an...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
  /*
   * Copyright (C) 2015 Daniel Krebs
   *               2016 INRIA
   *
   * This file is subject to the terms and conditions of the GNU Lesser
   * General Public License v2.1. See the file LICENSE in the top level
   * directory for more details.
   */
  
  /**
   * @ingroup     net_gnrc_lwmac
   * @{
   *
   * @file
   * @brief       Timeout handling of LWMAC protocol
   *
   * @author      Daniel Krebs <github@daniel-krebs.net>
   * @author      Shuguo Zhuo  <shuguo.zhuo@inria.fr>
   * @}
   */
  
  #include <errno.h>
  
  #include "net/gnrc/lwmac/timeout.h"
  
  #define ENABLE_DEBUG    (0)
  #include "debug.h"
  
  #if ENABLE_DEBUG
  char *lwmac_timeout_names[] = {
      [GNRC_LWMAC_TIMEOUT_DISABLED]              = "DISABLED",
      [GNRC_LWMAC_TIMEOUT_WR]                    = "WR",
      [GNRC_LWMAC_TIMEOUT_NO_RESPONSE]           = "NO_RESPONSE",
      [GNRC_LWMAC_TIMEOUT_DATA]                  = "DATA",
      [GNRC_LWMAC_TIMEOUT_WAIT_DEST_WAKEUP]      = "WAIT_FOR_DEST_WAKEUP",
      [GNRC_LWMAC_TIMEOUT_WAKEUP_PERIOD]         = "WAKEUP_PERIOD",
  };
  #endif
  
  static inline void _lwmac_clear_timeout(gnrc_lwmac_timeout_t *timeout)
  {
      assert(timeout);
  
      xtimer_remove(&(timeout->timer));
      timeout->type = GNRC_LWMAC_TIMEOUT_DISABLED;
  }
  
  /* Return index >= 0 if found, -ENONENT if not found */
  static int _lwmac_find_timeout(gnrc_lwmac_t *lwmac, gnrc_lwmac_timeout_type_t type)
  {
      assert(lwmac);
  
      for (unsigned i = 0; i < GNRC_LWMAC_TIMEOUT_COUNT; i++) {
          if (lwmac->timeouts[i].type == type) {
              return i;
          }
      }
      return -ENOENT;
  }
  
  inline bool gnrc_lwmac_timeout_is_running(gnrc_netdev_t *gnrc_netdev,
                                            gnrc_lwmac_timeout_type_t type)
  {
      assert(gnrc_netdev);
      return (_lwmac_find_timeout(&gnrc_netdev->lwmac, type) >= 0);
  }
  
  bool gnrc_lwmac_timeout_is_expired(gnrc_netdev_t *gnrc_netdev, gnrc_lwmac_timeout_type_t type)
  {
      assert(gnrc_netdev);
  
      int index = _lwmac_find_timeout(&gnrc_netdev->lwmac, type);
      if (index >= 0) {
          if (gnrc_netdev->lwmac.timeouts[index].expired) {
              _lwmac_clear_timeout(&gnrc_netdev->lwmac.timeouts[index]);
          }
          return gnrc_netdev->lwmac.timeouts[index].expired;
      }
      return false;
  }
  
  gnrc_lwmac_timeout_t *_lwmac_acquire_timeout(gnrc_netdev_t *gnrc_netdev,
                                               gnrc_lwmac_timeout_type_t type)
  {
      assert(gnrc_netdev);
  
      if (gnrc_lwmac_timeout_is_running(gnrc_netdev, type)) {
          return NULL;
      }
  
      for (unsigned i = 0; i < GNRC_LWMAC_TIMEOUT_COUNT; i++) {
          if (gnrc_netdev->lwmac.timeouts[i].type == GNRC_LWMAC_TIMEOUT_DISABLED) {
              gnrc_netdev->lwmac.timeouts[i].type = type;
              return &gnrc_netdev->lwmac.timeouts[i];
          }
      }
      return NULL;
  }
  
  void gnrc_lwmac_timeout_make_expire(gnrc_lwmac_timeout_t *timeout)
  {
      assert(timeout);
  
      timeout->expired = true;
  }
  
  void gnrc_lwmac_clear_timeout(gnrc_netdev_t *gnrc_netdev, gnrc_lwmac_timeout_type_t type)
  {
      assert(gnrc_netdev);
  
      int index = _lwmac_find_timeout(&gnrc_netdev->lwmac, type);
      if (index >= 0) {
          _lwmac_clear_timeout(&gnrc_netdev->lwmac.timeouts[index]);
      }
  }
  
  void gnrc_lwmac_set_timeout(gnrc_netdev_t *gnrc_netdev,
                              gnrc_lwmac_timeout_type_t type,
                              uint32_t offset)
  {
      assert(gnrc_netdev);
  
      gnrc_lwmac_timeout_t *timeout;
      if ((timeout = _lwmac_acquire_timeout(gnrc_netdev, type))) {
          DEBUG("[LWMAC] Set timeout %s in %" PRIu32 " us\n",
                lwmac_timeout_names[type], offset);
          timeout->expired = false;
          timeout->msg.type = GNRC_LWMAC_EVENT_TIMEOUT_TYPE;
          timeout->msg.content.ptr = (void *) timeout;
          xtimer_set_msg(&(timeout->timer), offset,
                         &(timeout->msg), gnrc_netdev->pid);
      }
      else {
          DEBUG("[LWMAC] Cannot set timeout %s, too many concurrent timeouts\n",
                lwmac_timeout_names[type]);
      }
  }
  
  void gnrc_lwmac_reset_timeouts(gnrc_netdev_t *gnrc_netdev)
  {
      assert(gnrc_netdev);
  
      for (unsigned i = 0; i < GNRC_LWMAC_TIMEOUT_COUNT; i++) {
          if (gnrc_netdev->lwmac.timeouts[i].type != GNRC_LWMAC_TIMEOUT_DISABLED) {
              _lwmac_clear_timeout(&gnrc_netdev->lwmac.timeouts[i]);
          }
      }
  }