1 /*!
2 * \file LmhpCompliance.c
3 *
4 * \brief Implements the LoRa-Alliance certification protocol handling
5 *
6 * \copyright Revised BSD License, see section \ref LICENSE.
7 *
8 * \code
9 * ______ _
10 * / _____) _ | |
11 * ( (____ _____ ____ _| |_ _____ ____| |__
12 * \____ \| ___ | (_ _) ___ |/ ___) _ \
13 * _____) ) ____| | | || |_| ____( (___| | | |
14 * (______/|_____)_|_|_| \__)_____)\____)_| |_|
15 * (C)2013-2018 Semtech
16 *
17 * \endcode
18 *
19 * \author Miguel Luis ( Semtech )
20 */
21 #include <stdlib.h>
22 #include <stdint.h>
23 #include <stdbool.h>
24 #include "board.h"
25 #include "NvmDataMgmt.h"
26 #include "LoRaMacTest.h"
27 #include "LmHandler.h"
28 #include "LmhpCompliance.h"
29
30 /*!
31 * LoRaWAN compliance certification protocol port number.
32 *
33 * LoRaWAN Specification V1.x.x, chapter 4.3.2
34 */
35 #define COMPLIANCE_PORT 224
36
37 #define COMPLIANCE_ID 6
38 #define COMPLIANCE_VERSION 1
39
40 typedef struct ClassBStatus_s
41 {
42 bool IsBeaconRxOn;
43 uint8_t PingSlotPeriodicity;
44 uint16_t BeaconCnt;
45 BeaconInfo_t Info;
46 } ClassBStatus_t;
47
48 /*!
49 * LoRaWAN compliance tests support data
50 */
51 typedef struct ComplianceTestState_s
52 {
53 bool Initialized;
54 bool IsTxPending;
55 TimerTime_t TxPendingTimestamp;
56 LmHandlerMsgTypes_t IsTxConfirmed;
57 uint8_t DataBufferMaxSize;
58 uint8_t DataBufferSize;
59 uint8_t* DataBuffer;
60 uint16_t RxAppCnt;
61 bool IsBeaconRxStatusIndOn;
62 ClassBStatus_t ClassBStatus;
63 bool IsResetCmdPending;
64 bool IsClassReqCmdPending;
65 DeviceClass_t NewClass;
66 } ComplianceTestState_t;
67
68 typedef enum ComplianceMoteCmd_e
69 {
70 COMPLIANCE_PKG_VERSION_ANS = 0x00,
71 COMPLIANCE_ECHO_PAYLOAD_ANS = 0x08,
72 COMPLIANCE_RX_APP_CNT_ANS = 0x09,
73 COMPLIANCE_BEACON_RX_STATUS_IND = 0x41,
74 COMPLIANCE_BEACON_CNT_ANS = 0x42,
75 COMPLIANCE_DUT_VERSION_ANS = 0x7F,
76 } ComplianceMoteCmd_t;
77
78 typedef enum ComplianceSrvCmd_e
79 {
80 COMPLIANCE_PKG_VERSION_REQ = 0x00,
81 COMPLIANCE_DUT_RESET_REQ = 0x01,
82 COMPLIANCE_DUT_JOIN_REQ = 0x02,
83 COMPLIANCE_SWITCH_CLASS_REQ = 0x03,
84 COMPLIANCE_ADR_BIT_CHANGE_REQ = 0x04,
85 COMPLIANCE_REGIONAL_DUTY_CYCLE_CTRL_REQ = 0x05,
86 COMPLIANCE_TX_PERIODICITY_CHANGE_REQ = 0x06,
87 COMPLIANCE_TX_FRAMES_CTRL_REQ = 0x07,
88 COMPLIANCE_ECHO_PAYLOAD_REQ = 0x08,
89 COMPLIANCE_RX_APP_CNT_REQ = 0x09,
90 COMPLIANCE_RX_APP_CNT_RESET_REQ = 0x0A,
91 COMPLIANCE_LINK_CHECK_REQ = 0x20,
92 COMPLIANCE_DEVICE_TIME_REQ = 0x21,
93 COMPLIANCE_PING_SLOT_INFO_REQ = 0x22,
94 COMPLIANCE_BEACON_RX_STATUS_IND_CTRL = 0x40,
95 COMPLIANCE_BEACON_CNT_REQ = 0x42,
96 COMPLIANCE_BEACON_CNT_RESET_REQ = 0x43,
97 COMPLIANCE_TX_CW_REQ = 0x7D,
98 COMPLIANCE_DUT_FPORT_224_DISABLE_REQ = 0x7E,
99 COMPLIANCE_DUT_VERSION_REQ = 0x7F,
100 } ComplianceSrvCmd_t;
101
102 /*!
103 * Holds the compliance test current context
104 */
105 static ComplianceTestState_t ComplianceTestState = {
106 .Initialized = false,
107 .IsTxPending = false,
108 .TxPendingTimestamp = 0,
109 .IsTxConfirmed = LORAMAC_HANDLER_UNCONFIRMED_MSG,
110 .DataBufferMaxSize = 0,
111 .DataBufferSize = 0,
112 .DataBuffer = NULL,
113 .RxAppCnt = 0,
114 .ClassBStatus = { 0 },
115 .IsBeaconRxStatusIndOn = false,
116 .IsResetCmdPending = false,
117 .IsClassReqCmdPending = false,
118 .NewClass = CLASS_A,
119 };
120
121 /*!
122 * LoRaWAN compliance tests protocol handler parameters
123 */
124 static LmhpComplianceParams_t* ComplianceParams;
125
126 /*!
127 * Reset Beacon status structure
128 */
ClassBStatusReset(void)129 static inline void ClassBStatusReset( void )
130 {
131 memset1( ( uint8_t* ) &ComplianceTestState.ClassBStatus, 0, sizeof( ClassBStatus_t ) / sizeof( uint8_t ) );
132 }
133
134 /*!
135 * Initializes the compliance tests with provided parameters
136 *
137 * \param [IN] params Structure containing the initial compliance
138 * tests parameters.
139 * \param [IN] dataBuffer Pointer to main application buffer
140 * \param [IN] dataBufferMaxSize Application buffer maximum size
141 */
142 static void LmhpComplianceInit( void* params, uint8_t* dataBuffer, uint8_t dataBufferMaxSize );
143
144 /*!
145 * Returns the current compliance certification protocol initialization status.
146 *
147 * \retval status Compliance certification protocol initialization status
148 * [true: Initialized, false: Not initialized]
149 */
150 static bool LmhpComplianceIsInitialized( void );
151
152 /*!
153 * Returns if a package transmission is pending or not.
154 *
155 * \retval status Package transmission status
156 * [true: pending, false: Not pending]
157 */
158 static bool LmhpComplianceIsTxPending( void );
159
160 /*!
161 * Processes the LoRaMac Compliance events.
162 */
163 static void LmhpComplianceProcess( void );
164
165 /*!
166 * Processes the MCPS Indication
167 *
168 * \param [IN] mcpsIndication MCPS indication primitive data
169 */
170 static void LmhpComplianceOnMcpsIndication( McpsIndication_t* mcpsIndication );
171
172 /*!
173 * Processes the MLME Confirm
174 *
175 * \param [IN] mlmeConfirm MLME confirmation primitive data
176 */
177 static void LmhpComplianceOnMlmeConfirm( MlmeConfirm_t *mlmeConfirm );
178
179 /*!
180 * Processes the MLME Indication
181 *
182 * \param [IN] mlmeIndication MLME indication primitive data
183 */
184 static void LmhpComplianceOnMlmeIndication( MlmeIndication_t* mlmeIndication );
185
186 /*!
187 * Helper function to send the BeaconRxStatusInd message
188 *
189 * \param [IN] isBeaconRxStatusIndOn Indicates if the beacon status info is sent or not
190 */
191 static void SendBeaconRxStatusInd( bool isBeaconRxStatusIndOn );
192
193 LmhPackage_t CompliancePackage = {
194 .Port = COMPLIANCE_PORT,
195 .Init = LmhpComplianceInit,
196 .IsInitialized = LmhpComplianceIsInitialized,
197 .IsTxPending = LmhpComplianceIsTxPending,
198 .Process = LmhpComplianceProcess,
199 .OnMcpsConfirmProcess = NULL, // Not used in this package
200 .OnMcpsIndicationProcess = LmhpComplianceOnMcpsIndication,
201 .OnMlmeConfirmProcess = LmhpComplianceOnMlmeConfirm,
202 .OnMlmeIndicationProcess = LmhpComplianceOnMlmeIndication,
203 .OnMacMcpsRequest = NULL, // To be initialized by LmHandler
204 .OnMacMlmeRequest = NULL, // To be initialized by LmHandler
205 .OnJoinRequest = NULL, // To be initialized by LmHandler
206 .OnDeviceTimeRequest = NULL, // To be initialized by LmHandler
207 .OnSysTimeUpdate = NULL, // To be initialized by LmHandler
208 };
209
LmphCompliancePackageFactory(void)210 LmhPackage_t* LmphCompliancePackageFactory( void )
211 {
212 return &CompliancePackage;
213 }
214
LmhpComplianceInit(void * params,uint8_t * dataBuffer,uint8_t dataBufferMaxSize)215 static void LmhpComplianceInit( void* params, uint8_t* dataBuffer, uint8_t dataBufferMaxSize )
216 {
217 if( ( params != NULL ) && ( dataBuffer != NULL ) )
218 {
219 ComplianceParams = ( LmhpComplianceParams_t* ) params;
220 ComplianceTestState.DataBuffer = dataBuffer;
221 ComplianceTestState.DataBufferMaxSize = dataBufferMaxSize;
222 ComplianceTestState.Initialized = true;
223 }
224 else
225 {
226 ComplianceParams = NULL;
227 ComplianceTestState.Initialized = false;
228 }
229 ComplianceTestState.RxAppCnt = 0;
230 ClassBStatusReset( );
231 ComplianceTestState.IsTxPending = false;
232 ComplianceTestState.IsBeaconRxStatusIndOn = false;
233 ComplianceTestState.IsResetCmdPending = false;
234 ComplianceTestState.IsClassReqCmdPending = false;
235 }
236
LmhpComplianceIsInitialized(void)237 static bool LmhpComplianceIsInitialized( void )
238 {
239 return ComplianceTestState.Initialized;
240 }
241
LmhpComplianceIsTxPending(void)242 static bool LmhpComplianceIsTxPending( void )
243 {
244 return ComplianceTestState.IsTxPending;
245 }
246
LmhpComplianceProcess(void)247 static void LmhpComplianceProcess( void )
248 {
249 if( ComplianceTestState.IsTxPending == true )
250 {
251 TimerTime_t now = TimerGetCurrentTime( );
252 if( now > ( ComplianceTestState.TxPendingTimestamp + LmHandlerGetDutyCycleWaitTime( ) ) )
253 {
254 if( ComplianceTestState.DataBufferSize != 0 )
255 {
256 // Answer commands
257 LmHandlerAppData_t appData = {
258 .Buffer = ComplianceTestState.DataBuffer,
259 .BufferSize = ComplianceTestState.DataBufferSize,
260 .Port = COMPLIANCE_PORT,
261 };
262
263 if( LmHandlerSend( &appData, ComplianceTestState.IsTxConfirmed ) != LORAMAC_HANDLER_SUCCESS )
264 {
265 // try to send the message again
266 ComplianceTestState.IsTxPending = true;
267 }
268 else
269 {
270 ComplianceTestState.IsTxPending = false;
271 }
272 ComplianceTestState.TxPendingTimestamp = now;
273 }
274 }
275 }
276 else
277 { // If no Tx is pending process other commands
278 if( ComplianceTestState.IsClassReqCmdPending == true )
279 {
280 ComplianceTestState.IsClassReqCmdPending = false;
281 LmHandlerRequestClass( ComplianceTestState.NewClass );
282 }
283 }
284
285 if( ComplianceTestState.IsResetCmdPending == true )
286 {
287 ComplianceTestState.IsResetCmdPending = false;
288
289 // Call platform MCU reset API
290 BoardResetMcu( );
291 }
292 }
293
LmhpComplianceOnMcpsIndication(McpsIndication_t * mcpsIndication)294 static void LmhpComplianceOnMcpsIndication( McpsIndication_t* mcpsIndication )
295 {
296 uint8_t cmdIndex = 0;
297 MibRequestConfirm_t mibReq;
298
299 if( ComplianceTestState.Initialized == false )
300 {
301 return;
302 }
303
304 // Increment the compliance certification protocol downlink counter
305 // Not counting downlinks on FPort 0
306 if( ( mcpsIndication->Port > 0 ) || ( mcpsIndication->AckReceived == true ) )
307 {
308 ComplianceTestState.RxAppCnt++;
309 }
310
311 if( mcpsIndication->RxData == false )
312 {
313 return;
314 }
315
316 if( mcpsIndication->Port != COMPLIANCE_PORT )
317 {
318 return;
319 }
320
321 ComplianceTestState.DataBufferSize = 0;
322
323 switch( mcpsIndication->Buffer[cmdIndex++] )
324 {
325 case COMPLIANCE_PKG_VERSION_REQ:
326 {
327 ComplianceTestState.DataBuffer[ComplianceTestState.DataBufferSize++] = COMPLIANCE_PKG_VERSION_ANS;
328 ComplianceTestState.DataBuffer[ComplianceTestState.DataBufferSize++] = COMPLIANCE_ID;
329 ComplianceTestState.DataBuffer[ComplianceTestState.DataBufferSize++] = COMPLIANCE_VERSION;
330 break;
331 }
332 case COMPLIANCE_DUT_RESET_REQ:
333 {
334 ComplianceTestState.IsResetCmdPending = true;
335 break;
336 }
337 case COMPLIANCE_DUT_JOIN_REQ:
338 {
339 CompliancePackage.OnJoinRequest( true );
340 break;
341 }
342 case COMPLIANCE_SWITCH_CLASS_REQ:
343 {
344 // CLASS_A = 0, CLASS_B = 1, CLASS_C = 2
345 ComplianceTestState.NewClass = ( DeviceClass_t ) mcpsIndication->Buffer[cmdIndex++];
346 ComplianceTestState.IsClassReqCmdPending = true;
347 break;
348 }
349 case COMPLIANCE_ADR_BIT_CHANGE_REQ:
350 {
351 MibRequestConfirm_t mibReq;
352 mibReq.Type = MIB_ADR;
353 mibReq.Param.AdrEnable = mcpsIndication->Buffer[cmdIndex++];
354
355 LoRaMacMibSetRequestConfirm( &mibReq );
356 break;
357 }
358 case COMPLIANCE_REGIONAL_DUTY_CYCLE_CTRL_REQ:
359 {
360 LoRaMacTestSetDutyCycleOn( mcpsIndication->Buffer[cmdIndex++] );
361 break;
362 }
363 case COMPLIANCE_TX_PERIODICITY_CHANGE_REQ:
364 {
365 // Periodicity in milli-seconds
366 uint32_t periodicity[] = { 0, 5000, 10000, 20000, 30000, 40000, 50000, 60000, 120000, 240000, 480000 };
367 uint8_t index = mcpsIndication->Buffer[cmdIndex++];
368
369 if( index < ( sizeof( periodicity ) / sizeof( uint32_t ) ) )
370 {
371 if( ComplianceParams->OnTxPeriodicityChanged != NULL )
372 {
373 ComplianceParams->OnTxPeriodicityChanged( periodicity[index] );
374 }
375 }
376 break;
377 }
378 case COMPLIANCE_TX_FRAMES_CTRL_REQ:
379 {
380 uint8_t frameType = mcpsIndication->Buffer[cmdIndex++];
381
382 if( ( frameType == 1 ) || ( frameType == 2 ) )
383 {
384 ComplianceTestState.IsTxConfirmed = ( frameType != 1 ) ? LORAMAC_HANDLER_CONFIRMED_MSG : LORAMAC_HANDLER_UNCONFIRMED_MSG;
385
386 ComplianceParams->OnTxFrameCtrlChanged( ComplianceTestState.IsTxConfirmed );
387 }
388 break;
389 }
390 case COMPLIANCE_ECHO_PAYLOAD_REQ:
391 {
392 ComplianceTestState.DataBuffer[ComplianceTestState.DataBufferSize++] = COMPLIANCE_ECHO_PAYLOAD_ANS;
393
394 for( uint8_t i = 1; i < MIN( mcpsIndication->BufferSize, ComplianceTestState.DataBufferMaxSize );
395 i++ )
396 {
397 ComplianceTestState.DataBuffer[ComplianceTestState.DataBufferSize++] = mcpsIndication->Buffer[cmdIndex++] + 1;
398 }
399 break;
400 }
401 case COMPLIANCE_RX_APP_CNT_REQ:
402 {
403 ComplianceTestState.DataBuffer[ComplianceTestState.DataBufferSize++] = COMPLIANCE_RX_APP_CNT_ANS;
404 ComplianceTestState.DataBuffer[ComplianceTestState.DataBufferSize++] = ComplianceTestState.RxAppCnt;
405 ComplianceTestState.DataBuffer[ComplianceTestState.DataBufferSize++] = ComplianceTestState.RxAppCnt >> 8;
406 break;
407 }
408 case COMPLIANCE_RX_APP_CNT_RESET_REQ:
409 {
410 ComplianceTestState.RxAppCnt = 0;
411 break;
412 }
413 case COMPLIANCE_LINK_CHECK_REQ:
414 {
415 MlmeReq_t mlmeReq;
416 mlmeReq.Type = MLME_LINK_CHECK;
417
418 LoRaMacStatus_t status = LoRaMacMlmeRequest( &mlmeReq );
419 if( CompliancePackage.OnMacMlmeRequest != NULL )
420 {
421 CompliancePackage.OnMacMlmeRequest( status, &mlmeReq, mlmeReq.ReqReturn.DutyCycleWaitTime );
422 }
423 break;
424 }
425 case COMPLIANCE_DEVICE_TIME_REQ:
426 {
427 CompliancePackage.OnDeviceTimeRequest( );
428 break;
429 }
430 case COMPLIANCE_PING_SLOT_INFO_REQ:
431 {
432 ComplianceTestState.ClassBStatus.PingSlotPeriodicity = mcpsIndication->Buffer[cmdIndex++];
433 ComplianceParams->OnPingSlotPeriodicityChanged( ComplianceTestState.ClassBStatus.PingSlotPeriodicity );
434 break;
435 }
436 case COMPLIANCE_BEACON_RX_STATUS_IND_CTRL:
437 {
438 ComplianceTestState.IsBeaconRxStatusIndOn = ( bool ) mcpsIndication->Buffer[cmdIndex++];
439 break;
440 }
441 case COMPLIANCE_BEACON_CNT_REQ:
442 {
443 ComplianceTestState.DataBuffer[ComplianceTestState.DataBufferSize++] = COMPLIANCE_BEACON_CNT_ANS;
444 ComplianceTestState.DataBuffer[ComplianceTestState.DataBufferSize++] = ComplianceTestState.ClassBStatus.BeaconCnt;
445 ComplianceTestState.DataBuffer[ComplianceTestState.DataBufferSize++] = ComplianceTestState.ClassBStatus.BeaconCnt >> 8;
446 break;
447 }
448 case COMPLIANCE_BEACON_CNT_RESET_REQ:
449 {
450 ComplianceTestState.ClassBStatus.BeaconCnt = 0;
451 break;
452 }
453 case COMPLIANCE_TX_CW_REQ:
454 {
455 MlmeReq_t mlmeReq;
456 if( mcpsIndication->BufferSize == 7 )
457 {
458 mlmeReq.Type = MLME_TXCW;
459 mlmeReq.Req.TxCw.Timeout =
460 ( uint16_t )( mcpsIndication->Buffer[cmdIndex] | ( mcpsIndication->Buffer[cmdIndex + 1] << 8 ) );
461 cmdIndex += 2;
462 mlmeReq.Req.TxCw.Frequency =
463 ( uint32_t )( mcpsIndication->Buffer[cmdIndex] | ( mcpsIndication->Buffer[cmdIndex + 1] << 8 ) |
464 ( mcpsIndication->Buffer[cmdIndex + 2] << 16 ) ) *
465 100;
466 cmdIndex += 3;
467 mlmeReq.Req.TxCw.Power = mcpsIndication->Buffer[cmdIndex++];
468
469 CompliancePackage.OnMacMlmeRequest( LoRaMacMlmeRequest( &mlmeReq ), &mlmeReq,
470 mlmeReq.ReqReturn.DutyCycleWaitTime );
471 }
472 break;
473 }
474 case COMPLIANCE_DUT_FPORT_224_DISABLE_REQ:
475 {
476 mibReq.Type = MIB_IS_CERT_FPORT_ON;
477 mibReq.Param.IsCertPortOn = false;
478 LoRaMacMibSetRequestConfirm( &mibReq );
479
480 ComplianceTestState.IsResetCmdPending = true;
481 break;
482 }
483 case COMPLIANCE_DUT_VERSION_REQ:
484 {
485 Version_t lrwanVersion;
486 Version_t lrwanRpVersion;
487 MibRequestConfirm_t mibReq;
488
489 mibReq.Type = MIB_LORAWAN_VERSION;
490
491 LoRaMacMibGetRequestConfirm( &mibReq );
492 lrwanVersion = mibReq.Param.LrWanVersion.LoRaWan;
493 lrwanRpVersion = mibReq.Param.LrWanVersion.LoRaWanRegion;
494
495 ComplianceTestState.DataBuffer[ComplianceTestState.DataBufferSize++] = COMPLIANCE_DUT_VERSION_ANS;
496 ComplianceTestState.DataBuffer[ComplianceTestState.DataBufferSize++] = ComplianceParams->FwVersion.Fields.Major;
497 ComplianceTestState.DataBuffer[ComplianceTestState.DataBufferSize++] = ComplianceParams->FwVersion.Fields.Minor;
498 ComplianceTestState.DataBuffer[ComplianceTestState.DataBufferSize++] = ComplianceParams->FwVersion.Fields.Patch;
499 ComplianceTestState.DataBuffer[ComplianceTestState.DataBufferSize++] = ComplianceParams->FwVersion.Fields.Revision;
500 ComplianceTestState.DataBuffer[ComplianceTestState.DataBufferSize++] = lrwanVersion.Fields.Major;
501 ComplianceTestState.DataBuffer[ComplianceTestState.DataBufferSize++] = lrwanVersion.Fields.Minor;
502 ComplianceTestState.DataBuffer[ComplianceTestState.DataBufferSize++] = lrwanVersion.Fields.Patch;
503 ComplianceTestState.DataBuffer[ComplianceTestState.DataBufferSize++] = lrwanVersion.Fields.Revision;
504 ComplianceTestState.DataBuffer[ComplianceTestState.DataBufferSize++] = lrwanRpVersion.Fields.Major;
505 ComplianceTestState.DataBuffer[ComplianceTestState.DataBufferSize++] = lrwanRpVersion.Fields.Minor;
506 ComplianceTestState.DataBuffer[ComplianceTestState.DataBufferSize++] = lrwanRpVersion.Fields.Patch;
507 ComplianceTestState.DataBuffer[ComplianceTestState.DataBufferSize++] = lrwanRpVersion.Fields.Revision;
508 break;
509 }
510 default:
511 {
512 break;
513 }
514 }
515
516 if( ComplianceTestState.DataBufferSize != 0 )
517 {
518 ComplianceTestState.IsTxPending = true;
519 }
520 else
521 {
522 // Abort any pending Tx as a new command has been processed
523 ComplianceTestState.IsTxPending = false;
524 }
525 }
526
LmhpComplianceOnMlmeConfirm(MlmeConfirm_t * mlmeConfirm)527 static void LmhpComplianceOnMlmeConfirm( MlmeConfirm_t *mlmeConfirm )
528 {
529 switch( mlmeConfirm->MlmeRequest )
530 {
531 case MLME_BEACON_ACQUISITION:
532 {
533 if( mlmeConfirm->Status == LORAMAC_EVENT_INFO_STATUS_OK )
534 {
535 ClassBStatusReset( );
536 ComplianceTestState.ClassBStatus.IsBeaconRxOn = true;
537 }
538 else
539 {
540 ComplianceTestState.ClassBStatus.IsBeaconRxOn = false;
541 }
542 break;
543 }
544 default:
545 break;
546 }
547 }
548
LmhpComplianceOnMlmeIndication(MlmeIndication_t * mlmeIndication)549 static void LmhpComplianceOnMlmeIndication( MlmeIndication_t* mlmeIndication )
550 {
551 if( ComplianceTestState.Initialized == false )
552 {
553 return;
554 }
555
556 switch( mlmeIndication->MlmeIndication )
557 {
558 case MLME_BEACON_LOST:
559 {
560 ClassBStatusReset( );
561 SendBeaconRxStatusInd( ComplianceTestState.IsBeaconRxStatusIndOn );
562 break;
563 }
564 case MLME_BEACON:
565 {
566 if( mlmeIndication->Status == LORAMAC_EVENT_INFO_STATUS_BEACON_LOCKED )
567 {
568 // As we received a beacon ensure that IsBeaconRxOn is set to true
569 if( ComplianceTestState.ClassBStatus.IsBeaconRxOn == false )
570 {
571 ComplianceTestState.ClassBStatus.IsBeaconRxOn = true;
572 }
573 ComplianceTestState.ClassBStatus.BeaconCnt++;
574 }
575 ComplianceTestState.ClassBStatus.Info = mlmeIndication->BeaconInfo;
576 SendBeaconRxStatusInd( ComplianceTestState.IsBeaconRxStatusIndOn );
577 break;
578 }
579 default:
580 break;
581 }
582 }
583
SendBeaconRxStatusInd(bool isBeaconRxStatusIndOn)584 static void SendBeaconRxStatusInd( bool isBeaconRxStatusIndOn )
585 {
586 if( isBeaconRxStatusIndOn == false )
587 {
588 return;
589 }
590 uint32_t frequency = ComplianceTestState.ClassBStatus.Info.Frequency / 100;
591
592 ComplianceTestState.DataBufferSize = 0;
593 ComplianceTestState.DataBuffer[ComplianceTestState.DataBufferSize++] = COMPLIANCE_BEACON_RX_STATUS_IND;
594 ComplianceTestState.DataBuffer[ComplianceTestState.DataBufferSize++] = ( ComplianceTestState.ClassBStatus.IsBeaconRxOn == true ) ? 1 : 0;
595 ComplianceTestState.DataBuffer[ComplianceTestState.DataBufferSize++] = ( uint8_t )( ComplianceTestState.ClassBStatus.BeaconCnt );
596 ComplianceTestState.DataBuffer[ComplianceTestState.DataBufferSize++] = ( uint8_t )( ComplianceTestState.ClassBStatus.BeaconCnt >> 8 );
597 ComplianceTestState.DataBuffer[ComplianceTestState.DataBufferSize++] = ( uint8_t )( frequency );
598 ComplianceTestState.DataBuffer[ComplianceTestState.DataBufferSize++] = ( uint8_t )( frequency >> 8 );
599 ComplianceTestState.DataBuffer[ComplianceTestState.DataBufferSize++] = ( uint8_t )( frequency >> 16 );
600 ComplianceTestState.DataBuffer[ComplianceTestState.DataBufferSize++] = ComplianceTestState.ClassBStatus.Info.Datarate;
601 ComplianceTestState.DataBuffer[ComplianceTestState.DataBufferSize++] = ( uint8_t )( ComplianceTestState.ClassBStatus.Info.Rssi );
602 ComplianceTestState.DataBuffer[ComplianceTestState.DataBufferSize++] = ( uint8_t )( ComplianceTestState.ClassBStatus.Info.Rssi >> 8 );
603 ComplianceTestState.DataBuffer[ComplianceTestState.DataBufferSize++] = ( uint8_t )( ComplianceTestState.ClassBStatus.Info.Snr );
604 ComplianceTestState.DataBuffer[ComplianceTestState.DataBufferSize++] = ( uint8_t )( ComplianceTestState.ClassBStatus.Info.Param );
605 ComplianceTestState.DataBuffer[ComplianceTestState.DataBufferSize++] = ( uint8_t )( ComplianceTestState.ClassBStatus.Info.Time.Seconds );
606 ComplianceTestState.DataBuffer[ComplianceTestState.DataBufferSize++] = ( uint8_t )( ComplianceTestState.ClassBStatus.Info.Time.Seconds >> 8 );
607 ComplianceTestState.DataBuffer[ComplianceTestState.DataBufferSize++] = ( uint8_t )( ComplianceTestState.ClassBStatus.Info.Time.Seconds >> 16 );
608 ComplianceTestState.DataBuffer[ComplianceTestState.DataBufferSize++] = ( uint8_t )( ComplianceTestState.ClassBStatus.Info.Time.Seconds >> 24 );
609 ComplianceTestState.DataBuffer[ComplianceTestState.DataBufferSize++] = ( uint8_t )( ComplianceTestState.ClassBStatus.Info.GwSpecific.InfoDesc );
610 ComplianceTestState.DataBuffer[ComplianceTestState.DataBufferSize++] = ( uint8_t )( ComplianceTestState.ClassBStatus.Info.GwSpecific.Info[0] );
611 ComplianceTestState.DataBuffer[ComplianceTestState.DataBufferSize++] = ( uint8_t )( ComplianceTestState.ClassBStatus.Info.GwSpecific.Info[1] );
612 ComplianceTestState.DataBuffer[ComplianceTestState.DataBufferSize++] = ( uint8_t )( ComplianceTestState.ClassBStatus.Info.GwSpecific.Info[2] );
613 ComplianceTestState.DataBuffer[ComplianceTestState.DataBufferSize++] = ( uint8_t )( ComplianceTestState.ClassBStatus.Info.GwSpecific.Info[3] );
614 ComplianceTestState.DataBuffer[ComplianceTestState.DataBufferSize++] = ( uint8_t )( ComplianceTestState.ClassBStatus.Info.GwSpecific.Info[4] );
615 ComplianceTestState.DataBuffer[ComplianceTestState.DataBufferSize++] = ( uint8_t )( ComplianceTestState.ClassBStatus.Info.GwSpecific.Info[5] );
616
617 ComplianceTestState.IsTxPending = true;
618 }
619