xref: /linux/lib/crc/crc16.c (revision a578dd095dfe8b56c167201d9aea43e47d27f807)
189a51591SEric Biggers // SPDX-License-Identifier: GPL-2.0-only
289a51591SEric Biggers /*
389a51591SEric Biggers  *      crc16.c
489a51591SEric Biggers  */
589a51591SEric Biggers 
689a51591SEric Biggers #include <linux/crc16.h>
7*1a822ea5SEric Biggers #include <linux/export.h>
8*1a822ea5SEric Biggers #include <linux/module.h>
9*1a822ea5SEric Biggers #include <linux/types.h>
1089a51591SEric Biggers 
1189a51591SEric Biggers /** CRC table for the CRC-16. The poly is 0x8005 (x^16 + x^15 + x^2 + 1) */
1289a51591SEric Biggers static const u16 crc16_table[256] = {
1389a51591SEric Biggers 	0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
1489a51591SEric Biggers 	0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
1589a51591SEric Biggers 	0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
1689a51591SEric Biggers 	0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
1789a51591SEric Biggers 	0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
1889a51591SEric Biggers 	0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
1989a51591SEric Biggers 	0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
2089a51591SEric Biggers 	0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
2189a51591SEric Biggers 	0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
2289a51591SEric Biggers 	0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
2389a51591SEric Biggers 	0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
2489a51591SEric Biggers 	0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
2589a51591SEric Biggers 	0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
2689a51591SEric Biggers 	0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
2789a51591SEric Biggers 	0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
2889a51591SEric Biggers 	0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
2989a51591SEric Biggers 	0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
3089a51591SEric Biggers 	0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
3189a51591SEric Biggers 	0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
3289a51591SEric Biggers 	0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
3389a51591SEric Biggers 	0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
3489a51591SEric Biggers 	0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
3589a51591SEric Biggers 	0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
3689a51591SEric Biggers 	0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
3789a51591SEric Biggers 	0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
3889a51591SEric Biggers 	0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
3989a51591SEric Biggers 	0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
4089a51591SEric Biggers 	0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
4189a51591SEric Biggers 	0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
4289a51591SEric Biggers 	0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
4389a51591SEric Biggers 	0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
4489a51591SEric Biggers 	0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040
4589a51591SEric Biggers };
4689a51591SEric Biggers 
4789a51591SEric Biggers /**
4889a51591SEric Biggers  * crc16 - compute the CRC-16 for the data buffer
4989a51591SEric Biggers  * @crc:	previous CRC value
5089a51591SEric Biggers  * @p:		data pointer
5189a51591SEric Biggers  * @len:	number of bytes in the buffer
5289a51591SEric Biggers  *
5389a51591SEric Biggers  * Returns the updated CRC value.
5489a51591SEric Biggers  */
crc16(u16 crc,const u8 * p,size_t len)5589a51591SEric Biggers u16 crc16(u16 crc, const u8 *p, size_t len)
5689a51591SEric Biggers {
5789a51591SEric Biggers 	while (len--)
5889a51591SEric Biggers 		crc = (crc >> 8) ^ crc16_table[(crc & 0xff) ^ *p++];
5989a51591SEric Biggers 	return crc;
6089a51591SEric Biggers }
6189a51591SEric Biggers EXPORT_SYMBOL(crc16);
6289a51591SEric Biggers 
6389a51591SEric Biggers MODULE_DESCRIPTION("CRC16 calculations");
6489a51591SEric Biggers MODULE_LICENSE("GPL");
6589a51591SEric Biggers 
66