xref: /btstack/chipset/cinnamon/hopping.c (revision 2c4f9bbb6d93b3f1a90ed62ac67e4cd019f0736a)
1*2c4f9bbbSMatthias Ringwald /*******************************************************************************
2*2c4f9bbbSMatthias Ringwald  *
3*2c4f9bbbSMatthias Ringwald  *      Copyright (c) 2018, Raccon BLE Sniffer
4*2c4f9bbbSMatthias Ringwald  *      All rights reserved.
5*2c4f9bbbSMatthias Ringwald  *
6*2c4f9bbbSMatthias Ringwald  *      Redistribution and use in source and binary forms, with or without
7*2c4f9bbbSMatthias Ringwald  *      modification, are permitted provided that the following conditions are
8*2c4f9bbbSMatthias Ringwald  *      met:
9*2c4f9bbbSMatthias Ringwald  *      
10*2c4f9bbbSMatthias Ringwald  *      * Redistributions of source code must retain the above copyright
11*2c4f9bbbSMatthias Ringwald  *        notice, this list of conditions and the following disclaimer.
12*2c4f9bbbSMatthias Ringwald  *      * Redistributions in binary form must reproduce the above
13*2c4f9bbbSMatthias Ringwald  *        copyright notice, this list of conditions and the following disclaimer
14*2c4f9bbbSMatthias Ringwald  *        in the documentation and/or other materials provided with the
15*2c4f9bbbSMatthias Ringwald  *        distribution.
16*2c4f9bbbSMatthias Ringwald  *      * Neither the name of "btlejack2" nor the names of its
17*2c4f9bbbSMatthias Ringwald  *        contributors may be used to endorse or promote products derived from
18*2c4f9bbbSMatthias Ringwald  *        this software without specific prior written permission.
19*2c4f9bbbSMatthias Ringwald  *      
20*2c4f9bbbSMatthias Ringwald  *      THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21*2c4f9bbbSMatthias Ringwald  *      "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22*2c4f9bbbSMatthias Ringwald  *      LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23*2c4f9bbbSMatthias Ringwald  *      A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24*2c4f9bbbSMatthias Ringwald  *      OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25*2c4f9bbbSMatthias Ringwald  *      SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26*2c4f9bbbSMatthias Ringwald  *      LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27*2c4f9bbbSMatthias Ringwald  *      DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28*2c4f9bbbSMatthias Ringwald  *      THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29*2c4f9bbbSMatthias Ringwald  *      (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30*2c4f9bbbSMatthias Ringwald  *      OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31*2c4f9bbbSMatthias Ringwald  *
32*2c4f9bbbSMatthias Ringwald  *******************************************************************************/
33*2c4f9bbbSMatthias Ringwald 
34*2c4f9bbbSMatthias Ringwald #include <string.h>
35*2c4f9bbbSMatthias Ringwald #include <strings.h>
36*2c4f9bbbSMatthias Ringwald #include <assert.h>
37*2c4f9bbbSMatthias Ringwald 
38*2c4f9bbbSMatthias Ringwald #include "debug.h"
39*2c4f9bbbSMatthias Ringwald #include "hopping.h"
40*2c4f9bbbSMatthias Ringwald 
41*2c4f9bbbSMatthias Ringwald #define GET_BIT( b, n )  ((b[(n&UINT32_C(0xFFFFFFF8))>>3]>>(n&0x7))&1)
42*2c4f9bbbSMatthias Ringwald 
hopping_init(hopping_t * c)43*2c4f9bbbSMatthias Ringwald void hopping_init( hopping_t *c ) {
44*2c4f9bbbSMatthias Ringwald     assert( c != NULL );
45*2c4f9bbbSMatthias Ringwald 
46*2c4f9bbbSMatthias Ringwald     memset( c, 0, sizeof(hopping_t) );
47*2c4f9bbbSMatthias Ringwald }
48*2c4f9bbbSMatthias Ringwald 
hopping_set_channel_map(hopping_t * c,const uint8_t * chm)49*2c4f9bbbSMatthias Ringwald void hopping_set_channel_map( hopping_t *c, const uint8_t *chm ) {
50*2c4f9bbbSMatthias Ringwald     assert( c != NULL );
51*2c4f9bbbSMatthias Ringwald     assert( chm != NULL );
52*2c4f9bbbSMatthias Ringwald 
53*2c4f9bbbSMatthias Ringwald     memcpy( c->chMap, chm, 5 );
54*2c4f9bbbSMatthias Ringwald 
55*2c4f9bbbSMatthias Ringwald     c->chCnt = 0;
56*2c4f9bbbSMatthias Ringwald     for(int i=0; i<37; ++i) {
57*2c4f9bbbSMatthias Ringwald         LOG_DBG("%d(%d)\n", i, (i&UINT32_C(0xFFFFFFF8))>>3 );
58*2c4f9bbbSMatthias Ringwald         LOG_DBG("%d(%d)\n", i, GET_BIT( c->chMap, i ) );
59*2c4f9bbbSMatthias Ringwald         if( 1 == GET_BIT( c->chMap, i ) ) {
60*2c4f9bbbSMatthias Ringwald             c->chRemap[c->chCnt++] = i;
61*2c4f9bbbSMatthias Ringwald         }
62*2c4f9bbbSMatthias Ringwald     }
63*2c4f9bbbSMatthias Ringwald 
64*2c4f9bbbSMatthias Ringwald //    for(int i=0; i<c->chCnt; ++i)
65*2c4f9bbbSMatthias Ringwald //        printf("%d\n", c->chRemap[i] );
66*2c4f9bbbSMatthias Ringwald 
67*2c4f9bbbSMatthias Ringwald //    printf("chCnt: %d\n", c->chCnt );
68*2c4f9bbbSMatthias Ringwald }
69*2c4f9bbbSMatthias Ringwald 
hopping_csa1_set_hop_increment(hopping_t * c,uint8_t hopIncrement)70*2c4f9bbbSMatthias Ringwald void hopping_csa1_set_hop_increment( hopping_t *c, uint8_t hopIncrement ){
71*2c4f9bbbSMatthias Ringwald     assert( c != NULL );
72*2c4f9bbbSMatthias Ringwald 
73*2c4f9bbbSMatthias Ringwald     c->hopIncrement = hopIncrement;
74*2c4f9bbbSMatthias Ringwald }
75*2c4f9bbbSMatthias Ringwald 
hopping_csa1_get_next_channel(hopping_t * c)76*2c4f9bbbSMatthias Ringwald uint8_t hopping_csa1_get_next_channel( hopping_t *c ) {
77*2c4f9bbbSMatthias Ringwald     assert( c != NULL );
78*2c4f9bbbSMatthias Ringwald 
79*2c4f9bbbSMatthias Ringwald     c->currentCh = (c->currentCh + c->hopIncrement) % 37;
80*2c4f9bbbSMatthias Ringwald     if( 1 == GET_BIT( c->chMap, c->currentCh ) ) {
81*2c4f9bbbSMatthias Ringwald         return c->currentCh;
82*2c4f9bbbSMatthias Ringwald     } else {
83*2c4f9bbbSMatthias Ringwald         return c->chRemap[ c->currentCh % c->chCnt ];
84*2c4f9bbbSMatthias Ringwald     }
85*2c4f9bbbSMatthias Ringwald }
86*2c4f9bbbSMatthias Ringwald 
87*2c4f9bbbSMatthias Ringwald // channelIdentifier = (Access Address31-16) XOR (Access Address15-0)
hopping_csa2_set_access_address(hopping_t * c,uint32_t accessAddress)88*2c4f9bbbSMatthias Ringwald void hopping_csa2_set_access_address( hopping_t *c, uint32_t accessAddress ){
89*2c4f9bbbSMatthias Ringwald     assert( c != NULL );
90*2c4f9bbbSMatthias Ringwald 
91*2c4f9bbbSMatthias Ringwald     c->channelIdentifier = (accessAddress >> 16) ^ (accessAddress & 0xffff);
92*2c4f9bbbSMatthias Ringwald }
93*2c4f9bbbSMatthias Ringwald 
94*2c4f9bbbSMatthias Ringwald // @TODO rbit intrinsic could be used
hopping_csa2_permutation(uint16_t v)95*2c4f9bbbSMatthias Ringwald static uint16_t hopping_csa2_permutation(uint16_t v){
96*2c4f9bbbSMatthias Ringwald     v = ((v >> 1) & 0x5555) | ((v & 0x5555) << 1);
97*2c4f9bbbSMatthias Ringwald     v = ((v >> 2) & 0x3333) | ((v & 0x3333) << 2);
98*2c4f9bbbSMatthias Ringwald     v = ((v >> 4) & 0x0F0F) | ((v & 0x0F0F) << 4);
99*2c4f9bbbSMatthias Ringwald     return v;
100*2c4f9bbbSMatthias Ringwald }
101*2c4f9bbbSMatthias Ringwald 
hopping_csa2_mam(uint16_t a,uint16_t b)102*2c4f9bbbSMatthias Ringwald static uint16_t hopping_csa2_mam(uint16_t a, uint16_t b){
103*2c4f9bbbSMatthias Ringwald     return (17 * a) + b;
104*2c4f9bbbSMatthias Ringwald }
105*2c4f9bbbSMatthias Ringwald 
hopping_csa2_prn_e(hopping_t * c,uint16_t counter)106*2c4f9bbbSMatthias Ringwald static uint16_t hopping_csa2_prn_e(hopping_t *c, uint16_t counter){
107*2c4f9bbbSMatthias Ringwald     assert( c != NULL );
108*2c4f9bbbSMatthias Ringwald 
109*2c4f9bbbSMatthias Ringwald     // see Bluetooth Spec v5, 4.5.8.3.3 Unmapped Event Channel Selection
110*2c4f9bbbSMatthias Ringwald     uint16_t v = counter ^ c->channelIdentifier;
111*2c4f9bbbSMatthias Ringwald     v = hopping_csa2_permutation (v);
112*2c4f9bbbSMatthias Ringwald     v = hopping_csa2_mam(v, c->channelIdentifier);
113*2c4f9bbbSMatthias Ringwald     v = hopping_csa2_permutation (v);
114*2c4f9bbbSMatthias Ringwald     v = hopping_csa2_mam(v, c->channelIdentifier);
115*2c4f9bbbSMatthias Ringwald     v = hopping_csa2_permutation (v);
116*2c4f9bbbSMatthias Ringwald     v = hopping_csa2_mam(v, c->channelIdentifier);
117*2c4f9bbbSMatthias Ringwald     v = v ^ c->channelIdentifier;
118*2c4f9bbbSMatthias Ringwald     return v;
119*2c4f9bbbSMatthias Ringwald }
120*2c4f9bbbSMatthias Ringwald 
hopping_csa2_get_channel_for_counter(hopping_t * c,uint16_t counter)121*2c4f9bbbSMatthias Ringwald uint8_t hopping_csa2_get_channel_for_counter( hopping_t *c, uint16_t counter ){
122*2c4f9bbbSMatthias Ringwald     assert( c != NULL );
123*2c4f9bbbSMatthias Ringwald 
124*2c4f9bbbSMatthias Ringwald     uint16_t prn_e = hopping_csa2_prn_e( c, counter);
125*2c4f9bbbSMatthias Ringwald     uint16_t unmapped_channel = prn_e % 37;
126*2c4f9bbbSMatthias Ringwald     if ( 1 == GET_BIT( c->chMap, unmapped_channel)){
127*2c4f9bbbSMatthias Ringwald         return unmapped_channel;
128*2c4f9bbbSMatthias Ringwald     } else {
129*2c4f9bbbSMatthias Ringwald         uint16_t remappingIndex = (((uint32_t) c->chCnt) * prn_e) >> 16;
130*2c4f9bbbSMatthias Ringwald         return c->chRemap[ remappingIndex ];
131*2c4f9bbbSMatthias Ringwald     }
132*2c4f9bbbSMatthias Ringwald }
133*2c4f9bbbSMatthias Ringwald 
134*2c4f9bbbSMatthias Ringwald 
135*2c4f9bbbSMatthias Ringwald 
136*2c4f9bbbSMatthias Ringwald 
137*2c4f9bbbSMatthias Ringwald 
138