1 /*
2 / _____) _ | |
3 ( (____ _____ ____ _| |_ _____ ____| |__
4 \____ \| ___ | (_ _) ___ |/ ___) _ \
5 _____) ) ____| | | || |_| ____( (___| | | |
6 (______/|_____)_|_|_| \__)_____)\____)_| |_|
7 (C)2013 Semtech
8 ___ _____ _ ___ _ _____ ___ ___ ___ ___
9 / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
10 \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
11 |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
12 embedded.connectivity.solutions===============
13
14 Description: LoRa MAC confirm queue implementation
15
16 License: Revised BSD License, see LICENSE.TXT file include in the project
17
18 Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jaeckle ( STACKFORCE )
19 */
20 #include <stdint.h>
21 #include <stdbool.h>
22 #include <stddef.h>
23
24 #include "timer.h"
25 #include "utilities.h"
26 #include "LoRaMac.h"
27 #include "LoRaMacConfirmQueue.h"
28
29
30 /*
31 * LoRaMac Confirm Queue Context NVM structure
32 */
33 typedef struct sLoRaMacConfirmQueueNvmData
34 {
35 /*!
36 * MlmeConfirm queue data structure
37 */
38 MlmeConfirmQueue_t MlmeConfirmQueue[LORA_MAC_MLME_CONFIRM_QUEUE_LEN];
39 /*!
40 * Counts the number of MlmeConfirms to process
41 */
42 uint8_t MlmeConfirmQueueCnt;
43 /*!
44 * Variable which holds a common status
45 */
46 LoRaMacEventInfoStatus_t CommonStatus;
47 } LoRaMacConfirmQueueNvmData_t;
48
49 /*
50 * LoRaMac Confirm Queue Context structure
51 */
52 typedef struct sLoRaMacConfirmQueueCtx
53 {
54 /*!
55 * LoRaMac callback function primitives
56 */
57 LoRaMacPrimitives_t* Primitives;
58 /*!
59 * Pointer to the first element of the ring buffer
60 */
61 MlmeConfirmQueue_t* BufferStart;
62 /*!
63 * Pointer to the last element of the ring buffer
64 */
65 MlmeConfirmQueue_t* BufferEnd;
66 /*!
67 * Non-volatile module context.
68 */
69 LoRaMacConfirmQueueNvmData_t Nvm;
70 } LoRaMacConfirmQueueCtx_t;
71
72 /*
73 * Module context.
74 */
75 static LoRaMacConfirmQueueCtx_t ConfirmQueueCtx;
76
IncreaseBufferPointer(MlmeConfirmQueue_t * bufferPointer)77 static MlmeConfirmQueue_t* IncreaseBufferPointer( MlmeConfirmQueue_t* bufferPointer )
78 {
79 if( bufferPointer == &ConfirmQueueCtx.Nvm.MlmeConfirmQueue[LORA_MAC_MLME_CONFIRM_QUEUE_LEN - 1] )
80 {
81 // Reset to the first element
82 bufferPointer = ConfirmQueueCtx.Nvm.MlmeConfirmQueue;
83 }
84 else
85 {
86 // Increase
87 bufferPointer++;
88 }
89 return bufferPointer;
90 }
91
DecreaseBufferPointer(MlmeConfirmQueue_t * bufferPointer)92 static MlmeConfirmQueue_t* DecreaseBufferPointer( MlmeConfirmQueue_t* bufferPointer )
93 {
94 if( bufferPointer == ConfirmQueueCtx.Nvm.MlmeConfirmQueue )
95 {
96 // Reset to the last element
97 bufferPointer = &ConfirmQueueCtx.Nvm.MlmeConfirmQueue[LORA_MAC_MLME_CONFIRM_QUEUE_LEN - 1];
98 }
99 else
100 {
101 bufferPointer--;
102 }
103 return bufferPointer;
104 }
105
IsListEmpty(uint8_t count)106 static bool IsListEmpty( uint8_t count )
107 {
108 if( count == 0 )
109 {
110 return true;
111 }
112 return false;
113 }
114
IsListFull(uint8_t count)115 static bool IsListFull( uint8_t count )
116 {
117 if( count >= LORA_MAC_MLME_CONFIRM_QUEUE_LEN )
118 {
119 return true;
120 }
121 return false;
122 }
123
GetElement(Mlme_t request,MlmeConfirmQueue_t * bufferStart,MlmeConfirmQueue_t * bufferEnd)124 static MlmeConfirmQueue_t* GetElement( Mlme_t request, MlmeConfirmQueue_t* bufferStart, MlmeConfirmQueue_t* bufferEnd )
125 {
126 MlmeConfirmQueue_t* element = bufferStart;
127
128 if( IsListEmpty( ConfirmQueueCtx.Nvm.MlmeConfirmQueueCnt ) == true )
129 {
130 return NULL;
131 }
132
133 for( uint8_t elementCnt = 0; elementCnt < ConfirmQueueCtx.Nvm.MlmeConfirmQueueCnt; elementCnt++ )
134 {
135 if( element->Request == request )
136 {
137 // We have found the element
138 return element;
139 }
140 element = IncreaseBufferPointer( element );
141 }
142
143 return NULL;
144 }
145
LoRaMacConfirmQueueInit(LoRaMacPrimitives_t * primitives)146 void LoRaMacConfirmQueueInit( LoRaMacPrimitives_t* primitives )
147 {
148 ConfirmQueueCtx.Primitives = primitives;
149
150 // Init counter
151 ConfirmQueueCtx.Nvm.MlmeConfirmQueueCnt = 0;
152
153 // Init buffer
154 ConfirmQueueCtx.BufferStart = ConfirmQueueCtx.Nvm.MlmeConfirmQueue;
155 ConfirmQueueCtx.BufferEnd = ConfirmQueueCtx.Nvm.MlmeConfirmQueue;
156
157 memset1( ( uint8_t* )ConfirmQueueCtx.Nvm.MlmeConfirmQueue, 0xFF, sizeof( ConfirmQueueCtx.Nvm.MlmeConfirmQueue ) );
158
159 // Common status
160 ConfirmQueueCtx.Nvm.CommonStatus = LORAMAC_EVENT_INFO_STATUS_ERROR;
161 }
162
LoRaMacConfirmQueueAdd(MlmeConfirmQueue_t * mlmeConfirm)163 bool LoRaMacConfirmQueueAdd( MlmeConfirmQueue_t* mlmeConfirm )
164 {
165 if( IsListFull( ConfirmQueueCtx.Nvm.MlmeConfirmQueueCnt ) == true )
166 {
167 // Protect the buffer against overwrites
168 return false;
169 }
170
171 // Add the element to the ring buffer
172 ConfirmQueueCtx.BufferEnd->Request = mlmeConfirm->Request;
173 ConfirmQueueCtx.BufferEnd->Status = mlmeConfirm->Status;
174 ConfirmQueueCtx.BufferEnd->RestrictCommonReadyToHandle = mlmeConfirm->RestrictCommonReadyToHandle;
175 ConfirmQueueCtx.BufferEnd->ReadyToHandle = mlmeConfirm->ReadyToHandle;
176 // Increase counter
177 ConfirmQueueCtx.Nvm.MlmeConfirmQueueCnt++;
178 // Update end pointer
179 ConfirmQueueCtx.BufferEnd = IncreaseBufferPointer( ConfirmQueueCtx.BufferEnd );
180
181 return true;
182 }
183
LoRaMacConfirmQueueRemoveLast(void)184 bool LoRaMacConfirmQueueRemoveLast( void )
185 {
186 if( IsListEmpty( ConfirmQueueCtx.Nvm.MlmeConfirmQueueCnt ) == true )
187 {
188 return false;
189 }
190
191 // Increase counter
192 ConfirmQueueCtx.Nvm.MlmeConfirmQueueCnt--;
193 // Update start pointer
194 ConfirmQueueCtx.BufferEnd = DecreaseBufferPointer( ConfirmQueueCtx.BufferEnd );
195
196 return true;
197 }
198
LoRaMacConfirmQueueRemoveFirst(void)199 bool LoRaMacConfirmQueueRemoveFirst( void )
200 {
201 if( IsListEmpty( ConfirmQueueCtx.Nvm.MlmeConfirmQueueCnt ) == true )
202 {
203 return false;
204 }
205
206 // Increase counter
207 ConfirmQueueCtx.Nvm.MlmeConfirmQueueCnt--;
208 // Update start pointer
209 ConfirmQueueCtx.BufferStart = IncreaseBufferPointer( ConfirmQueueCtx.BufferStart );
210
211 return true;
212 }
213
LoRaMacConfirmQueueSetStatus(LoRaMacEventInfoStatus_t status,Mlme_t request)214 void LoRaMacConfirmQueueSetStatus( LoRaMacEventInfoStatus_t status, Mlme_t request )
215 {
216 MlmeConfirmQueue_t* element = NULL;
217
218 if( IsListEmpty( ConfirmQueueCtx.Nvm.MlmeConfirmQueueCnt ) == false )
219 {
220 element = GetElement( request, ConfirmQueueCtx.BufferStart, ConfirmQueueCtx.BufferEnd );
221 if( element != NULL )
222 {
223 element->Status = status;
224 element->ReadyToHandle = true;
225 }
226 }
227 }
228
LoRaMacConfirmQueueGetStatus(Mlme_t request)229 LoRaMacEventInfoStatus_t LoRaMacConfirmQueueGetStatus( Mlme_t request )
230 {
231 MlmeConfirmQueue_t* element = NULL;
232
233 if( IsListEmpty( ConfirmQueueCtx.Nvm.MlmeConfirmQueueCnt ) == false )
234 {
235 element = GetElement( request, ConfirmQueueCtx.BufferStart, ConfirmQueueCtx.BufferEnd );
236 if( element != NULL )
237 {
238 return element->Status;
239 }
240 }
241 return LORAMAC_EVENT_INFO_STATUS_ERROR;
242 }
243
LoRaMacConfirmQueueSetStatusCmn(LoRaMacEventInfoStatus_t status)244 void LoRaMacConfirmQueueSetStatusCmn( LoRaMacEventInfoStatus_t status )
245 {
246 MlmeConfirmQueue_t* element = ConfirmQueueCtx.BufferStart;
247
248 ConfirmQueueCtx.Nvm.CommonStatus = status;
249
250 if( IsListEmpty( ConfirmQueueCtx.Nvm.MlmeConfirmQueueCnt ) == false )
251 {
252 do
253 {
254 element->Status = status;
255 // Set the status if it is allowed to set it with a call to
256 // LoRaMacConfirmQueueSetStatusCmn.
257 if( element->RestrictCommonReadyToHandle == false )
258 {
259 element->ReadyToHandle = true;
260 }
261 element = IncreaseBufferPointer( element );
262 }while( element != ConfirmQueueCtx.BufferEnd );
263 }
264 }
265
LoRaMacConfirmQueueGetStatusCmn(void)266 LoRaMacEventInfoStatus_t LoRaMacConfirmQueueGetStatusCmn( void )
267 {
268 return ConfirmQueueCtx.Nvm.CommonStatus;
269 }
270
LoRaMacConfirmQueueIsCmdActive(Mlme_t request)271 bool LoRaMacConfirmQueueIsCmdActive( Mlme_t request )
272 {
273 if( GetElement( request, ConfirmQueueCtx.BufferStart, ConfirmQueueCtx.BufferEnd ) != NULL )
274 {
275 return true;
276 }
277 return false;
278 }
279
LoRaMacConfirmQueueHandleCb(MlmeConfirm_t * mlmeConfirm)280 void LoRaMacConfirmQueueHandleCb( MlmeConfirm_t* mlmeConfirm )
281 {
282 uint8_t nbElements = ConfirmQueueCtx.Nvm.MlmeConfirmQueueCnt;
283 bool readyToHandle = false;
284 MlmeConfirmQueue_t mlmeConfirmToStore;
285
286 for( uint8_t i = 0; i < nbElements; i++ )
287 {
288 mlmeConfirm->MlmeRequest = ConfirmQueueCtx.BufferStart->Request;
289 mlmeConfirm->Status = ConfirmQueueCtx.BufferStart->Status;
290 readyToHandle = ConfirmQueueCtx.BufferStart->ReadyToHandle;
291
292 if( readyToHandle == true )
293 {
294 ConfirmQueueCtx.Primitives->MacMlmeConfirm( mlmeConfirm );
295 }
296 else
297 {
298 // The request is not processed yet. Store the state.
299 mlmeConfirmToStore.Request = ConfirmQueueCtx.BufferStart->Request;
300 mlmeConfirmToStore.Status = ConfirmQueueCtx.BufferStart->Status;
301 mlmeConfirmToStore.RestrictCommonReadyToHandle = ConfirmQueueCtx.BufferStart->RestrictCommonReadyToHandle;
302 }
303
304 // Increase the pointer afterwards to prevent overwrites
305 LoRaMacConfirmQueueRemoveFirst( );
306
307 if( readyToHandle == false )
308 {
309 // Add a request which has not been finished again to the queue
310 LoRaMacConfirmQueueAdd( &mlmeConfirmToStore );
311 }
312 }
313 }
314
LoRaMacConfirmQueueGetCnt(void)315 uint8_t LoRaMacConfirmQueueGetCnt( void )
316 {
317 return ConfirmQueueCtx.Nvm.MlmeConfirmQueueCnt;
318 }
319
LoRaMacConfirmQueueIsFull(void)320 bool LoRaMacConfirmQueueIsFull( void )
321 {
322 if( IsListFull( ConfirmQueueCtx.Nvm.MlmeConfirmQueueCnt ) == true )
323 {
324 return true;
325 }
326 else
327 {
328 return false;
329 }
330 }
331