static unsigned long crctable[256]; static unsigned char crcinvtable[256]; static unsigned long poly = 0xedb88320; void set_poly(unsigned long p) { poly = p; } unsigned long get_crc_table(unsigned long i) { return crctable[i]; } static inline unsigned char l2c(unsigned long l, int nr) { return (l >> (8*(nr-1))) & 0xff; } void calc_crc_table(void) { unsigned long value, idx, i; for (idx = 0 ; idx < 256 ; idx++) { for (value = idx, i = 0 ; i < 8 ; i++) { if (value & 1) { value >>= 1; value ^= poly; } else { value >>= 1; } } crctable[idx] = value; crcinvtable[l2c(value, 4)] = idx; } } unsigned long iter_crc(unsigned long c, unsigned long shiftreg) { return (shiftreg >> 8) ^ crctable[(c ^ shiftreg) & 0xff]; } unsigned long inv_iter_crc(unsigned long c, unsigned long shiftreg) { unsigned long i = crcinvtable[l2c(shiftreg, 4)]; return ((shiftreg ^ crctable[i]) << 8) | l2c(i ^ c, 1); } unsigned long calc_crc(unsigned char *buf, unsigned long buflen, unsigned long crc) { while (buflen--) crc = iter_crc(*buf++, crc); return ~crc; } unsigned long solve(unsigned char *buf, unsigned long buflen, unsigned long crc, unsigned long wcrc) { unsigned char a, b, c, d; while (buflen--) crc = iter_crc(*buf++, crc); wcrc = ~wcrc; // sequence of crc's we must have to finish with wcrc unsigned long c1, c2, c3, c4; c4 = crctable[ crcinvtable[ l2c(wcrc, 4) ] ]; c3 = crctable[ crcinvtable[ l2c(wcrc, 3) ^ l2c(c4, 3) ] ]; c2 = crctable[ crcinvtable[ l2c(wcrc, 2) ^ l2c(c4, 2) ^ l2c(c3, 3) ] ]; c1 = crctable[ crcinvtable[ l2c(wcrc, 1) ^ l2c(c4, 1) ^ l2c(c3, 2) ^ l2c(c2, 3) ] ]; a = crcinvtable[l2c(c1, 4)] ^ l2c(crc, 1); crc = (crc >> 8) ^ crctable[(a ^ crc) & 0xff]; b = crcinvtable[l2c(c2, 4)] ^ l2c(crc, 1); crc = (crc >> 8) ^ crctable[(b ^ crc) & 0xff]; c = crcinvtable[l2c(c3, 4)] ^ l2c(crc, 1); crc = (crc >> 8) ^ crctable[(c ^ crc) & 0xff]; d = crcinvtable[l2c(c4, 4)] ^ l2c(crc, 1); crc = 0; crc |= d; crc <<= 8; crc |= c; crc <<= 8; crc |= b; crc <<= 8; crc |= a; return crc; } unsigned long not(unsigned long l) { return ~l; }