android nfc - mifare classic 1k Increment operation tranceive failed - android

I want to store an integer value and increment or decrement it with API function.
I have readed the card with an utility and this is the content of block 5:
It seems that there is not any value block.
This is my code:
int sector = 5;
this.mClassic.connect();
boolean success = this.mClassic.authenticateSectorWithKeyA(sector, MifareClassic.KEY_DEFAULT );
if(success){
int firstBlock = mClassic.sectorToBlock(sector);
Log.i("MIFARE CLASSIC", "first block of the given sector:" + firstBlock);
//set the value = 0
byte[] zeroValue = {0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,0,0,};
//save this value
mClassic.writeBlock(firstBlock, zeroValue);
//increment the value and store it
this.mClassic.increment(firstBlock, 1);
this.mClassic.transfer(firstBlock);
// read the incremented value by converting it in integer from bytearray
b = readSector(firstBlock);
data = b.toByteArray();
value = 0;
for (int i = 0; i < data.length; i++)
{
value = (value << 8) + (data[i] & 0xff);
}
Log.i("MIFARE CLASSIC", "After increment " + value);
}
mClassic.close();
I have returned tranceive failed at this.mClassic.increment(firstBlock, 1);
I don't understand what I am doing wrong...who can help me?
Thanks a lot.

The Mifare 1K does a data-integrity check on the value-block. Your zeroValue block is unfortunately not a valid value-block. Therefore the tag complains and you get an error.
You can find the format in the Mifare Datasheets (worth reading!)
However, the format of the value-block is simple:
byte 0..3: 32 bit value in little endian
byte 4..7: copy of byte 0..3, with inverted bits (aka. XOR 255)
byte 8..11: copy of byte 0..3
byte 12: index of backup block (can be any value)
byte 13: copy of byte 12 with inverted bits (aka. XOR 255)
byte 14: copy of byte 12
byte 15: copy of byte 13
If you store your 32 bit value using the format above, your code will very likely just work.

Related

How to write byte array with BluetoothGattCharacteristic in BLE?

This code is working and LED is also turning off.
byte cmd[] = {(byte) 0xff};
mWrChar.setValue(cmd);
mBleGatt.writeCharacteristic(mWrChar);
But I want to pass "0x0801000" as byte array in BluetoothGattCharacteristic, how to do this?
Similar nRF Connect application.
You can just pass an array to the variable cmd. But you need to know if the byte array is MSO (most significant octet) -> LSO (least significant octet) or LSO -> MSO. Typically, characteristics use LSO -> MSO, which means that the first octet in your byte array is the least significant octet.
In the concrete case, note that your characteristic is composed of four bytes: 0x08|01|00|00
Then you have:
MSO -> LSO: 0x08|01|00|00 -> {0x08, 0x01, 0x00, 0x00}
LSO -> MSO: 0x08|01|00|00 -> {0x00, 0x00, 0x01, 0x08}
Check out which one is relevant in your case, or try out both and see what happens. Your code will then be something like this (I assume LSO -> MSO):
byte[] cmd = {0x00, 0x00, 0x01, 0x08};
mWrChar.setValue(cmd);
mBleGatt.writeCharacteristic(mWrChar);
For sending the byte array, this is how I did it (probably from the BluetoothLeGatt sample):
characteristic.setValue((integerToSend), BluetoothGattCharacteristic.FORMAT_UINT8, 0);
characteristic.setValue((integerToSend >> 8), BluetoothGattCharacteristic.FORMAT_UINT8, 1);
The last parameter specifies the byte field in the of the characteristic. I prefer to set each field manually. With the first line I populate field 0 with the first half of my integer. With the second line I populate field 1 with the second half of my integer. You can then populate each bye field individually, up to 18 bytes per characteristic (I think)
This is the method I use to format a hex data, like yours 0x08010000, as a byte array. Then you can write it to characteristics.
public static byte[] hexToByteData(String hex)
{
byte[] convertedByteArray = new byte[hex.length()/2];
int count = 0;
for( int i = 0; i < hex.length() -1; i += 2 )
{
String output;
output = hex.substring(i, (i + 2));
int decimal = (int)(Integer.parseInt(output, 16));
convertedByteArray[count] = (byte)(decimal & 0xFF);
count ++;
}
return convertedByteArray;
}
Hope it helps.

Android Bluetooth and sending an unsigned Hex value

