1 /*!
2 * \file LmhpRemoteMcastSetup.c
3 *
4 * \brief Implements the LoRa-Alliance remote multicast setup package
5 * Specification: https://lora-alliance.org/sites/default/files/2018-09/remote_multicast_setup_v1.0.0.pdf
6 *
7 * \copyright Revised BSD License, see section \ref LICENSE.
8 *
9 * \code
10 * ______ _
11 * / _____) _ | |
12 * ( (____ _____ ____ _| |_ _____ ____| |__
13 * \____ \| ___ | (_ _) ___ |/ ___) _ \
14 * _____) ) ____| | | || |_| ____( (___| | | |
15 * (______/|_____)_|_|_| \__)_____)\____)_| |_|
16 * (C)2013-2018 Semtech
17 *
18 * \endcode
19 *
20 * \author Miguel Luis ( Semtech )
21 */
22 #include "LmHandler.h"
23 #include "LmhpRemoteMcastSetup.h"
24
25 #define DBG_TRACE 1
26
27 #if DBG_TRACE == 1
28 #include <stdio.h>
29 /*!
30 * Works in the same way as the printf function does.
31 */
32 #define DBG( ... ) \
33 do \
34 { \
35 printf( __VA_ARGS__ ); \
36 }while( 0 )
37 #else
38 #define DBG( ... )
39 #endif
40
41 /*!
42 * LoRaWAN Application Layer Remote multicast setup Specification
43 */
44 #define REMOTE_MCAST_SETUP_PORT 200
45
46 #define REMOTE_MCAST_SETUP_ID 2
47 #define REMOTE_MCAST_SETUP_VERSION 1
48
49 typedef enum LmhpRemoteMcastSetupSessionStates_e
50 {
51 REMOTE_MCAST_SETUP_SESSION_STATE_IDLE,
52 REMOTE_MCAST_SETUP_SESSION_STATE_START,
53 REMOTE_MCAST_SETUP_SESSION_STATE_STOP,
54 }LmhpRemoteMcastSetupSessionStates_t;
55
56 /*!
57 * Package current context
58 */
59 typedef struct LmhpRemoteMcastSetupState_s
60 {
61 bool Initialized;
62 bool IsTxPending;
63 LmhpRemoteMcastSetupSessionStates_t SessionState;
64 uint8_t DataBufferMaxSize;
65 uint8_t *DataBuffer;
66 }LmhpRemoteMcastSetupState_t;
67
68 typedef enum LmhpRemoteMcastSetupMoteCmd_e
69 {
70 REMOTE_MCAST_SETUP_PKG_VERSION_ANS = 0x00,
71 REMOTE_MCAST_SETUP_MC_GROUP_STATUS_ANS = 0x01,
72 REMOTE_MCAST_SETUP_MC_GROUP_SETUP_ANS = 0x02,
73 REMOTE_MCAST_SETUP_MC_GROUP_DELETE_ANS = 0x03,
74 REMOTE_MCAST_SETUP_MC_GROUP_CLASS_C_SESSION_ANS = 0x04,
75 REMOTE_MCAST_SETUP_MC_GROUP_CLASS_B_SESSION_ANS = 0x05,
76 }LmhpRemoteMcastSetupMoteCmd_t;
77
78 typedef enum LmhpRemoteMcastSetupSrvCmd_e
79 {
80 REMOTE_MCAST_SETUP_PKG_VERSION_REQ = 0x00,
81 REMOTE_MCAST_SETUP_MC_GROUP_STATUS_REQ = 0x01,
82 REMOTE_MCAST_SETUP_MC_GROUP_SETUP_REQ = 0x02,
83 REMOTE_MCAST_SETUP_MC_GROUP_DELETE_REQ = 0x03,
84 REMOTE_MCAST_SETUP_MC_GROUP_CLASS_C_SESSION_REQ = 0x04,
85 REMOTE_MCAST_SETUP_MC_GROUP_CLASS_B_SESSION_REQ = 0x05,
86 }LmhpRemoteMcastSetupSrvCmd_t;
87
88 /*!
89 * Initializes the package with provided parameters
90 *
91 * \param [IN] params Pointer to the package parameters
92 * \param [IN] dataBuffer Pointer to main application buffer
93 * \param [IN] dataBufferMaxSize Main application buffer maximum size
94 */
95 static void LmhpRemoteMcastSetupInit( void *params, uint8_t *dataBuffer, uint8_t dataBufferMaxSize );
96
97 /*!
98 * Returns the current package initialization status.
99 *
100 * \retval status Package initialization status
101 * [true: Initialized, false: Not initialized]
102 */
103 static bool LmhpRemoteMcastSetupIsInitialized( void );
104
105 /*!
106 * Returns if a package transmission is pending or not.
107 *
108 * \retval status Package transmission status
109 * [true: pending, false: Not pending]
110 */
111 static bool LmhpRemoteMcastSetupIsTxPending( void );
112
113 /*!
114 * Processes the internal package events.
115 */
116 static void LmhpRemoteMcastSetupProcess( void );
117
118 /*!
119 * Processes the MCPS Indication
120 *
121 * \param [IN] mcpsIndication MCPS indication primitive data
122 */
123 static void LmhpRemoteMcastSetupOnMcpsIndication( McpsIndication_t *mcpsIndication );
124
125 static void OnSessionStartTimer( void *context );
126
127 static void OnSessionStopTimer( void *context );
128
129 static LmhpRemoteMcastSetupState_t LmhpRemoteMcastSetupState =
130 {
131 .Initialized = false,
132 .IsTxPending = false,
133 .SessionState = REMOTE_MCAST_SETUP_SESSION_STATE_IDLE,
134 };
135
136 typedef struct McGroupData_s
137 {
138 union
139 {
140 uint8_t Value;
141 struct
142 {
143 uint8_t McGroupId: 2;
144 uint8_t RFU: 6;
145 }Fields;
146 }IdHeader;
147 uint32_t McAddr;
148 uint8_t McKeyEncrypted[16];
149 uint32_t McFCountMin;
150 uint32_t McFCountMax;
151 }McGroupData_t;
152
153 typedef enum eSessionState
154 {
155 SESSION_STOPED,
156 SESSION_STARTED
157 }SessionState_t;
158
159 typedef struct McSessionData_s
160 {
161 McGroupData_t McGroupData;
162 SessionState_t SessionState;
163 uint32_t SessionTime;
164 uint8_t SessionTimeout;
165 McRxParams_t RxParams;
166 }McSessionData_t;
167
168 McSessionData_t McSessionData[LORAMAC_MAX_MC_CTX];
169
170 /*!
171 * Session start timer
172 */
173 static TimerEvent_t SessionStartTimer;
174
175 /*!
176 * Session start timer
177 */
178 static TimerEvent_t SessionStopTimer;
179
180 static LmhPackage_t LmhpRemoteMcastSetupPackage =
181 {
182 .Port = REMOTE_MCAST_SETUP_PORT,
183 .Init = LmhpRemoteMcastSetupInit,
184 .IsInitialized = LmhpRemoteMcastSetupIsInitialized,
185 .IsTxPending = LmhpRemoteMcastSetupIsTxPending,
186 .Process = LmhpRemoteMcastSetupProcess,
187 .OnMcpsConfirmProcess = NULL, // Not used in this package
188 .OnMcpsIndicationProcess = LmhpRemoteMcastSetupOnMcpsIndication,
189 .OnMlmeConfirmProcess = NULL, // Not used in this package
190 .OnMlmeIndicationProcess = NULL, // Not used in this package
191 .OnMacMcpsRequest = NULL, // To be initialized by LmHandler
192 .OnMacMlmeRequest = NULL, // To be initialized by LmHandler
193 .OnJoinRequest = NULL, // To be initialized by LmHandler
194 .OnDeviceTimeRequest = NULL, // To be initialized by LmHandler
195 .OnSysTimeUpdate = NULL, // To be initialized by LmHandler
196 };
197
LmhpRemoteMcastSetupPackageFactory(void)198 LmhPackage_t *LmhpRemoteMcastSetupPackageFactory( void )
199 {
200 return &LmhpRemoteMcastSetupPackage;
201 }
202
LmhpRemoteMcastSetupInit(void * params,uint8_t * dataBuffer,uint8_t dataBufferMaxSize)203 static void LmhpRemoteMcastSetupInit( void * params, uint8_t *dataBuffer, uint8_t dataBufferMaxSize )
204 {
205 if( dataBuffer != NULL )
206 {
207 LmhpRemoteMcastSetupState.DataBuffer = dataBuffer;
208 LmhpRemoteMcastSetupState.DataBufferMaxSize = dataBufferMaxSize;
209 LmhpRemoteMcastSetupState.Initialized = true;
210 TimerInit( &SessionStartTimer, OnSessionStartTimer );
211 TimerInit( &SessionStopTimer, OnSessionStopTimer );
212 }
213 else
214 {
215 LmhpRemoteMcastSetupState.Initialized = false;
216 }
217 LmhpRemoteMcastSetupState.IsTxPending = false;
218 }
219
LmhpRemoteMcastSetupIsInitialized(void)220 static bool LmhpRemoteMcastSetupIsInitialized( void )
221 {
222 return LmhpRemoteMcastSetupState.Initialized;
223 }
224
LmhpRemoteMcastSetupIsTxPending(void)225 static bool LmhpRemoteMcastSetupIsTxPending( void )
226 {
227 return LmhpRemoteMcastSetupState.IsTxPending;
228 }
229
LmhpRemoteMcastSetupProcess(void)230 static void LmhpRemoteMcastSetupProcess( void )
231 {
232 LmhpRemoteMcastSetupSessionStates_t state;
233
234 CRITICAL_SECTION_BEGIN( );
235 state = LmhpRemoteMcastSetupState.SessionState;
236 LmhpRemoteMcastSetupState.SessionState = REMOTE_MCAST_SETUP_SESSION_STATE_IDLE;
237 CRITICAL_SECTION_END( );
238
239 switch( state )
240 {
241 case REMOTE_MCAST_SETUP_SESSION_STATE_START:
242 // Switch to Class C
243 LmHandlerRequestClass( CLASS_C );
244
245 TimerSetValue( &SessionStopTimer, ( 1 << McSessionData[0].SessionTimeout ) * 1000 );
246 TimerStart( &SessionStopTimer );
247 break;
248 case REMOTE_MCAST_SETUP_SESSION_STATE_STOP:
249 // Switch back to Class A
250 LmHandlerRequestClass( CLASS_A );
251 break;
252 case REMOTE_MCAST_SETUP_SESSION_STATE_IDLE:
253 // Intentional fall through
254 default:
255 // Nothing to do.
256 break;
257 }
258 }
259
LmhpRemoteMcastSetupOnMcpsIndication(McpsIndication_t * mcpsIndication)260 static void LmhpRemoteMcastSetupOnMcpsIndication( McpsIndication_t *mcpsIndication )
261 {
262 uint8_t cmdIndex = 0;
263 uint8_t dataBufferIndex = 0;
264
265 if( mcpsIndication->Port != REMOTE_MCAST_SETUP_PORT )
266 {
267 return;
268 }
269
270 while( cmdIndex < mcpsIndication->BufferSize )
271 {
272 switch( mcpsIndication->Buffer[cmdIndex++] )
273 {
274 case REMOTE_MCAST_SETUP_PKG_VERSION_REQ:
275 {
276 LmhpRemoteMcastSetupState.DataBuffer[dataBufferIndex++] = REMOTE_MCAST_SETUP_PKG_VERSION_ANS;
277 LmhpRemoteMcastSetupState.DataBuffer[dataBufferIndex++] = REMOTE_MCAST_SETUP_ID;
278 LmhpRemoteMcastSetupState.DataBuffer[dataBufferIndex++] = REMOTE_MCAST_SETUP_VERSION;
279 break;
280 }
281 case REMOTE_MCAST_SETUP_MC_GROUP_STATUS_REQ:
282 {
283 // TODO implement command prosessing and handling
284 break;
285 }
286 case REMOTE_MCAST_SETUP_MC_GROUP_SETUP_REQ:
287 {
288 uint8_t id = mcpsIndication->Buffer[cmdIndex++];
289 McSessionData[id].McGroupData.IdHeader.Value = id;
290
291 McSessionData[id].McGroupData.McAddr = ( mcpsIndication->Buffer[cmdIndex++] << 0 ) & 0x000000FF;
292 McSessionData[id].McGroupData.McAddr += ( mcpsIndication->Buffer[cmdIndex++] << 8 ) & 0x0000FF00;
293 McSessionData[id].McGroupData.McAddr += ( mcpsIndication->Buffer[cmdIndex++] << 16 ) & 0x00FF0000;
294 McSessionData[id].McGroupData.McAddr += ( mcpsIndication->Buffer[cmdIndex++] << 24 ) & 0xFF000000;
295
296 for( int8_t i = 0; i < 16; i++ )
297 {
298 McSessionData[id].McGroupData.McKeyEncrypted[i] = mcpsIndication->Buffer[cmdIndex++];
299 }
300
301 McSessionData[id].McGroupData.McFCountMin = ( mcpsIndication->Buffer[cmdIndex++] << 0 ) & 0x000000FF;
302 McSessionData[id].McGroupData.McFCountMin += ( mcpsIndication->Buffer[cmdIndex++] << 8 ) & 0x0000FF00;
303 McSessionData[id].McGroupData.McFCountMin += ( mcpsIndication->Buffer[cmdIndex++] << 16 ) & 0x00FF0000;
304 McSessionData[id].McGroupData.McFCountMin += ( mcpsIndication->Buffer[cmdIndex++] << 24 ) & 0xFF000000;
305
306 McSessionData[id].McGroupData.McFCountMax = ( mcpsIndication->Buffer[cmdIndex++] << 0 ) & 0x000000FF;
307 McSessionData[id].McGroupData.McFCountMax += ( mcpsIndication->Buffer[cmdIndex++] << 8 ) & 0x0000FF00;
308 McSessionData[id].McGroupData.McFCountMax += ( mcpsIndication->Buffer[cmdIndex++] << 16 ) & 0x00FF0000;
309 McSessionData[id].McGroupData.McFCountMax += ( mcpsIndication->Buffer[cmdIndex++] << 24 ) & 0xFF000000;
310
311 McChannelParams_t channel =
312 {
313 .IsRemotelySetup = true,
314 .IsEnabled = true,
315 .GroupID = ( AddressIdentifier_t )McSessionData[id].McGroupData.IdHeader.Fields.McGroupId,
316 .Address = McSessionData[id].McGroupData.McAddr,
317 .McKeys.McKeyE = McSessionData[id].McGroupData.McKeyEncrypted,
318 .FCountMin = McSessionData[id].McGroupData.McFCountMin,
319 .FCountMax = McSessionData[id].McGroupData.McFCountMax,
320 .RxParams.Params.ClassC = // Field not used for multicast channel setup. Must be initialized to something
321 {
322 .Frequency = 0,
323 .Datarate = 0
324 }
325 };
326 uint8_t idError = 0x01; // One bit value
327 if( LoRaMacMcChannelSetup( &channel ) == LORAMAC_STATUS_OK )
328 {
329 idError = 0x00;
330 }
331 LmhpRemoteMcastSetupState.DataBuffer[dataBufferIndex++] = REMOTE_MCAST_SETUP_MC_GROUP_SETUP_ANS;
332 LmhpRemoteMcastSetupState.DataBuffer[dataBufferIndex++] = ( idError << 2 ) | McSessionData[id].McGroupData.IdHeader.Fields.McGroupId;
333 break;
334 }
335 case REMOTE_MCAST_SETUP_MC_GROUP_DELETE_REQ:
336 {
337 uint8_t status = 0x00;
338 uint8_t id = mcpsIndication->Buffer[cmdIndex++] & 0x03;
339
340 status = id;
341
342 LmhpRemoteMcastSetupState.DataBuffer[dataBufferIndex++] = REMOTE_MCAST_SETUP_MC_GROUP_DELETE_ANS;
343
344 if( LoRaMacMcChannelDelete( ( AddressIdentifier_t )id ) != LORAMAC_STATUS_OK )
345 {
346 status |= 0x04; // McGroupUndefined bit set
347 }
348 LmhpRemoteMcastSetupState.DataBuffer[dataBufferIndex++] = status;
349 break;
350 }
351 case REMOTE_MCAST_SETUP_MC_GROUP_CLASS_C_SESSION_REQ:
352 {
353 uint8_t status = 0x00;
354 uint8_t id = mcpsIndication->Buffer[cmdIndex++] & 0x03;
355
356 McSessionData[id].RxParams.Class = CLASS_C;
357
358 McSessionData[id].SessionTime = ( mcpsIndication->Buffer[cmdIndex++] << 0 ) & 0x000000FF;
359 McSessionData[id].SessionTime += ( mcpsIndication->Buffer[cmdIndex++] << 8 ) & 0x0000FF00;
360 McSessionData[id].SessionTime += ( mcpsIndication->Buffer[cmdIndex++] << 16 ) & 0x00FF0000;
361 McSessionData[id].SessionTime += ( mcpsIndication->Buffer[cmdIndex++] << 24 ) & 0xFF000000;
362
363 // Add Unix to Gps epoch offset. The system time is based on Unix time.
364 McSessionData[id].SessionTime += UNIX_GPS_EPOCH_OFFSET;
365
366 McSessionData[id].SessionTimeout = mcpsIndication->Buffer[cmdIndex++] & 0x0F;
367
368 McSessionData[id].RxParams.Params.ClassC.Frequency = ( mcpsIndication->Buffer[cmdIndex++] << 0 ) & 0x000000FF;
369 McSessionData[id].RxParams.Params.ClassC.Frequency |= ( mcpsIndication->Buffer[cmdIndex++] << 8 ) & 0x0000FF00;
370 McSessionData[id].RxParams.Params.ClassC.Frequency |= ( mcpsIndication->Buffer[cmdIndex++] << 16 ) & 0x00FF0000;
371 McSessionData[id].RxParams.Params.ClassC.Frequency *= 100;
372 McSessionData[id].RxParams.Params.ClassC.Datarate = mcpsIndication->Buffer[cmdIndex++];
373
374 LmhpRemoteMcastSetupState.DataBuffer[dataBufferIndex++] = REMOTE_MCAST_SETUP_MC_GROUP_CLASS_C_SESSION_ANS;
375 if( LoRaMacMcChannelSetupRxParams( ( AddressIdentifier_t )id, &McSessionData[id].RxParams, &status ) == LORAMAC_STATUS_OK )
376 {
377 SysTime_t curTime = { .Seconds = 0, .SubSeconds = 0 };
378 curTime = SysTimeGet( );
379
380 int32_t timeToSessionStart = McSessionData[id].SessionTime - curTime.Seconds;
381 if( timeToSessionStart > 0 )
382 {
383 // Start session start timer
384 TimerSetValue( &SessionStartTimer, timeToSessionStart * 1000 );
385 TimerStart( &SessionStartTimer );
386
387 DBG( "Time2SessionStart: %ld ms\n", timeToSessionStart * 1000 );
388
389 LmhpRemoteMcastSetupState.DataBuffer[dataBufferIndex++] = status;
390 LmhpRemoteMcastSetupState.DataBuffer[dataBufferIndex++] = ( timeToSessionStart >> 0 ) & 0xFF;
391 LmhpRemoteMcastSetupState.DataBuffer[dataBufferIndex++] = ( timeToSessionStart >> 8 ) & 0xFF;
392 LmhpRemoteMcastSetupState.DataBuffer[dataBufferIndex++] = ( timeToSessionStart >> 16 ) & 0xFF;
393 break;
394 }
395 else
396 {
397 // Session start time before current device time
398 status |= 0x10;
399 }
400 }
401 LmhpRemoteMcastSetupState.DataBuffer[dataBufferIndex++] = status;
402 break;
403 }
404 case REMOTE_MCAST_SETUP_MC_GROUP_CLASS_B_SESSION_REQ:
405 {
406 uint8_t status = 0x00;
407 uint8_t id = mcpsIndication->Buffer[cmdIndex++] & 0x03;
408
409 McSessionData[id].RxParams.Class = CLASS_B;
410
411 McSessionData[id].SessionTime = ( mcpsIndication->Buffer[cmdIndex++] << 0 ) & 0x000000FF;
412 McSessionData[id].SessionTime += ( mcpsIndication->Buffer[cmdIndex++] << 8 ) & 0x0000FF00;
413 McSessionData[id].SessionTime += ( mcpsIndication->Buffer[cmdIndex++] << 16 ) & 0x00FF0000;
414 McSessionData[id].SessionTime += ( mcpsIndication->Buffer[cmdIndex++] << 24 ) & 0xFF000000;
415
416 // Add Unix to Gps epoch offset. The system time is based on Unix time.
417 McSessionData[id].SessionTime += UNIX_GPS_EPOCH_OFFSET;
418
419 McSessionData[id].RxParams.Params.ClassB.Periodicity = ( mcpsIndication->Buffer[cmdIndex] >> 4 ) & 0x07;
420 McSessionData[id].SessionTimeout = mcpsIndication->Buffer[cmdIndex++] & 0x0F;
421
422 McSessionData[id].RxParams.Params.ClassB.Frequency = ( mcpsIndication->Buffer[cmdIndex++] << 0 ) & 0x000000FF;
423 McSessionData[id].RxParams.Params.ClassB.Frequency |= ( mcpsIndication->Buffer[cmdIndex++] << 8 ) & 0x0000FF00;
424 McSessionData[id].RxParams.Params.ClassB.Frequency |= ( mcpsIndication->Buffer[cmdIndex++] << 16 ) & 0x00FF0000;
425 McSessionData[id].RxParams.Params.ClassB.Frequency *= 100;
426 McSessionData[id].RxParams.Params.ClassB.Datarate = mcpsIndication->Buffer[cmdIndex++];
427
428 LmhpRemoteMcastSetupState.DataBuffer[dataBufferIndex++] = REMOTE_MCAST_SETUP_MC_GROUP_CLASS_B_SESSION_ANS;
429 if( LoRaMacMcChannelSetupRxParams( ( AddressIdentifier_t )id, &McSessionData[id].RxParams, &status ) == LORAMAC_STATUS_OK )
430 {
431 SysTime_t curTime = { .Seconds = 0, .SubSeconds = 0 };
432 curTime = SysTimeGet( );
433
434 int32_t timeToSessionStart = McSessionData[id].SessionTime - curTime.Seconds;
435 if( timeToSessionStart > 0 )
436 {
437 // Start session start timer
438 TimerSetValue( &SessionStartTimer, timeToSessionStart * 1000 );
439 TimerStart( &SessionStartTimer );
440
441 DBG( "Time2SessionStart: %ld ms\n", timeToSessionStart * 1000 );
442
443 LmhpRemoteMcastSetupState.DataBuffer[dataBufferIndex++] = status;
444 LmhpRemoteMcastSetupState.DataBuffer[dataBufferIndex++] = ( timeToSessionStart >> 0 ) & 0xFF;
445 LmhpRemoteMcastSetupState.DataBuffer[dataBufferIndex++] = ( timeToSessionStart >> 8 ) & 0xFF;
446 LmhpRemoteMcastSetupState.DataBuffer[dataBufferIndex++] = ( timeToSessionStart >> 16 ) & 0xFF;
447 break;
448 }
449 else
450 {
451 // Session start time before current device time
452 status |= 0x10;
453 }
454 }
455 LmhpRemoteMcastSetupState.DataBuffer[dataBufferIndex++] = status;
456 break;
457 }
458 default:
459 {
460 break;
461 }
462 }
463 }
464
465 if( dataBufferIndex != 0 )
466 {
467 // Answer commands
468 LmHandlerAppData_t appData =
469 {
470 .Buffer = LmhpRemoteMcastSetupState.DataBuffer,
471 .BufferSize = dataBufferIndex,
472 .Port = REMOTE_MCAST_SETUP_PORT
473 };
474 LmHandlerSend( &appData, LORAMAC_HANDLER_UNCONFIRMED_MSG );
475
476 DBG( "ID : %d\n", McSessionData[0].McGroupData.IdHeader.Fields.McGroupId );
477 DBG( "McAddr : %08lX\n", McSessionData[0].McGroupData.McAddr );
478 DBG( "McKey : %02X", McSessionData[0].McGroupData.McKeyEncrypted[0] );
479 for( int i = 1; i < 16; i++ )
480 {
481 DBG( "-%02X", McSessionData[0].McGroupData.McKeyEncrypted[i] );
482 }
483 DBG( "\n" );
484 DBG( "McFCountMin : %lu\n", McSessionData[0].McGroupData.McFCountMin );
485 DBG( "McFCountMax : %lu\n", McSessionData[0].McGroupData.McFCountMax );
486 DBG( "SessionTime : %lu\n", McSessionData[0].SessionTime );
487 DBG( "SessionTimeT: %d\n", McSessionData[0].SessionTimeout );
488 if( McSessionData[0].RxParams.Class == CLASS_B )
489 {
490 DBG( "Rx Freq : %lu\n", McSessionData[0].RxParams.Params.ClassB.Frequency );
491 DBG( "Rx DR : DR_%d\n", McSessionData[0].RxParams.Params.ClassB.Datarate );
492 DBG( "Periodicity : %u\n", McSessionData[0].RxParams.Params.ClassB.Periodicity );
493 }
494 else
495 {
496 DBG( "Rx Freq : %lu\n", McSessionData[0].RxParams.Params.ClassC.Frequency );
497 DBG( "Rx DR : DR_%d\n", McSessionData[0].RxParams.Params.ClassC.Datarate );
498 }
499 }
500 }
501
OnSessionStartTimer(void * context)502 static void OnSessionStartTimer( void *context )
503 {
504 TimerStop( &SessionStartTimer );
505
506 LmhpRemoteMcastSetupState.SessionState = REMOTE_MCAST_SETUP_SESSION_STATE_START;
507 }
508
OnSessionStopTimer(void * context)509 static void OnSessionStopTimer( void *context )
510 {
511 TimerStop( &SessionStopTimer );
512
513 LmhpRemoteMcastSetupState.SessionState = REMOTE_MCAST_SETUP_SESSION_STATE_STOP;
514 }
515