From acdb50347d9e01a78318c5f4dbad8d0c4411bfb8 Mon Sep 17 00:00:00 2001 From: Terry Moore Date: Sun, 30 May 2021 20:41:44 -0400 Subject: [PATCH] Fix #739: fix #740: improve JoinAccept CFList processing --- src/lmic/lmic.c | 18 +++--------------- src/lmic/lmic_bandplan.h | 4 ++++ src/lmic/lmic_eu_like.c | 20 ++++++++++++++++++++ src/lmic/lmic_eu_like.h | 5 +++++ src/lmic/lmic_us_like.c | 26 ++++++++++++++++++++++++++ src/lmic/lmic_us_like.h | 10 ++++++++-- src/lmic/lorabase.h | 7 +++++++ 7 files changed, 73 insertions(+), 17 deletions(-) diff --git a/src/lmic/lmic.c b/src/lmic/lmic.c index 6a6f288c..9d4c90ea 100644 --- a/src/lmic/lmic.c +++ b/src/lmic/lmic.c @@ -1621,21 +1621,9 @@ static bit_t processJoinAccept (void) { // initDefaultChannels(0) for EU-like, nothing otherwise LMICbandplan_joinAcceptChannelClear(); - if (!LMICbandplan_hasJoinCFlist() && dlen > LEN_JA) { - // if no JoinCFList, we're supposed to continue - // the join per 2.2.5 of LoRaWAN regional 2.2.4 - // https://github.com/mcci-catena/arduino-lmic/issues/19 - } else if ( LMICbandplan_hasJoinCFlist() && dlen > LEN_JA ) { - dlen = OFF_CFLIST; - for( u1_t chidx=3; chidx<8; chidx++, dlen+=3 ) { - u4_t freq = LMICbandplan_convFreq(&LMIC.frame[dlen]); - if( freq ) { - LMIC_setupChannel(chidx, freq, 0, -1); -#if LMIC_DEBUG_LEVEL > 1 - LMIC_DEBUG_PRINTF("%"LMIC_PRId_ostime_t": Setup channel, idx=%d, freq=%"PRIu32"\n", os_getTime(), chidx, freq); -#endif - } - } + // process the CFList if present + if (dlen == LEN_JAEXT) { + LMICbandplan_processJoinAcceptCFList(); } // already incremented when JOIN REQ got sent off diff --git a/src/lmic/lmic_bandplan.h b/src/lmic/lmic_bandplan.h index e43a7ba0..3921819f 100644 --- a/src/lmic/lmic_bandplan.h +++ b/src/lmic/lmic_bandplan.h @@ -170,6 +170,10 @@ # error "LMICbandplan_validDR() not defined by bandplan" #endif +#if !defined(LMICbandplan_processJoinAcceptCFList) +# error "LMICbandplan_processJoinAcceptCFList() not defined by bandplan" +#endif + // // Things common to lmic.c code // diff --git a/src/lmic/lmic_eu_like.c b/src/lmic/lmic_eu_like.c index 44533790..1555bbed 100644 --- a/src/lmic/lmic_eu_like.c +++ b/src/lmic/lmic_eu_like.c @@ -227,6 +227,26 @@ ostime_t LMICeulike_nextJoinState(uint8_t nDefaultChannels) { } #endif // !DISABLE_JOIN +#if !defined(DISABLE_JOIN) +void LMICeulike_processJoinAcceptCFList(void) { + if ( LMICbandplan_hasJoinCFlist() && + LMIC.frame[OFF_CFLIST + 15] == LORAWAN_JoinAccept_CFListType_FREQUENCIES) { + u1_t dlen; + u1_t nDefault = LMIC_queryNumDefaultChannels(); + + dlen = OFF_CFLIST; + for( u1_t chidx = nDefault; chidx < nDefault + 5; chidx++, dlen+=3 ) { + u4_t freq = LMICbandplan_convFreq(&LMIC.frame[dlen]); + if( freq ) { + LMIC_setupChannel(chidx, freq, 0, -1); +#if LMIC_DEBUG_LEVEL > 1 + LMIC_DEBUG_PRINTF("%"LMIC_PRId_ostime_t": Setup channel, idx=%d, freq=%"PRIu32"\n", os_getTime(), chidx, freq); +#endif + } + } +} +#endif // !DISABLE_JOIN + void LMICeulike_saveAdrState(lmic_saved_adr_state_t *pStateBuffer) { os_copyMem( pStateBuffer->channelFreq, diff --git a/src/lmic/lmic_eu_like.h b/src/lmic/lmic_eu_like.h index c9bbeac1..729af643 100644 --- a/src/lmic/lmic_eu_like.h +++ b/src/lmic/lmic_eu_like.h @@ -66,6 +66,11 @@ enum { BAND_MILLI = 0, BAND_CENTI = 1, BAND_DECI = 2, BAND_AUX = 3 }; // there's a CFList on joins for EU-like plans #define LMICbandplan_hasJoinCFlist() (1) +/// \brief process CFLists from JoinAccept for EU-like regions +void LMICeulike_processJoinAcceptCFList(void); +/// \brief by default, EU-like plans use LMICeulike_processJoinAcceptCFList +#define LMICbandplan_processJoinAcceptCFList LMICeulike_processJoinAcceptCFList + #define LMICbandplan_advanceBeaconChannel() \ do { /* nothing */ } while (0) diff --git a/src/lmic/lmic_us_like.c b/src/lmic/lmic_us_like.c index d2e89d36..31e4cc18 100644 --- a/src/lmic/lmic_us_like.c +++ b/src/lmic/lmic_us_like.c @@ -315,6 +315,32 @@ ostime_t LMICuslike_nextJoinState(void) { } #endif +#if !defined(DISABLE_JOIN) +void LMICuslike_processJoinAcceptCFList(void) { + if ( LMICbandplan_hasJoinCFlist() && + LMIC.frame[OFF_CFLIST + 15] == LORAWAN_JoinAccept_CFListType_MASK ) { + u1_t dlen; + + dlen = OFF_CFLIST; + for( u1_t chidx = 0; chidx < 8 * sizeof(LMIC.channelMap); chidx += 16, dlen += 2 ) { + u2_t mask = os_rlsbf2(&LMIC.frame[dlen]); +#if LMIC_DEBUG_LEVEL > 1 + LMIC_DEBUG_PRINTF("%"LMIC_PRId_ostime_t": Setup channel mask, group=%u, mask=%04x\n", os_getTime(), chidx, mask); +#endif + for ( u1_t chnum = chidx; chnum < chidx + 16; ++chnum, mask >>= 1) { + if (chnum >= 72) { + break; + } else if (mask & 1) { + LMIC_enableChannel(chnum); + } else { + LMIC_disableChannel(chnum); + } + } + } + } +} +#endif // !DISABLE_JOIN + void LMICuslike_saveAdrState(lmic_saved_adr_state_t *pStateBuffer) { os_copyMem( pStateBuffer->channelMap, diff --git a/src/lmic/lmic_us_like.h b/src/lmic/lmic_us_like.h index 62812369..f3e8bfca 100644 --- a/src/lmic/lmic_us_like.h +++ b/src/lmic/lmic_us_like.h @@ -63,8 +63,14 @@ LMICuslike_isValidBeacon1(const uint8_t *d) { // provide a default LMICbandplan_joinAcceptChannelClear() #define LMICbandplan_joinAcceptChannelClear() do { } while (0) -// no CFList on joins for US-like plans -#define LMICbandplan_hasJoinCFlist() (0) +/// \brief there's a CFList on joins for US-like plans +#define LMICbandplan_hasJoinCFlist() (1) + +/// \brief process CFLists from JoinAccept for EU-like regions +void LMICuslike_processJoinAcceptCFList(void); +/// \brief by default, EU-like plans use LMICuslike_processJoinAcceptCFList +#define LMICbandplan_processJoinAcceptCFList LMICuslike_processJoinAcceptCFList + #define LMICbandplan_advanceBeaconChannel() \ do { LMIC.bcnChnl = (LMIC.bcnChnl+1) & 7; } while (0) diff --git a/src/lmic/lorabase.h b/src/lmic/lorabase.h index f668f42a..632a8b42 100644 --- a/src/lmic/lorabase.h +++ b/src/lmic/lorabase.h @@ -445,6 +445,13 @@ enum { LEN_JA = 17, LEN_JAEXT = 17+16 }; + +enum { + // JoinAccept CFList types + LORAWAN_JoinAccept_CFListType_FREQUENCIES = 0, ///< the CFList contains 5 frequencies + LORAWAN_JoinAccept_CFListType_MASK = 1, ///< the CFList contains channel-mask data +}; + enum { // Data frame format OFF_DAT_HDR = 0,