I am currently working on a Android application that takes values from a text box and then sends it over bluetooth, all operations are in Hex values.
I have a convertion method that can take the string make give me the unsigned integer for the string, but once i place it in the byte array it becomes signed and the board that receives this cannot do signed hex.
This is how the process works:
//sample string to send
String toSend = "0BDD";
//sending the byte[] to the board over bluetooth
btOutputStream.write(SendByteData(toSend));
// --- perform the conversion to byte[] ---
public static byte[] SendByteData(String hexString)
{
byte[] sendingThisByteArray = new byte[hexString.length()/2];
int count = 0;
for( int i = 0; i < hexString.length() - 1; i += 2 )
{
//grab the hex in pairs
String output = hexString.substring(i, (i + 2));
//convert the 2 characters in the 'output' string to the hex number
int decimal = (int)(Integer.parseInt(output, 16)) ;
//place into array for sending
sendingThisByteArray[count] = (byte)(decimal);
Log.d(TAG, "in byte array = " + sendingThisByteArray[count]);
count ++;
}
return sendingThisByteArray;
}
The issue is as follows:
When the for for loop runs through the string and picks up "0B" it correctly gives me integer 11; then when the loop runs through "DD" it give me integer 221 which is also correct
When I perform the operation of
sendingThisByteArray[count] = (byte)(decimal);
11 gets correctly placed in sendingThisByteArray[0]
but for sendingThisByteArray[1] the number 221 gets changed to -35
I know that Java has signed bytes.. is there a way to put/place/change the byte array so i can place and number 221 or any other value higher than 127?
your help is greatly appreciated
You can convert from a signed integer to unsigned byte like this, by binary AND'ing it with 0xFF:
sendingThisByteArray[count] = (byte)(decimal & 0xFF);
This way you can send values from 0 to 255
I found the problem, when i tried to do unsigned hex into a byte array it would always put a sign, i had to create single byte to retain the unsigned hex
int zeroA = (int)(Integer.parseInt("0D", 16));
sendStream.write(unsignedToBytes((byte) zeroA));

How to get byte by byte from byte array

