1 /*
2  * Copyright (c) 2017 Oticon A/S
3  * Copyright (c) 2023 Nordic Semiconductor ASA
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 #include <stdint.h>
9 #include <stddef.h>
10 
11 /**
12  * Bitwise reverse 1 byte,
13  * Based on code in the public domain as claimed by the author in this page:
14  * http://graphics.stanford.edu/~seander/bithacks.html#ReverseByteWith64Bits
15  */
rev_byte(uint8_t input)16 static uint8_t rev_byte(uint8_t input){
17   return ((input * 0x80200802ULL) & 0x0884422110ULL)
18           * 0x0101010101ULL >> 32;
19 }
20 
21 /**
22  * Reverse the bits order in a 24 bit word
23  */
rev_24(uint32_t input)24 static uint32_t rev_24(uint32_t input){
25   uint32_t ret;
26   ret = rev_byte((input >> 0) & 0xff) << 16
27       | rev_byte((input >> 8) & 0xff) << 8
28       | rev_byte((input >> 16) & 0xff);
29   return ret;
30 }
31 
32 /**
33  * Reverse the bits order in a 16 bit word
34  */
rev_16(uint16_t input)35 static uint32_t rev_16(uint16_t input){
36   uint16_t ret;
37   ret = rev_byte((input >> 0) & 0xff) << 8
38       | rev_byte((input >> 8) & 0xff) << 0;
39   return ret;
40 }
41 
42 /*
43  Table implementation of the CRCs autogenerated with these scripts (with very minor modifications)
44  https://pycrc.org (These python scripts are MIT licensed)
45  Options="--std=C99 --width=24 --poly=0x100065B --algorithm=table-driven --xor-out=0x0 --xor-in=0x555555 --reflect-in=true --reflect-out=true --crc-type=uint32_t"
46  python pycrc.py $Options --generate=h > pycrc_stdout.h
47  python pycrc.py $Options --generate=c-main  > pycrc_stdout.c
48  gcc pycrc_stdout.c -o testexe && ./testexe -s "@"
49  */
50 static const uint32_t crc_table_24_ble[256] = {
51     0x000000, 0x01b4c0, 0x036980, 0x02dd40, 0x06d300, 0x0767c0, 0x05ba80, 0x040e40,
52     0x0da600, 0x0c12c0, 0x0ecf80, 0x0f7b40, 0x0b7500, 0x0ac1c0, 0x081c80, 0x09a840,
53     0x1b4c00, 0x1af8c0, 0x182580, 0x199140, 0x1d9f00, 0x1c2bc0, 0x1ef680, 0x1f4240,
54     0x16ea00, 0x175ec0, 0x158380, 0x143740, 0x103900, 0x118dc0, 0x135080, 0x12e440,
55     0x369800, 0x372cc0, 0x35f180, 0x344540, 0x304b00, 0x31ffc0, 0x332280, 0x329640,
56     0x3b3e00, 0x3a8ac0, 0x385780, 0x39e340, 0x3ded00, 0x3c59c0, 0x3e8480, 0x3f3040,
57     0x2dd400, 0x2c60c0, 0x2ebd80, 0x2f0940, 0x2b0700, 0x2ab3c0, 0x286e80, 0x29da40,
58     0x207200, 0x21c6c0, 0x231b80, 0x22af40, 0x26a100, 0x2715c0, 0x25c880, 0x247c40,
59     0x6d3000, 0x6c84c0, 0x6e5980, 0x6fed40, 0x6be300, 0x6a57c0, 0x688a80, 0x693e40,
60     0x609600, 0x6122c0, 0x63ff80, 0x624b40, 0x664500, 0x67f1c0, 0x652c80, 0x649840,
61     0x767c00, 0x77c8c0, 0x751580, 0x74a140, 0x70af00, 0x711bc0, 0x73c680, 0x727240,
62     0x7bda00, 0x7a6ec0, 0x78b380, 0x790740, 0x7d0900, 0x7cbdc0, 0x7e6080, 0x7fd440,
63     0x5ba800, 0x5a1cc0, 0x58c180, 0x597540, 0x5d7b00, 0x5ccfc0, 0x5e1280, 0x5fa640,
64     0x560e00, 0x57bac0, 0x556780, 0x54d340, 0x50dd00, 0x5169c0, 0x53b480, 0x520040,
65     0x40e400, 0x4150c0, 0x438d80, 0x423940, 0x463700, 0x4783c0, 0x455e80, 0x44ea40,
66     0x4d4200, 0x4cf6c0, 0x4e2b80, 0x4f9f40, 0x4b9100, 0x4a25c0, 0x48f880, 0x494c40,
67     0xda6000, 0xdbd4c0, 0xd90980, 0xd8bd40, 0xdcb300, 0xdd07c0, 0xdfda80, 0xde6e40,
68     0xd7c600, 0xd672c0, 0xd4af80, 0xd51b40, 0xd11500, 0xd0a1c0, 0xd27c80, 0xd3c840,
69     0xc12c00, 0xc098c0, 0xc24580, 0xc3f140, 0xc7ff00, 0xc64bc0, 0xc49680, 0xc52240,
70     0xcc8a00, 0xcd3ec0, 0xcfe380, 0xce5740, 0xca5900, 0xcbedc0, 0xc93080, 0xc88440,
71     0xecf800, 0xed4cc0, 0xef9180, 0xee2540, 0xea2b00, 0xeb9fc0, 0xe94280, 0xe8f640,
72     0xe15e00, 0xe0eac0, 0xe23780, 0xe38340, 0xe78d00, 0xe639c0, 0xe4e480, 0xe55040,
73     0xf7b400, 0xf600c0, 0xf4dd80, 0xf56940, 0xf16700, 0xf0d3c0, 0xf20e80, 0xf3ba40,
74     0xfa1200, 0xfba6c0, 0xf97b80, 0xf8cf40, 0xfcc100, 0xfd75c0, 0xffa880, 0xfe1c40,
75     0xb75000, 0xb6e4c0, 0xb43980, 0xb58d40, 0xb18300, 0xb037c0, 0xb2ea80, 0xb35e40,
76     0xbaf600, 0xbb42c0, 0xb99f80, 0xb82b40, 0xbc2500, 0xbd91c0, 0xbf4c80, 0xbef840,
77     0xac1c00, 0xada8c0, 0xaf7580, 0xaec140, 0xaacf00, 0xab7bc0, 0xa9a680, 0xa81240,
78     0xa1ba00, 0xa00ec0, 0xa2d380, 0xa36740, 0xa76900, 0xa6ddc0, 0xa40080, 0xa5b440,
79     0x81c800, 0x807cc0, 0x82a180, 0x831540, 0x871b00, 0x86afc0, 0x847280, 0x85c640,
80     0x8c6e00, 0x8ddac0, 0x8f0780, 0x8eb340, 0x8abd00, 0x8b09c0, 0x89d480, 0x886040,
81     0x9a8400, 0x9b30c0, 0x99ed80, 0x985940, 0x9c5700, 0x9de3c0, 0x9f3e80, 0x9e8a40,
82     0x972200, 0x9696c0, 0x944b80, 0x95ff40, 0x91f100, 0x9045c0, 0x929880, 0x932c40
83 };
84 
crc_update_ble(uint32_t crc,const void * data,size_t data_len)85 static uint32_t crc_update_ble(uint32_t crc, const void *data, size_t data_len)
86 {
87   const unsigned char *d = (const unsigned char *)data;
88   unsigned int tbl_idx;
89 
90   while (data_len--) {
91     tbl_idx = (crc ^ *d) & 0xff;
92     crc = (crc_table_24_ble[tbl_idx] ^ (crc >> 8)) & 0xffffff;
93 
94     d++;
95   }
96   return crc & 0xffffff;
97 }
98 
99 
100 /**
101  * Append the BLE CRC to a buffer buf of len bytes at the end of the buffer
102  * itself
103  */
append_crc_ble(uint8_t * buf,unsigned int len,uint32_t crc_init)104 void append_crc_ble(uint8_t* buf, unsigned int len, uint32_t crc_init)
105 {
106   uint32_t crc;
107   crc = crc_update_ble( rev_24(crc_init), buf, len );
108 
109   /*Copy CRC itself at the end of the input buffer*/
110   for (int i = 0; i < 3; i++) {
111     buf[len + i] = (crc >> (i*8)) & 0xff;
112   }
113   return;
114 }
115 
116 
117 /*
118  Table implementation of the CRCs autogenerated with these scripts (with very minor changes)
119  https://pycrc.org (These python scripts are MIT licensed)
120  mkdir pycrc && cd pycrc
121  git clone git@github.com:tpircher/pycrc.git .
122 
123  Options="--std=C99 --width=16 --poly=0x1021 --algorithm=table-driven --reflect-in=true --reflect-out=true --crc-type=uint16_t"
124  python3 src/pycrc.py $Options --generate=h > pycrc_stdout.h
125  python3 src/pycrc.py $Options --generate=c-main  > pycrc_stdout.c
126 */
127 static const uint16_t crc_table_154[256] = {
128     0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
129     0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
130     0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
131     0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
132     0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
133     0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
134     0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
135     0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
136     0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
137     0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
138     0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
139     0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
140     0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
141     0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
142     0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
143     0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
144     0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
145     0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
146     0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
147     0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
148     0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
149     0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
150     0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
151     0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
152     0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
153     0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
154     0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
155     0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
156     0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
157     0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
158     0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
159     0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
160 };
161 
crc_update_154(uint16_t crc,const void * data,size_t data_len)162 uint16_t crc_update_154(uint16_t crc, const void *data, size_t data_len)
163 {
164     const unsigned char *d = (const unsigned char *)data;
165     unsigned int tbl_idx;
166 
167     while (data_len--) {
168         tbl_idx = (crc ^ *d) & 0xff;
169         crc = (crc_table_154[tbl_idx] ^ (crc >> 8)) & 0xffff;
170         d++;
171     }
172     return crc & 0xffff;
173 }
174 
175 /**
176  * Append the 154 CRC to a buffer buf of len bytes at the end of the buffer
177  * itself
178  */
append_crc_154(uint8_t * buf,unsigned int len,uint16_t crc_init)179 void append_crc_154(uint8_t* buf, unsigned int len, uint16_t crc_init)
180 {
181   uint16_t crc;
182   crc = crc_update_154( rev_16(crc_init), buf, len );
183 
184   /*Copy CRC itself at the end of the input buffer*/
185   for (int i = 0; i < 2; i++) {
186     buf[len + i] = (crc >> (i*8)) & 0xff;
187   }
188   return;
189 }
190 
191 #if defined(__TEST_CRC_154)
192 //Quick unit test of the 154 CRC
193 // gcc -D__TEST_CRC_154 crc.c -o crc_154test && ./crc_154test
194 #include <string.h>
195 #include <stdlib.h>
196 #include <stdio.h>
197 
198 //An acknowledgment frame with no payload and the following 3 byte MHR (spec example)
199 //  0100 0000 0000 0000 0101 0110 (b0..b23)
200 uint8_t test_data[] = {0x2, 0x0, 0x6A};
201 //Expected CRC: 0010 0111 1001 1110 r0..r15
202 uint8_t test_crc[] = {0xE4, 0x79};
203 
main()204 int main(){
205   uint8_t buffer[10] = {0};
206   memcpy(buffer, test_data, 3);
207 
208   append_crc_154(buffer, 3, 0x0);
209   for (int i=0 ; i < 5; i++){
210     printf("0x%02X ", buffer[i]);
211   }
212   printf("\n");
213 
214   if ((buffer[3] == test_crc[0]) && (buffer[4] == test_crc[1])){
215     printf("CRC was correct -> PASSED\n");
216     return 0;
217   } else {
218     printf("CRC NOT was correct -> FAILED \n");
219     return 1;
220   }
221 }
222 #endif //defined(__TEST_CRC_154)
223