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