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.


/** 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,
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


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"

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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