//------------------------------------------------------------------- // usbcrc16.cpp // // This program illustrates the steps needed in order compute // the 16-bit Cyclic Redundancy Check for a USB data-packet. // // programmer: ALLAN CRUSE // written on: 13 JUN 2011 //------------------------------------------------------------------- #include // for printf() #define USB_POLY16 0x18005 // USB CRC-16 polynomial unsigned int mod2( unsigned int arg32 ) { unsigned int temp = arg32; unsigned int parm = USB_POLY16 << 15; unsigned int pop; int bits_to_do = 8; while ( bits_to_do > 0 ) { pop = ( temp >> 31 ) & 1; if ( pop ) temp = (temp ^ parm); temp <<= 1; --bits_to_do; } return temp; } unsigned int bit_reflect08( unsigned char arg08 ) { unsigned int temp = 0; for (int i = 0; i < 8; i++) { temp <<= 1; if ( (arg08 >> i) & 1 ) temp |= 1; } return temp; } unsigned int bit_reflect16( unsigned short arg16 ) { unsigned int temp = 0; for (int i = 0; i < 16; i++) { temp <<= 1; if ( (arg16 >> i) & 1 ) temp |= 1; } return temp; } unsigned int bit_reflect32( unsigned int arg32 ) { unsigned int temp = 0; for (int i = 0; i < 32; i++) { temp <<= 1; if ( (arg32 >> i) & 1 ) temp |= 1; } return temp; } unsigned int crc16( unsigned char octet, unsigned short dst16 ) { // Algorithm is adapted from pseudocode describing the // operation of Intel's x86_64 'crc32' instruction, in // "Volume 2A: Instruction Set Reference", of Intel 64 // and IA-32 Architecture Software Developer's Manual. unsigned int temp1 = bit_reflect08( octet ); unsigned int temp2 = bit_reflect16( dst16 ); unsigned int temp3 = temp1 << 24; unsigned int temp4 = temp2 << 16; unsigned int temp5 = temp3 ^ temp4; unsigned int temp6 = mod2( temp5 ); unsigned int temp7 = bit_reflect32( temp6 ); return temp7; } unsigned char data[ 8 ] = // From 'Get_Descriptor' transaction { 0x80, 0x06, 0x00, 0x01, 0x00, 0x00, 0x40, 0x00 }; int main( int argc, char **argv ) { // display the packet's data-field printf( "\n Packet-Data: " ); for (int i = 0; i < sizeof( data ); i++) printf( "%02X ", data[i] ); printf( "\n" ); // seed the register with all 1's unsigned short crc = 0xFFFF; // perform the polynomial division in GF(2) for (int i = 0; i < 8; i++) crc = crc16( data[i], crc ); // complement the register-bits crc = (crc ^ 0xFFFF); // Report the 16-bit CRC value printf( "\n crc16=0x%04X \n\n", crc ); } //-------------------------------------------------------------------- // REFERENCE: USB Specification, Revision 2.0 (April 2000), page 198. //--------------------------------------------------------------------