Funkce pro výpočet kontrolního součtu je špatná, a výše zmíněná nelze nijak rozumně použít. Po relativně náročném hledání a úpravě jsem našel konečně funkční verzi:
uint16_t checksum(uint8_t *addr_b, unsigned len)
{
uint16_t* addr = (uint16_t*) addr_b;
uint16_t answer = 0;
/*
* Our algorithm is simple, using a 32 bit accumulator (sum), we add
* sequential 16 bit words to it, and at the end, fold back all the
* carry bits from the top 16 bits into the lower 16 bits.
*/
uint32_t sum = 0;
while (len > 1) {
sum += *addr++;
len -= 2;
}
// mop up an odd byte, if necessary
if (len == 1) {
*(unsigned char *)&answer = *(unsigned char *)addr ;
sum += answer;
}
// add back carry outs from top 16 bits to low 16 bits
sum = (sum >> 16) + (sum & 0xffff); // add high 16 to low 16
sum += (sum >> 16); // add carry
answer = ~sum; // truncate to 16 bits
return answer;
}