IsoDep Tag send always 0x0B as result for all APDUs - nfc

I've a problem with my MobiGo2F terminal.
The Android system version is 10. When I send APDUs to my smartcard,
I always receive 0B as result. Find below my code:
String action = intent.getAction();
if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(action)
|| NfcAdapter.ACTION_TECH_DISCOVERED.equals(action)
|| NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action)) {
Tag tagI = (Tag) intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
byte[] serial=intent.getByteArrayExtra(NfcAdapter.EXTRA_ID);
Log.v("SN : ", Utils.bytesToHex(serial));
assert tagI != null;
byte[] payload = detectTagData(tagI).getBytes();
IsoDep tag = IsoDep.get(tagI);
byte[] APDU = {
(byte) 0x00, // CLA Class
(byte) 0x84, // INS Instruction
(byte) 0x00, // P1 Parameter 1
(byte) 0x00, // P2 Parameter 2
(byte) 0x08 // LE maximal number of bytes expected in result
};
byte[] result = new byte[0];
try {
tag.connect();
tag.setTimeout(10000);
result = tag.transceive(APDU);
Log.v("result =", Utils.bytesToHex(result) + " & lenght = " + result.length);
} catch (Exception e) {
e.printStackTrace();
}
}
The result that I got is:
Result
I received 0B for any APDUs that I send. Normally, ISO7816 describe APDU response as 2 bytes, SW1 and SW2.
Need your support and enjoy Code!

Related

Analog measurement incorrect on Teensy 2.0++

I have a Joystick wired up to my Teensy 2.0++ and I want to read the analog values from it.
I took this implementation from PJRC:
static uint8_t aref = (1<<REFS0); // default to AREF = Vcc, this is a 5V Vcc Teensy
void analogReference(uint8_t mode)
{
aref = mode & 0xC0;
}
// Mux input
int16_t adc_read(uint8_t mux)
{
#if defined(__AVR_AT90USB162__)
return 0;
#else
uint8_t low;
ADCSRA = (1<<ADEN) | ADC_PRESCALER; // enable ADC
ADCSRB = (1<<ADHSM) | (mux & 0x20); // high speed mode
ADMUX = aref | (mux & 0x1F); // configure mux input
ADCSRA = (1<<ADEN) | ADC_PRESCALER | (1<<ADSC); // start the conversion
while (ADCSRA & (1<<ADSC)) ; // wait for result
low = ADCL; // must read LSB first
return (ADCH << 8) | low; // must read MSB only once!
#endif
}
// Arduino compatible pin input
int16_t analogRead(uint8_t pin)
{
#if defined(__AVR_ATmega32U4__)
static const uint8_t PROGMEM pin_to_mux[] = {
0x00, 0x01, 0x04, 0x05, 0x06, 0x07,
0x25, 0x24, 0x23, 0x22, 0x21, 0x20};
if (pin >= 12) return 0;
return adc_read(pgm_read_byte(pin_to_mux + pin));
#elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)
if (pin >= 8) return 0;
return adc_read(pin);
#else
return 0;
#endif
}
I have my X and Y pins wired up to F1 and F0, and I want to retrieve values with the following code:
long map(long x, long in_min, long in_max, long out_min, long out_max) // map method shamelessy ripped from Arduino
{
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}
joy_ly = map(analogRead(0), 0, 65535, 0, 255);
joy_lx = map(analogRead(1), 0, 65535, 0, 255);
I measured my Joystick with a multimeter and it works perfectly (around 2.43V on center, 0V on min, and 5V on max), but the center value always ends up being very close to zero.
Is there anything I'm doing wrong?
NOTE: This is an at90usb1286 chip.
The ADC max value is 1024, not 65535.

Optimal uint8_t bitmap into a 8 x 32bit SIMD "bool" vector

