I bought a Bluetooth keyboard from China. The manufacturer only has apps for Android and iOS that will allow me to control backlight on the keyboard. So I am currently creating a UWP app for Windows 10 that will allow me to control the backlight.
The Android app creates a (custom?) CRC16 checksum, I am hoping if anyone can help me identify the polynomial and type of CRC16 algorithm it uses. I have tried porting the code to C#, but it seems that the checksums do not match the ones created by the App.
Code:
package com.obins.anne.utils;
import android.support.v4.internal.view.SupportMenu;
import android.support.v4.media.TransportMediator;
import android.support.v4.view.MotionEventCompat;
import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat;
public class CRC16 {
static byte[] crc16_tab_h;
static byte[] crc16_tab_l;
static {
byte[] bArr = new byte[AccessibilityNodeInfoCompat.ACTION_NEXT_AT_MOVEMENT_GRANULARITY];
bArr[1] = (byte) -63;
bArr[2] = (byte) -127;
bArr[3] = (byte) 64;
bArr[4] = (byte) 1;
bArr[5] = (byte) -64;
bArr[6] = Byte.MIN_VALUE;
bArr[7] = (byte) 65;
bArr[8] = (byte) 1;
bArr[9] = (byte) -64;
bArr[10] = Byte.MIN_VALUE;
bArr[11] = (byte) 65;
bArr[13] = (byte) -63;
bArr[14] = (byte) -127;
bArr[15] = (byte) 64;
bArr[16] = (byte) 1;
bArr[17] = (byte) -64;
bArr[18] = Byte.MIN_VALUE;
bArr[19] = (byte) 65;
bArr[21] = (byte) -63;
bArr[22] = (byte) -127;
bArr[23] = (byte) 64;
bArr[25] = (byte) -63;
bArr[26] = (byte) -127;
bArr[27] = (byte) 64;
bArr[28] = (byte) 1;
bArr[29] = (byte) -64;
bArr[30] = Byte.MIN_VALUE;
bArr[31] = (byte) 65;
bArr[32] = (byte) 1;
bArr[33] = (byte) -64;
bArr[34] = Byte.MIN_VALUE;
bArr[35] = (byte) 65;
bArr[37] = (byte) -63;
bArr[38] = (byte) -127;
bArr[39] = (byte) 64;
bArr[41] = (byte) -63;
bArr[42] = (byte) -127;
bArr[43] = (byte) 64;
bArr[44] = (byte) 1;
bArr[45] = (byte) -64;
bArr[46] = Byte.MIN_VALUE;
bArr[47] = (byte) 65;
bArr[49] = (byte) -63;
bArr[50] = (byte) -127;
bArr[51] = (byte) 64;
bArr[52] = (byte) 1;
bArr[53] = (byte) -64;
bArr[54] = Byte.MIN_VALUE;
bArr[55] = (byte) 65;
bArr[56] = (byte) 1;
bArr[57] = (byte) -64;
bArr[58] = Byte.MIN_VALUE;
bArr[59] = (byte) 65;
bArr[61] = (byte) -63;
bArr[62] = (byte) -127;
bArr[63] = (byte) 64;
bArr[64] = (byte) 1;
bArr[65] = (byte) -64;
bArr[66] = Byte.MIN_VALUE;
bArr[67] = (byte) 65;
bArr[69] = (byte) -63;
bArr[70] = (byte) -127;
bArr[71] = (byte) 64;
bArr[73] = (byte) -63;
bArr[74] = (byte) -127;
bArr[75] = (byte) 64;
bArr[76] = (byte) 1;
bArr[77] = (byte) -64;
bArr[78] = Byte.MIN_VALUE;
bArr[79] = (byte) 65;
bArr[81] = (byte) -63;
bArr[82] = (byte) -127;
bArr[83] = (byte) 64;
bArr[84] = (byte) 1;
bArr[85] = (byte) -64;
bArr[86] = Byte.MIN_VALUE;
bArr[87] = (byte) 65;
bArr[88] = (byte) 1;
bArr[89] = (byte) -64;
bArr[90] = Byte.MIN_VALUE;
bArr[91] = (byte) 65;
bArr[93] = (byte) -63;
bArr[94] = (byte) -127;
bArr[95] = (byte) 64;
bArr[97] = (byte) -63;
bArr[98] = (byte) -127;
bArr[99] = (byte) 64;
bArr[100] = (byte) 1;
bArr[101] = (byte) -64;
bArr[102] = Byte.MIN_VALUE;
bArr[103] = (byte) 65;
bArr[104] = (byte) 1;
bArr[105] = (byte) -64;
bArr[106] = Byte.MIN_VALUE;
bArr[107] = (byte) 65;
bArr[109] = (byte) -63;
bArr[110] = (byte) -127;
bArr[111] = (byte) 64;
bArr[112] = (byte) 1;
bArr[113] = (byte) -64;
bArr[114] = Byte.MIN_VALUE;
bArr[115] = (byte) 65;
bArr[117] = (byte) -63;
bArr[118] = (byte) -127;
bArr[119] = (byte) 64;
bArr[121] = (byte) -63;
bArr[122] = (byte) -127;
bArr[123] = (byte) 64;
bArr[124] = (byte) 1;
bArr[125] = (byte) -64;
bArr[TransportMediator.KEYCODE_MEDIA_PLAY] = Byte.MIN_VALUE;
bArr[TransportMediator.KEYCODE_MEDIA_PAUSE] = (byte) 65;
bArr[TransportMediator.FLAG_KEY_MEDIA_NEXT] = (byte) 1;
bArr[Msgprotocol.SYSTEM_ACK_GET_ID] = (byte) -64;
bArr[TransportMediator.KEYCODE_MEDIA_RECORD] = Byte.MIN_VALUE;
bArr[Msgprotocol.SYSTEM_ACK_ENTER_DFU] = (byte) 65;
bArr[Msgprotocol.SYSTEM_ACK_GET_FW_VER] = (byte) -63;
bArr[Msgprotocol.SYSTEM_ACK_GET_DEVICE_TYPE] = (byte) -127;
bArr[Msgprotocol.SYSTEM_ACK_GET_PROTOCOL_VER] = (byte) 64;
bArr[Msgprotocol.SYSTEM_ACK_SET_SYNC_CODE] = (byte) -63;
bArr[Msgprotocol.LEDSTYLE_ACK_MODE_GET_USER_STATIC_CRC_ID] = (byte) -127;
bArr[Msgprotocol.BLE_ACK_CURRENT_HOST_QUERY] = (byte) 64;
bArr[Msgprotocol.BLE_ACK_COMP_MODE] = (byte) 1;
bArr[141] = (byte) -64;
bArr[142] = Byte.MIN_VALUE;
bArr[143] = (byte) 65;
bArr[145] = (byte) -63;
bArr[146] = (byte) -127;
bArr[147] = (byte) 64;
bArr[148] = (byte) 1;
bArr[149] = (byte) -64;
bArr[150] = Byte.MIN_VALUE;
bArr[151] = (byte) 65;
bArr[152] = (byte) 1;
bArr[153] = (byte) -64;
bArr[154] = Byte.MIN_VALUE;
bArr[155] = (byte) 65;
bArr[157] = (byte) -63;
bArr[158] = (byte) -127;
bArr[159] = (byte) 64;
bArr[161] = (byte) -63;
bArr[162] = (byte) -127;
bArr[163] = (byte) 64;
bArr[164] = (byte) 1;
bArr[165] = (byte) -64;
bArr[166] = Byte.MIN_VALUE;
bArr[167] = (byte) 65;
bArr[168] = (byte) 1;
bArr[169] = (byte) -64;
bArr[170] = Byte.MIN_VALUE;
bArr[171] = (byte) 65;
bArr[173] = (byte) -63;
bArr[174] = (byte) -127;
bArr[175] = (byte) 64;
bArr[176] = (byte) 1;
bArr[177] = (byte) -64;
bArr[178] = Byte.MIN_VALUE;
bArr[179] = (byte) 65;
bArr[181] = (byte) -63;
bArr[182] = (byte) -127;
bArr[183] = (byte) 64;
bArr[185] = (byte) -63;
bArr[186] = (byte) -127;
bArr[187] = (byte) 64;
bArr[188] = (byte) 1;
bArr[189] = (byte) -64;
bArr[190] = Byte.MIN_VALUE;
bArr[191] = (byte) 65;
bArr[193] = (byte) -63;
bArr[194] = (byte) -127;
bArr[195] = (byte) 64;
bArr[196] = (byte) 1;
bArr[197] = (byte) -64;
bArr[198] = Byte.MIN_VALUE;
bArr[199] = (byte) 65;
bArr[200] = (byte) 1;
bArr[201] = (byte) -64;
bArr[202] = Byte.MIN_VALUE;
bArr[203] = (byte) 65;
bArr[205] = (byte) -63;
bArr[206] = (byte) -127;
bArr[207] = (byte) 64;
bArr[208] = (byte) 1;
bArr[209] = (byte) -64;
bArr[210] = Byte.MIN_VALUE;
bArr[211] = (byte) 65;
bArr[213] = (byte) -63;
bArr[214] = (byte) -127;
bArr[215] = (byte) 64;
bArr[217] = (byte) -63;
bArr[218] = (byte) -127;
bArr[219] = (byte) 64;
bArr[220] = (byte) 1;
bArr[221] = (byte) -64;
bArr[222] = Byte.MIN_VALUE;
bArr[223] = (byte) 65;
bArr[224] = (byte) 1;
bArr[225] = (byte) -64;
bArr[226] = Byte.MIN_VALUE;
bArr[227] = (byte) 65;
bArr[229] = (byte) -63;
bArr[230] = (byte) -127;
bArr[231] = (byte) 64;
bArr[233] = (byte) -63;
bArr[234] = (byte) -127;
bArr[235] = (byte) 64;
bArr[236] = (byte) 1;
bArr[237] = (byte) -64;
bArr[238] = Byte.MIN_VALUE;
bArr[239] = (byte) 65;
bArr[241] = (byte) -63;
bArr[242] = (byte) -127;
bArr[243] = (byte) 64;
bArr[244] = (byte) 1;
bArr[245] = (byte) -64;
bArr[246] = Byte.MIN_VALUE;
bArr[247] = (byte) 65;
bArr[248] = (byte) 1;
bArr[249] = (byte) -64;
bArr[250] = Byte.MIN_VALUE;
bArr[251] = (byte) 65;
bArr[253] = (byte) -63;
bArr[254] = (byte) -127;
bArr[MotionEventCompat.ACTION_MASK] = (byte) 64;
crc16_tab_h = bArr;
bArr = new byte[AccessibilityNodeInfoCompat.ACTION_NEXT_AT_MOVEMENT_GRANULARITY];
bArr[1] = (byte) -64;
bArr[2] = (byte) -63;
bArr[3] = (byte) 1;
bArr[4] = (byte) -61;
bArr[5] = (byte) 3;
bArr[6] = (byte) 2;
bArr[7] = (byte) -62;
bArr[8] = (byte) -58;
bArr[9] = (byte) 6;
bArr[10] = (byte) 7;
bArr[11] = (byte) -57;
bArr[12] = (byte) 5;
bArr[13] = (byte) -59;
bArr[14] = (byte) -60;
bArr[15] = (byte) 4;
bArr[16] = (byte) -52;
bArr[17] = (byte) 12;
bArr[18] = (byte) 13;
bArr[19] = (byte) -51;
bArr[20] = (byte) 15;
bArr[21] = (byte) -49;
bArr[22] = (byte) -50;
bArr[23] = (byte) 14;
bArr[24] = (byte) 10;
bArr[25] = (byte) -54;
bArr[26] = (byte) -53;
bArr[27] = (byte) 11;
bArr[28] = (byte) -55;
bArr[29] = (byte) 9;
bArr[30] = (byte) 8;
bArr[31] = (byte) -56;
bArr[32] = (byte) -40;
bArr[33] = (byte) 24;
bArr[34] = (byte) 25;
bArr[35] = (byte) -39;
bArr[36] = (byte) 27;
bArr[37] = (byte) -37;
bArr[38] = (byte) -38;
bArr[39] = (byte) 26;
bArr[40] = (byte) 30;
bArr[41] = (byte) -34;
bArr[42] = (byte) -33;
bArr[43] = (byte) 31;
bArr[44] = (byte) -35;
bArr[45] = (byte) 29;
bArr[46] = (byte) 28;
bArr[47] = (byte) -36;
bArr[48] = (byte) 20;
bArr[49] = (byte) -44;
bArr[50] = (byte) -43;
bArr[51] = (byte) 21;
bArr[52] = (byte) -41;
bArr[53] = (byte) 23;
bArr[54] = (byte) 22;
bArr[55] = (byte) -42;
bArr[56] = (byte) -46;
bArr[57] = (byte) 18;
bArr[58] = (byte) 19;
bArr[59] = (byte) -45;
bArr[60] = (byte) 17;
bArr[61] = (byte) -47;
bArr[62] = (byte) -48;
bArr[63] = (byte) 16;
bArr[64] = (byte) -16;
bArr[65] = (byte) 48;
bArr[66] = (byte) 49;
bArr[67] = (byte) -15;
bArr[68] = (byte) 51;
bArr[69] = (byte) -13;
bArr[70] = (byte) -14;
bArr[71] = (byte) 50;
bArr[72] = (byte) 54;
bArr[73] = (byte) -10;
bArr[74] = (byte) -9;
bArr[75] = (byte) 55;
bArr[76] = (byte) -11;
bArr[77] = (byte) 53;
bArr[78] = (byte) 52;
bArr[79] = (byte) -12;
bArr[80] = (byte) 60;
bArr[81] = (byte) -4;
bArr[82] = (byte) -3;
bArr[83] = (byte) 61;
bArr[84] = (byte) -1;
bArr[85] = (byte) 63;
bArr[86] = (byte) 62;
bArr[87] = (byte) -2;
bArr[88] = (byte) -6;
bArr[89] = (byte) 58;
bArr[90] = (byte) 59;
bArr[91] = (byte) -5;
bArr[92] = (byte) 57;
bArr[93] = (byte) -7;
bArr[94] = (byte) -8;
bArr[95] = (byte) 56;
bArr[96] = (byte) 40;
bArr[97] = (byte) -24;
bArr[98] = (byte) -23;
bArr[99] = (byte) 41;
bArr[100] = (byte) -21;
bArr[101] = (byte) 43;
bArr[102] = (byte) 42;
bArr[103] = (byte) -22;
bArr[104] = (byte) -18;
bArr[105] = (byte) 46;
bArr[106] = (byte) 47;
bArr[107] = (byte) -17;
bArr[108] = (byte) 45;
bArr[109] = (byte) -19;
bArr[110] = (byte) -20;
bArr[111] = (byte) 44;
bArr[112] = (byte) -28;
bArr[113] = (byte) 36;
bArr[114] = (byte) 37;
bArr[115] = (byte) -27;
bArr[116] = (byte) 39;
bArr[117] = (byte) -25;
bArr[118] = (byte) -26;
bArr[119] = (byte) 38;
bArr[120] = (byte) 34;
bArr[121] = (byte) -30;
bArr[122] = (byte) -29;
bArr[123] = (byte) 35;
bArr[124] = (byte) -31;
bArr[125] = (byte) 33;
bArr[TransportMediator.KEYCODE_MEDIA_PLAY] = (byte) 32;
bArr[TransportMediator.KEYCODE_MEDIA_PAUSE] = (byte) -32;
bArr[TransportMediator.FLAG_KEY_MEDIA_NEXT] = (byte) -96;
bArr[Msgprotocol.SYSTEM_ACK_GET_ID] = (byte) 96;
bArr[TransportMediator.KEYCODE_MEDIA_RECORD] = (byte) 97;
bArr[Msgprotocol.SYSTEM_ACK_ENTER_DFU] = (byte) -95;
bArr[Msgprotocol.SYSTEM_ACK_PING] = (byte) 99;
bArr[Msgprotocol.SYSTEM_ACK_GET_FW_VER] = (byte) -93;
bArr[Msgprotocol.SYSTEM_ACK_GET_DEVICE_TYPE] = (byte) -94;
bArr[Msgprotocol.SYSTEM_ACK_GET_PROTOCOL_VER] = (byte) 98;
bArr[Msgprotocol.SYSTEM_ACK_IS_SYNC_CODE] = (byte) 102;
bArr[Msgprotocol.SYSTEM_ACK_SET_SYNC_CODE] = (byte) -90;
bArr[Msgprotocol.LEDSTYLE_ACK_MODE_GET_USER_STATIC_CRC_ID] = (byte) -89;
bArr[Msgprotocol.BLE_ACK_CURRENT_HOST_QUERY] = (byte) 103;
bArr[Msgprotocol.BLE_ACK_COMP_MODE] = (byte) -91;
bArr[141] = (byte) 101;
bArr[142] = (byte) 100;
bArr[143] = (byte) -92;
bArr[144] = (byte) 108;
bArr[145] = (byte) -84;
bArr[146] = (byte) -83;
bArr[147] = (byte) 109;
bArr[148] = (byte) -81;
bArr[149] = (byte) 111;
bArr[150] = (byte) 110;
bArr[151] = (byte) -82;
bArr[152] = (byte) -86;
bArr[153] = (byte) 106;
bArr[154] = (byte) 107;
bArr[155] = (byte) -85;
bArr[156] = (byte) 105;
bArr[157] = (byte) -87;
bArr[158] = (byte) -88;
bArr[159] = (byte) 104;
bArr[160] = (byte) 120;
bArr[161] = (byte) -72;
bArr[162] = (byte) -71;
bArr[163] = (byte) 121;
bArr[164] = (byte) -69;
bArr[165] = (byte) 123;
bArr[166] = (byte) 122;
bArr[167] = (byte) -70;
bArr[168] = (byte) -66;
bArr[169] = (byte) 126;
bArr[170] = Byte.MAX_VALUE;
bArr[171] = (byte) -65;
bArr[172] = (byte) 125;
bArr[173] = (byte) -67;
bArr[174] = (byte) -68;
bArr[175] = (byte) 124;
bArr[176] = (byte) -76;
bArr[177] = (byte) 116;
bArr[178] = (byte) 117;
bArr[179] = (byte) -75;
bArr[180] = (byte) 119;
bArr[181] = (byte) -73;
bArr[182] = (byte) -74;
bArr[183] = (byte) 118;
bArr[184] = (byte) 114;
bArr[185] = (byte) -78;
bArr[186] = (byte) -77;
bArr[187] = (byte) 115;
bArr[188] = (byte) -79;
bArr[189] = (byte) 113;
bArr[190] = (byte) 112;
bArr[191] = (byte) -80;
bArr[192] = (byte) 80;
bArr[193] = (byte) -112;
bArr[194] = (byte) -111;
bArr[195] = (byte) 81;
bArr[196] = (byte) -109;
bArr[197] = (byte) 83;
bArr[198] = (byte) 82;
bArr[199] = (byte) -110;
bArr[200] = (byte) -106;
bArr[201] = (byte) 86;
bArr[202] = (byte) 87;
bArr[203] = (byte) -105;
bArr[204] = (byte) 85;
bArr[205] = (byte) -107;
bArr[206] = (byte) -108;
bArr[207] = (byte) 84;
bArr[208] = (byte) -100;
bArr[209] = (byte) 92;
bArr[210] = (byte) 93;
bArr[211] = (byte) -99;
bArr[212] = (byte) 95;
bArr[213] = (byte) -97;
bArr[214] = (byte) -98;
bArr[215] = (byte) 94;
bArr[216] = (byte) 90;
bArr[217] = (byte) -102;
bArr[218] = (byte) -101;
bArr[219] = (byte) 91;
bArr[220] = (byte) -103;
bArr[221] = (byte) 89;
bArr[222] = (byte) 88;
bArr[223] = (byte) -104;
bArr[224] = (byte) -120;
bArr[225] = (byte) 72;
bArr[226] = (byte) 73;
bArr[227] = (byte) -119;
bArr[228] = (byte) 75;
bArr[229] = (byte) -117;
bArr[230] = (byte) -118;
bArr[231] = (byte) 74;
bArr[232] = (byte) 78;
bArr[233] = (byte) -114;
bArr[234] = (byte) -113;
bArr[235] = (byte) 79;
bArr[236] = (byte) -115;
bArr[237] = (byte) 77;
bArr[238] = (byte) 76;
bArr[239] = (byte) -116;
bArr[240] = (byte) 68;
bArr[241] = (byte) -124;
bArr[242] = (byte) -123;
bArr[243] = (byte) 69;
bArr[244] = (byte) -121;
bArr[245] = (byte) 71;
bArr[246] = (byte) 70;
bArr[247] = (byte) -122;
bArr[248] = (byte) -126;
bArr[249] = (byte) 66;
bArr[250] = (byte) 67;
bArr[251] = (byte) -125;
bArr[252] = (byte) 65;
bArr[253] = (byte) -127;
bArr[254] = Byte.MIN_VALUE;
bArr[MotionEventCompat.ACTION_MASK] = (byte) 64;
crc16_tab_l = bArr;
}
public static int calcCrc16(byte[] data) {
return calcCrc16(data, 0, data.length);
}
public static int calcCrc16(byte[] data, int offset, int len) {
return calcCrc16(data, offset, len, SupportMenu.USER_MASK);
}
public static int calcCrc16(byte[] data, int offset, int len, int preval) {
int ucCRCHi = (MotionEventCompat.ACTION_POINTER_INDEX_MASK & preval) >> 8;
int ucCRCLo = preval & MotionEventCompat.ACTION_MASK;
for (int i = 0; i < len; i++) {
int iIndex = (data[offset + i] ^ ucCRCLo) & MotionEventCompat.ACTION_MASK;
ucCRCLo = ucCRCHi ^ crc16_tab_h[iIndex];
ucCRCHi = crc16_tab_l[iIndex];
}
return ((ucCRCHi & MotionEventCompat.ACTION_MASK) << 8) | ((ucCRCLo & MotionEventCompat.ACTION_MASK) & SupportMenu.USER_MASK);
}