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