I am getting response from server in string format like
V1YYZZ0x0000010x0D0x00112050x0C152031962061900x0D410240x0E152031962061900x0F410240x1021TATADOCOMOINTERNET101
Then I am converting it in to byte array because i need to get value from this byte by byte.
I tried to use
Arrays.copyOfRange(original,
from , to);
but it work on index basis not on byte basis.
I also tried following solution but it also truncating String(if I use string instead of byte[]) on length basis.
public static String truncateWhenUTF8(String s, int maxBytes) {
int b = 0;
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
// ranges from http://en.wikipedia.org/wiki/UTF-8
int skip = 0;
int more;
if (c <= 0x007f) {
more = 1;
} else if (c <= 0x07FF) {
more = 2;
} else if (c <= 0xd7ff) {
more = 3;
} else if (c <= 0xDFFF) {
// surrogate area, consume next char as well
more = 4;
skip = 1;
} else {
more = 3;
}
if (b + more > maxBytes) {
return s.substring(0, i);
}
b += more;
i += skip;
}
return s;
}
I know how to calculate string in byte length but it giving only full string length in byte like
Here is how I need to extract packet on byte basis.
Above codes and parameters is only example. I need to get byte by byte from string/byte array.
I searched lot but didn't get any solution or link which I can refer. I am not getting how to split string using byte length because I know byte length for each parameter and for value also.
Please give me any reference or hint.
To determine what is equal to one byte in a String is not trivial. Your String contains bytes in hexadecimal text form: 0x0D (one byte, equal to 13), but also contains values as substrings. For example 1024 can be interpreted as an integer which in this case fits into 2 bytes, but could also be interpreted as a text made up by 4 chars, totaling to 8 bytes.
Anyways, I would split the string using a regular expression, and then further split the parts to length and value:
String message = "V1YYZZ0x0000010x0D0x00112050x0C152031962061900x0D41024"+
"0x0E152031962061900x0F410240x1021TATADOCOMOINTERNET101";
String regex = "(0)(x)(\\w\\w)";
String[] parts = message.split(regex);
Log.d(TAG,"HEADER = "+parts[0]);
for (int i=1; i<parts.length; i++) {
String s = parts[i];
// Only process if it has length > 0
if (s.length()>0) {
String len = "", val = "";
// String s is now in format LVVVV where L is the length, V is the value
if (s.length() < 11) {
// 1 character indicates length, up to 9 contains value
len = s.substring(0, 1);
val = s.substring(1);
} else if (s.length() > 10) {
// 2 characters indicate length, up to 99 contains value
len = s.substring(0, 2);
val = s.substring(2);
} else if (s.length() > 101) {
// 3 characters indicate length, up to 999 contains value
len = s.substring(0, 3);
val = s.substring(3);
}
Log.d(TAG, "Length: " + len + " Value: " + val);
}
}
This produces the following output:
D/Activity: HEADER = V1YYZZ
D/Activity: Length: 0 Value: 001
D/Activity: Length: 1 Value: 1205
D/Activity: Length: 15 Value: 203196206190
D/Activity: Length: 4 Value: 1024
D/Activity: Length: 15 Value: 203196206190
D/Activity: Length: 4 Value: 1024
D/Activity: Length: 21 Value: TATADOCOMOINTERNET101
Then you can check the packages (the first two package in the header is not needed), convert Strings to whatever you would like (e.g. Integer.parseInt(val))
If you explain the structure of the header (V1YYZZ0x0000010x0D0x0011205), I can improve my answer to find the message count.
I think it is doable with Scanner
import java.util.Scanner;
public class Library {
public static void main(String[] args) {
String s = "V1YYZZ0x0000010x0D0x001120"
+ "50x0C152031962061900x0D410240x0E152031962061900x0F410240x1"
+ "021TATADOCOMOINTERNET101";
// Skip first 9? bytes. I'm not sure how you define them
// so I just assumed it is 26 chars long.
s = s.substring(26, s.length());
System.out.println(s);
Scanner scanner = new Scanner(s);
// Use byte as delimiter i.e. 0xDC, 0x00
// Maybe you should use smth like 0x[\\da-fA-F]{2}
// And if you want to know that byte, you should use
// just 0x and get first 2 chars later
scanner.useDelimiter("0x\\w{2}");
// Easily extracted
int numberOfParams = scanner.nextInt();
for (int i = 0; i < numberOfParams; i++) {
String extracted = scanner.next();
// Length of message
int l = extracted.length();
boolean c = getLength(l) == getLength(l - getLength(l));
l -= getLength(l);
l = c ? l : l-1;
System.out.println("length="
+ extracted.substring(0, extracted.length()-l));
System.out.println("message="
+ extracted.substring(extracted.length()-l, extracted.length()));
}
// close the scanner
scanner.close();
}
// Counting digits assuming number is decimal
private static int getLength(int l) {
int length = (int) (Math.log10(l) + 1);
System.out.println("counted length = " + length);
return length;
}
}
We definitely need more information about rules, how string is formed. And what exactly you need to do. This code might be good enough you. And without comments it is really short and simple.
This is not a answer to accessing a byte array byte by byte, but is an answer for the situation in which you find yourself.
Your explanation and description have the appearance of being confused as to what it is that you are really getting from the server (e.g. it is quite hard to represent "V1YYZZ0x0000010x0D0x001120" as a 9 byte field (note it probably ends on the 2, not the 0)). Alternately, that you are using the wrong method to get it from the server, or not getting it as the intended data type.
Your code indicates that you believe that what you are getting is a UTF8 string. The data shown in your question does not appear to indicate that it is intended to be in that format.
Keep in mind when doing something like this that some other programmer had to create structure for the data that you are seeing. They had to define it somewhere with the intent that it be able to be decoded by their intended recipients. Unless there are other considerations (security, minimal bandwidth, etc.), such formats are usually defined in a way that is both easy to encode and decode.
The existence of the multiple "0x"-ASCII-encoded hexadecimal numbers --particularly the single byte representing the parameter (called "varam" in your graphic)-- strongly implies that this data was intended to be interpreted as a ASCII encoded string. While that might not be the case, it should be kept in mind when looking at the problem from a larger perspective.
You are having to put too much effort into decoding the information you are getting from the server. It, probably, should be relatively easy unless there are considerations why it would have intentionally been made difficult.
All of this indicates that the real problem exists in an area for which you have provided us with no information.
Step back:
Think about things like:
How are you receiving this from the server (what function/interface)?
In the call requesting the information from the server is there a way to specify the encoding type be bytes, an ASCII string, or some other format that is easier to deal with than UTF8? At a minimum, it appears to be clear that the data was not intended to be handled as a UTF8 string. There should be a way for you to get it without it having been converted to UTF8.
Also, you should try to find an actual specification for the format of the data. You have not explained much about the source, so it may be you are reverse-engineering something and have no access to specifications.
Basically, it looks like this is a problem where it might be a good idea to step back and ask if you are starting from the point that makes it easiest to solve and if you are headed in the right direction for doing so.
I'm sure I'm missing something obvious...
String.getBytes();
And if you want to process it in order taking defined objects from the array, just wrap using
ByteBuffer.wrap();
The result being something along the lines of:
String s = "OUTPUT FROM SERVER";
byte[] bytes = s.getBytes();
ByteBuffer bb = ByteBuffer.wrap(bytes);
What did I miss from the initial question? :/