As part of a compression algorithm, I am looking for the optimal way to achieve the following:
I have a simple bitmap in a uint8_t. For example 01010011
What I want is a __m256i of the form: (0, maxint, 0, maxint, 0, 0, maxint, maxint)
One way to achieve this is by shuffling a vector of 8 x maxint into a vector of zeros. But that first requires me to expand my uint8_t to the right shuffle bitmap.
I am wondering if there is a better way?
I think I'd probably go for the "brute force and ignorance" approach initially, maybe something like this:
uint8_t u = 0x53; // 01010011
const union {
uint32_t a[4];
__m128i v;
} kLUT[16] = { { { 0, 0, 0, 0 } },
{ { -1, 0, 0, 0 } },
{ { 0, -1, 0, 0 } },
{ { -1, -1, 0, 0 } },
{ { 0, 0, -1, 0 } },
{ { -1, 0, -1, 0 } },
{ { 0, -1, -1, 0 } },
{ { -1, -1, -1, 0 } },
{ { 0, 0, 0, -1 } },
{ { -1, 0, 0, -1 } },
{ { 0, -1, 0, -1 } },
{ { -1, -1, 0, -1 } },
{ { 0, 0, -1, -1 } },
{ { -1, 0, -1, -1 } },
{ { 0, -1, -1, -1 } },
{ { -1, -1, -1, -1 } } };
__m256i v = _mm256_set_m128i(kLUT[u >> 4].v, kLUT[u & 15].v);
Using clang -O3 this compiles to:
movl %ebx, %eax ;; eax = ebx = u
andl $15, %eax ;; get low offset = (u & 15) * 16
shlq $4, %rax
leaq _main.kLUT(%rip), %rcx ;; rcx = kLUT
vmovaps (%rax,%rcx), %xmm0 ;; load low half of ymm0 from kLUT
andl $240, %ebx ;; get high offset = (u >> 4) * 16
vinsertf128 $1, (%rbx,%rcx), %ymm0, %ymm0
;; load high half of ymm0 from kLUT
FWIW I threw together a simple test harness for three implementations: (i) a simple scalar code reference implementation, (ii) the above code, (iii) an implementation based on #Zboson's answer, (iv) a slightly improved version of (iii) and (v) a further improvement on (iv) using a suggestion from #MarcGlisse. I got the following results with a 2.6GHz Haswell CPU (compiled with clang -O3):
scalar code: 7.55336 ns / vector
Paul R: 1.36016 ns / vector
Z boson: 1.24863 ns / vector
Z boson (improved): 1.07590 ns / vector
Z boson (improved + #MarcGlisse suggestion): 1.08195 ns / vector
So #Zboson's solution(s) win, by around 10% - 20%, presumably because they need only 1 load, versus 2 for mine.
If we get any other implementations I'll add these to the test harness and update the results.
Slightly improved version of #Zboson's implementation:
__m256i v = _mm256_set1_epi8(u);
v = _mm256_and_si256(v, mask);
v = _mm256_xor_si256(v, mask);
return _mm256_cmpeq_epi32(v, _mm256_setzero_si256());
Further improved version of #Zboson's implementation incorporating suggestion from #MarcGlisse:
__m256i v = _mm256_set1_epi8(u);
v = _mm256_and_si256(v, mask);
return _mm256_cmpeq_epi32(v, mask);
(Note that mask needs to contain replicated 8 bit values in each 32 bit element, i.e. 0x01010101, 0x02020202, ..., 0x80808080)
Here is a solution (PaulR improved my solution, see the end of my answer or his answer) based on a variation of this question fastest-way-to-broadcast-32-bits-in-32-bytes.
__m256i t1 = _mm256_set1_epi8(x);
__m256i t2 = _mm256_and_si256(t1, mask);
__m256i t4 = _mm256_cmpeq_epi32(t2, _mm256_setzero_si256());
t4 = _mm256_xor_si256(t4, _mm256_set1_epi32(-1));
I don't have AVX2 hardware to test this on right now but here is a SSE2 version showing that it works which also shows how to define the mask.
#include <x86intrin.h>
#include <stdint.h>
#include <stdio.h>
int main(void) {
char mask[32] = {
0x01, 0x00, 0x00, 0x00,
0x02, 0x00, 0x00, 0x00,
0x04, 0x00, 0x00, 0x00,
0x08, 0x00, 0x00, 0x00,
0x10, 0x00, 0x00, 0x00,
0x20, 0x00, 0x00, 0x00,
0x40, 0x00, 0x00, 0x00,
0x80, 0x00, 0x00, 0x00,
};
__m128i mask1 = _mm_loadu_si128((__m128i*)&mask[ 0]);
__m128i mask2 = _mm_loadu_si128((__m128i*)&mask[16]);
uint8_t x = 0x53; //0101 0011
__m128i t1 = _mm_set1_epi8(x);
__m128i t2 = _mm_and_si128(t1, mask1);
__m128i t3 = _mm_and_si128(t1, mask2);
__m128i t4 = _mm_cmpeq_epi32(t2,_mm_setzero_si128());
__m128i t5 = _mm_cmpeq_epi32(t3,_mm_setzero_si128());
t4 = _mm_xor_si128(t4, _mm_set1_epi32(-1));
t5 = _mm_xor_si128(t5, _mm_set1_epi32(-1));
int o1[4], o2[4];
_mm_store_si128((__m128i*)o1, t4);
_mm_store_si128((__m128i*)o2, t5);
for(int i=0; i<4; i++) printf("%d \n", o1[i]);
for(int i=0; i<4; i++) printf("%d \n", o2[i]);
}
Edit:
PaulR improved my solution
__m256i v = _mm256_set1_epi8(u);
v = _mm256_and_si256(v, mask);
v = _mm256_xor_si256(v, mask);
return _mm256_cmpeq_epi32(v, _mm256_setzero_si256());
with the mask defined as
int mask[8] = {
0x01010101, 0x02020202, 0x04040404, 0x08080808,
0x10101010, 0x20202020, 0x40404040, 0x80808080,
};
See his answer with performance testing for more details.
Based on all the answers, I hacked up a solution using Agner Fog's excellent library (which handles both AVX2, AVX and SSE solutions with a common abstraction). Figured I would share it as an alternative answer:
// Used to generate 32 bit vector bitmasks from 8 bit ints
static const Vec8ui VecBitMask8(
0x01010101
, 0x02020202
, 0x04040404
, 0x08080808
, 0x10101010
, 0x20202020
, 0x40404040
, 0x80808080);
// As above, but for 64 bit vectors and 4 bit ints
static const Vec4uq VecBitMask4(
0x0101010101010101
, 0x0202020202020202
, 0x0404040404040404
, 0x0808080808080808);
template <typename V>
inline static Vec32c getBitmapMask();
template <> inline Vec32c getBitmapMask<Vec8ui>() {return VecBitMask8;};
template <> inline Vec32c getBitmapMask<Vec8i>() {return VecBitMask8;};
template <> inline Vec32c getBitmapMask<Vec4uq>() {return VecBitMask4;};
template <> inline Vec32c getBitmapMask<Vec4q>() {return VecBitMask4;};
// Returns a bool vector representing the bitmask passed.
template <typename V>
static inline V getBitmap(const uint8_t bitMask) {
Vec32c mask = getBitmapMask<V>();
Vec32c v1(bitMask);
v1 = v1 & mask;
return ((V)v1 == (V)mask);
}

CreateFile Failed: 5

I'm new in windows driver.
I downloaded this sample and fixed nothing but a report descriptor like this.
HID_REPORT_DESCRIPTOR G_DefaultReportDescriptor[] = {
0x06, 0x00, 0xFF, // USAGE_PAGE (Vender Defined Usage Page)
0x09, 0x01, // USAGE (Vendor Usage 0x01)
0xA1, 0x01, // COLLECTION (Application)
0x85, CONTROL_FEATURE_REPORT_ID, // REPORT_ID (1)
0x09, 0x01, // USAGE (Vendor Usage 0x01)
0x15, 0x00, // LOGICAL_MINIMUM(0)
0x26, 0xff, 0x00, // LOGICAL_MAXIMUM(255)
0x75, 0x08, // REPORT_SIZE (0x08)
//0x95,FEATURE_REPORT_SIZE_CB, // REPORT_COUNT
0x96, (FEATURE_REPORT_SIZE_CB & 0xff), (FEATURE_REPORT_SIZE_CB >> 8), // REPORT_COUNT
0xB1, 0x00, // FEATURE (Data,Ary,Abs)
0x09, 0x01, // USAGE (Vendor Usage 0x01)
0x75, 0x08, // REPORT_SIZE (0x08)
//0x95,INPUT_REPORT_SIZE_CB, // REPORT_COUNT
0x96, (INPUT_REPORT_SIZE_CB & 0xff), (INPUT_REPORT_SIZE_CB >> 8), // REPORT_COUNT
0x81, 0x00, // INPUT (Data,Ary,Abs)
0x09, 0x01, // USAGE (Vendor Usage 0x01)
0x75, 0x08, // REPORT_SIZE (0x08)
//0x95,OUTPUT_REPORT_SIZE_CB, // REPORT_COUNT
0x96, (OUTPUT_REPORT_SIZE_CB & 0xff), (OUTPUT_REPORT_SIZE_CB >> 8), // REPORT_COUNT
0x91, 0x00, // OUTPUT (Data,Ary,Abs)
0xC0, // END_COLLECTION
};
to
HID_REPORT_DESCRIPTOR G_DefaultReportDescriptor[] = {
0x05,0x01, // USAGE_PAGE (Generic Desktop)
0x09,0x02, // USAGE (Mouse)
0xA1,0x01, // COLLECTION (Application)
0x85,0x01, // REPORT_ID (1)
0x09,0x01, // USAGE (Pointer)
0xA1,0x00, // COLLECTION (Physical)
0x05,0x09, // USAGE Page (Buttons)
0x19,0x01, // USAGE Minimum (01)
0x29,0x03, // USAGE Maximum (03)
0x15,0x00, // LOGICAL_MINIMUM(0)
0x25,0x01, // LOGICAL_MAXIMUM(1)
0x95,0x03, // REPORT_COUNT (3)
0x75,0x01, // REPORT_SIZE (1)
0x81,0x02, // Input (Data, Variable, Absolute)
0x95,0x01, // REPORT_COUNT (1)
0x75,0x05, // REPORT_SIZE (5)
0x81,0x03, // Input (Constant)
0x05,0x01, // USAGE_PAGE (Generic Desktop)
0x09,0x30, // Usage (X)
0x09,0x31, // Usage (Y)
0x15,0x81, // LOGICAL_MINIMUM(-127)
0x25,0x7F, // LOGICAL_MAXIMUM(127)
0x75,0x08, // REPORT_SIZE (8)
0x95,0x02, // REPORT_COUNT (2)
0x81,0x06, // Input (Data, Variable, Relative)
0xC0, // END_COLLECTION
0xC0 // END_COLLECTION
};
The results:
1. Successfully installed as a HID mouse.
2. Running testApp, CreateFile Failed like this.
....looking for our HID device
Error: CreateFile failed: 5
Failure: Could not find our HID device
Please help me. I couldn't figure out why this happened.

Mifare read APDU command recived 63 00

All!
I'm trying to read data from mifare card 1k.
to get ID
I send: 0xFF 0xCA 0x00 0x00 0x00
Recive: 0x00 0x00 0x00 0x00 0x00 0x00 - ??? it's normal?
to load auth key to reader
I send: 0xFF 0x82 0x00 0x00 0x06 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF
Recive: 90 00 - it's ok
to authenticate in block 01
I send: 0xFF 0x86 0x00 0x00 0x05 0x01 0x00 0x01 0x60 0x00
Recive: 90 00 - it's ok
to read data from block 01
I send: 0xFF 0xB0 0x00 0x01 0x0F
Recive: 63 00 - how a understand it's authentication error
I can't understand - why?
My code:
#include "stdafx.h"
#include "Winscard.h"
LPTSTR pmszReaders = NULL;
LPTSTR pmszCards = NULL;
LPTSTR pReader;
LPTSTR pCard;
LONG lReturn, lReturn2;
DWORD cch = SCARD_AUTOALLOCATE;
SCARDCONTEXT hSC;
SCARD_READERSTATE readerState;
LPCTSTR readerName = L"ACS ACR1222 1S Dual Reader 0";
SCARDHANDLE hCardHandle;
DWORD dwAP;
BYTE pbRecv[50];
DWORD dwRecv;
BYTE cmdGetData[] = {0xFF, 0xCA, 0x00, 0x00, 0x00};
BYTE cmdLoadKey[] = {0xFF, 0x82, 0x00, 0x00, 0x06, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
BYTE cmdAuthBlock01[] = {0xFF, 0x86, 0x00, 0x00, 0x05, 0x01, 0x00, 0x01, 0x60, 0x00};
BYTE cmdReadBlock01[] = {0xFF, 0xB0, 0x00, 0x01, 0x0F};
int _tmain(int argc, _TCHAR* argv[]) {
lReturn = SCardEstablishContext(SCARD_SCOPE_USER, NULL, NULL, &hSC);
if ( SCARD_S_SUCCESS != lReturn )
printf("Failed SCardEstablishContext\n");
else {
lReturn = SCardListReaders(hSC, NULL, (LPTSTR)&pmszReaders, &cch );
if (lReturn != SCARD_S_SUCCESS) {
printf("Failed SCardListReaders\n");
} else {
pReader = pmszReaders;
while ( '\0' != *pReader ) {
printf("Reader: %S\n", pReader );
pReader = pReader + wcslen((wchar_t *)pReader) + 1;
}
}
memset(&readerState,0,sizeof(readerState));
readerState.szReader = pmszReaders;
lReturn = SCardConnect( hSC, pmszReaders, SCARD_SHARE_EXCLUSIVE, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &hCardHandle, &dwAP );
if ( SCARD_S_SUCCESS != lReturn ) {
printf("Failed SCardConnect\n");
system("pause");
exit(1);
} else {
printf("Success SCardConnect\n");
switch ( dwAP ) {
case SCARD_PROTOCOL_T0:
printf("Active protocol T0\n");
break;
case SCARD_PROTOCOL_T1:
printf("Active protocol T1\n");
break;
case SCARD_PROTOCOL_UNDEFINED:
default:
printf("Active protocol unnegotiated or unknown\n");
break;
}
}
lReturn = SCardTransmit(hCardHandle, SCARD_PCI_T1, cmdGetData, sizeof(cmdGetData), NULL, pbRecv, &dwRecv);
if ( SCARD_S_SUCCESS != lReturn ) {
printf("Failed SCardTransmit\n");
} else {
printf("Success SCardTransmit\n");
printf("Read %u bytes\n", dwRecv);
for(byte i=0;i<dwRecv;i++) {
printf("%x ", pbRecv[i]);
}
printf("\n");
}
lReturn = SCardTransmit(hCardHandle, SCARD_PCI_T1, cmdLoadKey, sizeof(cmdLoadKey), NULL, pbRecv, &dwRecv);
if ( SCARD_S_SUCCESS != lReturn ) {
printf("Failed SCardTransmit\n");
} else {
printf("Success SCardTransmit\n");
printf("Read %u bytes\n", dwRecv);
for(byte i=0;i<dwRecv;i++) {
printf("%x ", pbRecv[i]);
}
printf("\n");
}
lReturn = SCardTransmit(hCardHandle, SCARD_PCI_T1, cmdAuthBlock01, sizeof(cmdAuthBlock01), NULL, pbRecv, &dwRecv);
if ( SCARD_S_SUCCESS != lReturn ) {
printf("Failed SCardTransmit\n");
} else {
printf("Success SCardTransmit\n");
printf("Read %u bytes\n", dwRecv);
for(byte i=0;i<dwRecv;i++) {
printf("%x ", pbRecv[i]);
}
printf("\n");
}
lReturn = SCardTransmit(hCardHandle, SCARD_PCI_T1, cmdReadBlock01, sizeof(cmdReadBlock01), NULL, pbRecv, &dwRecv);
if ( SCARD_S_SUCCESS != lReturn ) {
printf("Failed SCardTransmit\n");
} else {
printf("Success SCardTransmit\n");
printf("Read %u bytes\n", dwRecv);
for(byte i=0;i<dwRecv;i++) {
printf("%x ", pbRecv[i]);
}
printf("\n");
}
}
lReturn = SCardDisconnect(hCardHandle, SCARD_LEAVE_CARD);
if ( SCARD_S_SUCCESS != lReturn ) {
printf("Failed SCardDisconnect\n");
} else {
printf("Success SCardDisconnect\n");
}
system("pause");
return 0;
}
Can anyone explain why i got 63 00?
Thanks.
Afair your read command has to be: "0xFF, 0xB0, 0x00, BLOCK, 0x10". You send buffer length 0F - which is decimal 15 - but you have to read 16 Byte, which is 0x10.
Hope this helps
In Mifare Classic 1K tags There are 16 Sectors and each Sectors contains 4 Blocks and each block contains 16 bytes.
Sector 0 contains Block (0,1,2,3)
Sector 1 contains Block (4,5,6,7)
Sector 2 contains Block (8,9,10,11)
Sector 3 contains Block (12,13,14,15)....
Before Reading or writing from a block You must have to Authenticate its corresponding Sector using Key A or Key B of that sector. When Authentication is complete then you can read or write.
using this command you can authenticate sector 0 using KEY A(60)
byte[] authenticationByte = new byte[10];
authenticationByte = new byte[] { (byte) 0xFF, (byte) 0x86, (byte) 0x00,
(byte) 0x00, (byte) 0x05, (byte) 0x00,(byte) 0x00, (byte) 0x04,
(byte) 0x60,(byte) 0x00 };
When Authentication is succes then you will get 90 00. That is Success message. Else response is 63 00 , that means authentication failed. When Authentication complete then you can read block (0,1,2,3) cause sector 0 contains 4 block and those are block (0,1,2,3).
Here your problem is you are authenticating Sector 1 but trying to read data from Sector 0's blocks.
For more details you can read this Answer.
Sorry for bad English

crc16 implementation java

I am having problems with calculating CRC-16 implementation of a byte array in java. Basically I am trying to send bytes to a RFID that starts writing to a tag. I can see the checksum value of array by looking tcpdump command on mac. But my goal is to generate it by myself. Here is my byte array which should generate 0xbe,0xd9:
byte[] bytes = new byte[]{(byte) 0x55,(byte) 0x08,(byte) 0x68, (byte) 0x14,
(byte) 0x93, (byte) 0x01, (byte) 0x00, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x06,
(byte) 0x00, (byte) 0x00, (byte) 0x01, (byte) 0x00,
(byte) 0x13, (byte) 0x50, (byte) 0x00, (byte) 0x00,
(byte) 0x00, (byte) 0x22, (byte) 0x09, (byte) 0x11};
0x55 is the header. As the documentation says it will be excluded.
Whenever I try this array on java (with 0xbe,0xd9), RFID works. My problem is the generating of those checksum values. I searched almost entire web but no chance. I couldn't find any algorithm that produces 0xbe,0xd9.
Any idea is most welcome for me. Thanks in advance.
edit: here is the protocol that provided with rfid
I'm not really sure if this is the correct translation in Java of the C crc16 algorithm....
but it shows the correct result for your example!
Please compare other results with Mac's CRC16 and stress-test it before using it.
public class Crc16 {
public static void main(String... a) {
byte[] bytes = new byte[] { (byte) 0x08, (byte) 0x68, (byte) 0x14, (byte) 0x93, (byte) 0x01, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x06, (byte) 0x00, (byte) 0x00, (byte) 0x01,
(byte) 0x00, (byte) 0x13, (byte) 0x50, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x22, (byte) 0x09,
(byte) 0x11 };
byte[] byteStr = new byte[4];
Integer crcRes = new Crc16().calculate_crc(bytes);
System.out.println(Integer.toHexString(crcRes));
byteStr[0] = (byte) ((crcRes & 0x000000ff));
byteStr[1] = (byte) ((crcRes & 0x0000ff00) >>> 8);
System.out.printf("%02X\n%02X", byteStr[0],byteStr[1]);
}
int calculate_crc(byte[] bytes) {
int i;
int crc_value = 0;
for (int len = 0; len < bytes.length; len++) {
for (i = 0x80; i != 0; i >>= 1) {
if ((crc_value & 0x8000) != 0) {
crc_value = (crc_value << 1) ^ 0x8005;
} else {
crc_value = crc_value << 1;
}
if ((bytes[len] & i) != 0) {
crc_value ^= 0x8005;
}
}
}
return crc_value;
}
}
There is a CRC16 implementation in the Java runtime (rt.jar) already.
Please see grepcode for the source.
You will probably be able to see it in your IDE if you search for CRC16:
Maybe are you looking for this?
Crc16 in java
I use the same array (variable "table") in this method:
public Integer computeCrc16(byte[] data) {
int crc = 0x0000;
for (byte b : data) {
crc = (crc >>> 8) ^ table[((crc ^ b) & 0xff)];
}
return (int) crc;
}
if you want ASCII character then change
byte[] bytes="02303131313233343031303345303903".getBytes();
Below is correct answer for HEX input ,
byte[] bytes = hexStringToByteArray("02303131313233343031303345303903");
public class CRC16 {
public static void main(String[] args) {
int[] table = {
0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040,
};
byte[] bytes = hexStringToByteArray("02303131313233343031303345303903"); // for HEX
int crc16 = 0x0000;
for (byte b : bytes) {
crc16=table[(crc16 ^ b) & 0xff] ^ (crc16 >> 8);
}
crc16= crc16 & 0xFFFF;
System.out.println("CRC16 = " +Integer.toHexString(crc16));
}
public static byte[] hexStringToByteArray(String s) {
int len = s.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)+ Character.digit(s.charAt(i+1), 16));
}
return data;
}
}

Resources