I try to send command to USB device. I have to convert this command : DA AD 02 74 00 BFDB to byte array. I started like this :
private static final byte[] send = new byte[] {
(byte)0xda,(byte)0xad, // const
// command
};
But I don't know what's next. How should I write 02 as a byte, 74 and so on ? Please, help.
Just continue the same way you did before:
private static final byte[] send = new byte[] {
(byte)0xDA, (byte)0xAD, (byte)0x02, (byte)0x74,
(byte)0x00, (byte)0xBF, (byte)0xDB
};
To simplify the syntax, you could also take a look at this answer and then use a string like "DAAD027400BFDB" or even improve the code from that answer to ignore spaces, so you can keep the syntax you had in your question.
Related
I am trying to get a weight value from a set of weighing scales over USB. It should be quite simple, according to their doc, I need to send two bytes the letter "W" and the carriage return byte. It then responds with 16 bytes of data representing the current weight on the device.
The device has 1 interface, 2 endpoints with a max packet size of 64. I believe I must use the bulkTransfer function as the endpoint types are USB_ENDPOINT_XFER_BULK.
Here is the doc graphic:
How exactly should I send this request and receive the response? My attempt is below, and the response is simply a Start of Heading symbol, then a back quote symbol "`" and a load of zeroes. I have tried to run the code on a polling loop or just a single request but get the same result.
val connection = usbManager.openDevice(scales)
val intf: UsbInterface = scales.getInterface(0)
connection.claimInterface(intf, true)
val endpointReadIn = intf.getEndpoint(0)
val endpointWriteOut = intf.getEndpoint(1)
val bytes = byteArrayOf(0x57.toByte(), 0x0D.toByte())
thread {
val request = connection.bulkTransfer(endpointWriteOut, bytes, bytes.size, 0)
Log.d(TAG, "Was request to write successful? $request")
val buffer = ByteArray(16)
val response = connection.bulkTransfer(endpointReadIn, buffer, buffer.size, 0)
Log.d(TAG, "Was response from read successful? $response")
val responseString = StringBuilder()
for (i in 0..15) {
responseString.append(buffer[i])
}
Log.d(TAG, "Response: $responseString")
val hex = toHexString(buffer)
Log.d(TAG, "Hex: $hex")
connection.close()
}
fun fromHexString(hexString: String): ByteArray {
val len = hexString.length / 2
val bytes = ByteArray(len)
for (i in 0 until len) bytes[i] = hexString.substring(2 * i, 2 * i + 2).toInt(16).toByte()
return bytes
}
Output:
Was request to write successful? 2
Was response from read successful? 2
Response: 19600000000000000
Hex: 01 60 00 00 00 00 00 00 00 00 00 00 00 00 00 00
There was a couple of missing pieces here. I think the big one was not specifying the baud rate, data bit, stop bit and parity which are all achieved via the controlTransfer function.
In the end I couldn't get it to work myself despite getting successful responses while setting these. Then I found this lovely library which is compatible with this RS232 device and it works well. I just need to specify the vid / pid to get a custom driver using the FtdiSerialDriver class.
Which is the right way to print GB pound symbol in thermal printer?
I am using the following code for writing printer:
String pound = "\u00a3";
opstream = BluetoothPrinter.btSocket.getOutputStream();
//Tried
outputStream.write(pound.getBytes(StandardCharsets.UTF_8));
//Tried
outputStream.write(pound.getBytes(Charset.forName("UTF-8")));
I have tried like £ also. What is the alternative for this in a thermal printer?
It's indeed 00 A3 eg. in code-page 1252 or 437.
To switch, that's ESC t n where n equals 16 eg. for code-page 1252.
Select character code table.
ASCII ESC t n
Hex. 1B 74 0F
Decimal 27 116 16
This should encode it into a matching format:
String gbp = "£";
byte[] b = gbp.getBytes(Charset.forName("Windows-1252"));
The output b should in every case be 00 A3 and the printer needs to know which code-page it is. Unless the printer won't be switched to a code-page which has the £, it won't print a £, no matter which value it is being represented by (except as graphics). See the ESC/POS Mode Command Specifications, page 4-47. In unicode it's also U+00A3 (which the printer likely won't support).
The whole sequence would be: 1B 74 0F 00 A3
and to switch back to default code-page: 1B 74 00
Consult your printer's manual, which code-pages it even supports (also the 0F might vary).
Please try to this:
String pound = "£ 20.00";
outputStream.write(BitmapAsEuro(pound));
public byte[] BitmapAsEuro(String poundValue){
Bitmap image = Bitmap.createBitmap(600, 200, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(image);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setTextSize(26);
paint.setColor(Color.BLACK);
paint.setTextSize(26);
paint.setFlags(Paint.EMBEDDED_BITMAP_TEXT_FLAG);
canvas.drawText(poundValue,0,60,paint);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
image.compress(Bitmap.CompressFormat.PNG, 100, stream);
byte[] byteArray = stream.toByteArray();
image.recycle();
return byteArray;
}
I found this
String pound = "€";
String codeL = "GBK";
opstream = BluetoothPrinter.btSocket.getOutputStream();
outputStream.write(pound.getBytes(codeL));
I am trying to implement an OTP generator for Blackberry OS10. I already use the reference implementation on Android side, you can find it here:
So I would like to convert it to C++ / QNX code and I have some troubles with hexadecimal conversion...
In java:
private static byte[] hexStr2Bytes(String hex){
// Adding one byte to get the right conversion
// Values starting with "0" can be converted
byte[] bArray = new BigInteger("10" + hex,16).toByteArray();
// Copy all the REAL bytes, not the "first"
byte[] ret = new byte[bArray.length - 1];
for (int i = 0; i < ret.length; i++)
ret[i] = bArray[i+1];
return ret;
}
In QNX:
QByteArray msg = QByteArray::fromHex(m.toLocal8Bit());
Problem is "m" start with '00' and so my final msg array is 0 length...
For example I try to encode the hex qstring:0000000002ca4e32
In blackberry: m=""
In Android: m="?M?"
So you can someone explain me how to deal with such a conversion ?
Thanks!
What I would do is to translate your Java function to plain C++, i.e. not QT format. Then adapt data type to QT.
I am trying to send some data to the Nexus 4 through NFC (i.e. the card emulation mode). I tried a number of the command APDUs such as writing and updating APDUs, but I couldn't get them to work.
What I am trying to say is, I want to send some data (that is not the AID) to the phone after the select APDU command.
Thanks in advance,
Bader
The HCE emulated card will understand exactly those commands that your HCE app's APDU service processes. So, for instance, if your HCE service's processCommandApdu() callback method looks like this:
final static byte[] SW_NO_ERROR = new byte[]{ (byte)0x90, (byte)0x00 };
final static byte[] SW_INCORRECT_P1P2 = new byte[]{ (byte)0x6A, (byte)0x86 };
final static byte[] SW_INS_NOT_SUPPORTED = new byte[]{ (byte)0x6D, (byte)0x00 };
final static byte[] SW_ERR_UNKNOWN = new byte[]{ (byte)0x6F, (byte)0x00 };
#Override
public byte[] processCommandApdu(byte[] apdu, Bundle extras) {
if (apdu.length >= 4) {
if ((apdu[1] == (byte)0xA4) && (apdu[2] == (byte)0x04)) {
// SELECT APPLICATION
return SW_NO_ERROR;
} else if ((apdu[1] == (byte)0xCA) && (apdu[2] == (byte)0x02)) {
// GET DATA (SIMPLE TLV)
switch (apdu[3] & 0x0FF) {
case 0x001:
return new byte[]{ apdu[3], (byte)0x02, (byte)0x01, (byte)0x00, (byte)0x90, (byte)0x00 };
case 0x002:
return new byte[]{ apdu[3], (byte)0x02, (byte)0x12, (byte)0x34, (byte)0x90, (byte)0x00 };
case 0x003:
return new byte[]{ apdu[3], (byte)0x06, (byte)0xAA, (byte)0xBB, (byte)0xCC, (byte)0xDD, (byte)0xEE, (byte)0xFF, (byte)0x90, (byte)0x00 };
default:
return SW_INCORRECT_P1P2;
}
} else {
return SW_INS_NOT_SUPPORTED;
}
}
return SW_ERR_UNKNOWN;
}
Your HCE app would understand the following command APDUs:
SELECT APPLICATION (by AID)
00 A4 04 xx ...
GET DATA for data object 0201
00 CA 02 01 00
GET DATA for data object 0202
00 CA 02 02 00
GET DATA for data object 0203
00 CA 02 03 00
Other commands will result in various errors.
I'm trying to read a smartcard via my LG P710 Optimus L7 2.
I'm following this tutorial
I can select the "1PAY.SYS.DDF01" directory
I can select the Application
But I can't perform an "GET PROCESSING OPTIONS"
It always result in an 6700 error (Lc or Le wrong)
here is my code
NfcAdapter mNFCAdapter;
Intent intent;
PendingIntent pendingIntent;
private TextView mTextView;
String[][] techList;
IntentFilter[] filters = new IntentFilter[3];
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mTextView = (TextView) findViewById(R.id.title);
mNFCAdapter = NfcAdapter.getDefaultAdapter(this);
intent = new Intent(getApplicationContext(), getClass());
intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
pendingIntent = PendingIntent.getActivity(getApplicationContext(), 0, intent, 0);
techList = new String[][]{
new String[]
{ MifareClassic.class.getName() },
new String[]
{ IsoDep.class.getName() }
};
filters[0] = new IntentFilter();
filters[0].addAction(NfcAdapter.ACTION_NDEF_DISCOVERED);
filters[0].addCategory(Intent.CATEGORY_DEFAULT);
// add type of tag data you want to have - here ndef -> plain text
try {
filters[0].addDataType(MIME_TEXT_PLAIN);
} catch (MalformedMimeTypeException e) {
e.printStackTrace();
}
filters[1] = new IntentFilter();
filters[1].addAction(NfcAdapter.ACTION_TAG_DISCOVERED);
filters[1].addCategory(Intent.CATEGORY_DEFAULT);
filters[2] = new IntentFilter();
filters[2].addAction(NfcAdapter.ACTION_TECH_DISCOVERED);
filters[2].addCategory(Intent.CATEGORY_DEFAULT);
}
#Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
String action = intent.getAction();
mTextView.setText(action);
Toast.makeText(getApplicationContext(), action, Toast.LENGTH_SHORT).show();
Tag tagFromIntent = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
IsoDep tagIsoDep;
if((tagIsoDep = IsoDep.get(tagFromIntent)) != null)
if(handleIsoDep(tagIsoDep))
return;
}
private boolean handleIsoDep(IsoDep tag){
try{
tag.connect();
tag.setTimeout(20);
byte[] responseAPDU;
//2PAY.SYS.DDF01
byte[] select_Dir = new byte[]{
(byte)0x00, (byte)0xa4, (byte)0x04, (byte)0x00, (byte)0x0e,
(byte)0x32, (byte)0x50, (byte)0x41, (byte)0x59, (byte)0x2e,
(byte)0x53, (byte)0x59, (byte)0x53, (byte)0x2e, (byte)0x44,
(byte)0x44, (byte)0x46, (byte)0x30, (byte)0x31
};
//Select CC Applet
byte[] select_Applet = new byte[]{
(byte)0x00, (byte)0xa4, (byte)0x04, (byte)0x00, (byte)7,
(byte)0xa0, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x04,
(byte)0x30, (byte)0x60
};
//Send GET PROCESSING OPTIONS command
byte[] Send_Get = new byte[]{
(byte)0x80,(byte)0xA8,(byte)0x00,(byte)0x00,(byte)0x02,
(byte)0x83,(byte)0x00,
(byte)0x00
};
responseAPDU = tag.transceive(select_Dir);
mTextView.setText(mTextView.getText() + handleResponse(responseAPDU));
this returns the APDU-Statusword 9000 -> success
responseAPDU = tag.transceive(select_Applet);
mTextView.setText(mTextView.getText() + handleResponse(responseAPDU));
this returns the APDU-Statusword 9000 -> success
responseAPDU = tag.transceive(Send_Get);
mTextView.setText(mTextView.getText() + handleResponse(responseAPDU));
and this one is making problems: it returns 6700 -> wrong Lc or Le
mTextView.setText(mTextView.getText() + "\n\nDone");
tag.close();
} catch (IOException e) {
e.printStackTrace();
return false;
}
return true;
}
The function handleResponse just parses the "responseAPDU" from Binary to Hex an highlights the Statusword
Can anybody tell my what is going wrong?
or just help me out?
PS sry for bad english ;)
As response to my application-select I get:
6f298407a0000000043060a51e50074d41455354524f5f2d046465656e9f38039f5c08bf0c059f4d020b0a9000
6F -> FCI Template 29
84 -> DF Name 07 A0 00 00 00 04 30 60
A5 -> FCI Properietary Template 1E
50 -> Application Lable 07 4D 41 45 53 54 52 4F 5F 2D 04 64 65 6E
9F38 -> PDOL 03 9F 5C 08
BF0C -> FCI Issuer Data 05
9F4D -> Log Entry 02 0B
0A Additional Issuer Data
But I don't know what ive to insert into the Data fild from the GET PROCESSING OPTIONS.
Iv'e red the guidelines in EMV Book 3, section "5.4 Rules for Using a Data Object List (DOL)".
So do I just have to set the data field 83 03 9F 5C 08
and Lc = 5?
In order to help you, the entire ADPU dialog (commands/responses) would be needed.
However, based on your code : hardcoding your select_Dir and select_Applet commands is correct, but you can't hardcode the GET PROCESSING OPTIONS command whose syntax depends on the response of the card (ICC) to your select_Applet command.
EMV 4.3 Book 1, "Table 45: SELECT Response Message Data Field (FCI) of an ADF", explains that a successful card response to the SELECT command contains a "Processing Options Data Object List" (PDOL, tag 9F38). That's the list of fields required by the card to process the transaction (ex : amount, ...). These fields values are to be returned to the card by the terminal (your phone) through the GET PROCESSING OPTIONS command data field (tag 83), as documented in EMV 4.3 book 3, section "6.5.8.3 Data Field Sent in the Command Message" :
The data field of the command message is a data object coded according to the PDOL provided by the ICC, as defined in section 5.4, and is introduced by the tag '83'. When the data object list is not provided by the ICC, the terminal sets the length field of the template to zero. Otherwise, the length field of the template is the total length of the value fields of the data objects transmitted to the ICC.
Knowing that :
Your selected AID (A0 00 00 00 04 30 60) is a Mastercard Maestro one, which is unlikely to have an empty PDOL
But your GET PROCESSING OPTIONS command does not list any value in its data field
You probably have a mismatch between the length of your GET PROCESSING OPTIONS data field and the total length of the fields asked by the card in the PDOL, hence the 6700 checking error returned by the card (EMV Book 1, "Table 33: GET RESPONSE Error Conditions").
You have identified the PDOL requested by the card as : 9F38 -> 03 9F 5C 08.
The 03 tells you the PDOL is 3 bytes long. 9F5C is the tag of the requested field, 08 is the length of the field value that is to be returned by the phone.
Tag 9F5C is defined in EMV Contactless 2.3 Book C2 kernel 2 specification, section "A.1.59 DS Requested Operator ID". The DS Requested Operator ID is defined as
Contains the Terminal determined operator identifier for data
storage. It is sent to the Card in the GET PROCESSING
OPTIONS command.
I'm not familiar with this tag, so I can't tell you what a proper value is.
However, here is what the data field of the GET PROCESSING OPTIONS command should look like, assuming a DS Requested Operator ID has value 01 02 03 04 05 06 07 08, and given the Data Object List formatting guidelines in EMV Book 3, section "5.4 Rules for Using a Data Object List (DOL)" :
83 08 01 02 03 04 05 06 07 08
and Lc = 10