Socket Data issue between Android and iOS

I'm facing a bit of an issue trying to communicate with 2 devices through a socket (UDP, but not the issue here...)
One device is Android, the other is iOS.
Here's the Android code to create the Data I'm sending :
int part = 1;
int num = -1;
ByteBuffer bb = ByteBuffer.allocate(20);
bb.order(ByteOrder.nativeOrder());
bb.putChar('R');
bb.putInt(part);
bb.putInt(num);
bb.flip();
byte[] toSend = new byte[bb.remaining()]; // bb.remaining() = 10
bb.get(toSend);
send(toSend);
On iOS, here's the code I use to parse the data I get from the socket
char *sData = (char*)[data bytes];
if (sData[0] == 'R') {
sData += sizeof(char);
int part = 0;
memcpy(&part, sData, sizeof(int));
sData += sizeof(int);
int num = 0;
memcpy(&num, sData, sizeof(int));
}
The data I get is :
part = 256
num = -256
The weird thing is if I change value from the Android device I get :
part = 0 & num = -1 ---> part = 0 & num = -256
part = 1 & num = -1 ---> part = 256 & num = -256
part = 2 & num = -1 ---> part = 512 & num = -256
part = 3 & num = -1 ---> part = 768 & num = -256
As you can see, the value are correct, they are just multiplied by 256, and I can't understand why...
To avoid compatibility issue between Android and iOS (32/64) I avoided the long type, because on
Android long = 8
iOS 32b long = 4
iOS 64b long = 8
Does anybody can see why it is multiplying my value by 256 ?
EDIT 1 :
From iOS to iOS data transfer, it is working fine, so my guess is that the bug is coming from Android.
In Java, your buffer contains this:
char 2 bytes | int 4 bytes | int 4 bytes
Since iOS stores char in one byte, you are reading it as if it were:
char 1 byte | int 4 bytes | int 4 bytes
This also explains why iOS -> iOS works.
[Edit]
To fix, you could use byte in Java.
byte b = (byte) 'R';
Like this:
ByteBuffer bb = ByteBuffer.allocate(20);
bb.order(ByteOrder.nativeOrder());
bb.putByte((byte)'R');
bb.putInt(part);
bb.putInt(num);
bb.flip();
Note though that casting char to byte "loses" the high 8 bits so this will only work for ASCII chars.

Converting sections of byte arrays to integer values

I am currently making an android application which accepts bluetooth measurement from a device. The way the data is packaged is in 4 bytes. I need to get two values out of these bytes.
First value is made up of: 6bit and 7bit of first byte and bit 0 to bit 6 of byte 2
Second values is simpler and consists of the full 3rd byte.
What is a good way to access these bit values, combine them and convert them to integer values? Right now i'm trying to convert from byte array to bitset, and then access individual bits to create new bytes that would then be converted to a integer.
Thanks, and please ask if I am not being clear enough.
I figured it out: I converted the byte array to int using this method
public static int byteArrayToInt(byte[] b, int offset) {
int value = 0;
for (int i = 0; i < 4; i++) {
int shift = (4 - 1 - i) * 8;
value += (b[i + offset] & 0x000000FF) << shift;
}
return value;
}
Then I used the method pokey described. Thanks for your help!
im not sure if i understood your format correctly.
Does this bitmask correspond to your first value?
0xC07F0000
That is bits 16-22,30,31 (zero based indexing used here, i.e. bit 31 is last bit).
Another thing, is your value expected to be signed or unsigned?
Anyway, if it is the way i assume then you can convert it like this with some bitmasks:
unsigned int val = 0xdeadbeef;
unsigned int mask1 = 0xC0000000;
unsigned int mask2 = 0x007F0000;
unsigned int YourValue = (val&mask1)>>23 | (val&mask2)>>16;
Do that in the same way with your other values. Define a bitmask and shift it to the right. Done.
Cheers

Categories

Resources