4

The Linux source code has a routine for calculating CRC-16s. It's described as 'standard CRC-16', but doesn't have a formal name. It seems to be using a polynomial of 8005 but is otherwise undescribed.

https://github.com/torvalds/linux/blob/master/lib/crc16.c

/** CRC table for the CRC-16. The poly is 0x8005 (x^16 + x^15 + x^2 + 1) */
u16 const crc16_table[256] = {
    0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
    0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
    0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
...etc...
u16 crc16_byte(u16 crc, const u8 data)
{
    return (crc >> 8) ^ crc16_table[(crc ^ data) & 0xff];
}

u16 crc16(u16 crc, u8 const *buffer, size_t len)
{
    while (len--)
        crc = crc16_byte(crc, *buffer++);
    return crc;
}

I'm having trouble duplicating this with reveng, which doesn't have a setting for 'standard', and I can't tell whether I'm giving it the wrong data or whether I'm using the wrong CRC settings. Does anyone know precisely which CRC-16 variant this is?

1 Answer 1

4

This seems to be CRC-16/MODBUS. Parameter specification can be found on this nice list of CRC16 specifications:

width=16 poly=0x8005 init=0xffff refin=true refout=true xorout=0x0000 check=0x4b37 residue=0x0000 name="CRC-16/MODBUS"

1
  • Fantastic, thanks. (For the record, I have just found out that I was sending it the wrong data too, which didn't help...) Commented May 21, 2023 at 15:25

Not the answer you're looking for? Browse other questions tagged or ask your own question.