MCP2200 linux settings - linux

Im want to control MCP2200 in linux.
I found Text Link and set everything.
For example:
I type in console
GP3-1
It will sets pin 3 to 1. But i dont know what to type in console

for controlling the mcp2200 you will need a program doing the stuff for you.
The USBtoUART didn't work for me, maybe you'll have to do some coding yourself - but you can use it to understand how to connect to the mcp2200 hid.
For controlling the IOs, just set up a 16-byte array, filled with the data described here:
http://ww1.microchip.com/downloads/en/DeviceDoc/93066A.pdf
If you want to control some more stuff but gpios, you'll have to do some more - it is possible to control more than just the gpios of the mcp2200 from linux.
I did a little usb trace of the communication of the windows config tool, extracted some informations and - tadaah, there you go with your own pID/vID, Manufacturer and Product strings.
Note: you'll probably need the HIDAPI MikeF was talking about.
First of all, some definitions:
// NOTE: max. string length for manufacturer / product string is 63 bytes!!
// from usb trace of mcp2200 config tool
#define MCP2200_SECRET_CONFIGURE 0x01
#define MCP2200_CFG_PID_VID 0x00
#define MCP2200_CFG_MANU 0x01
#define MCP2200_CFG_PROD 0x02
... and some variables:
unsigned char **mcp2200_manu_string;
unsigned char **mcp2200_prod_string;
The output message for manufacturer string looks like
/* configure manufacturer string (16 x 16 bytes):
* output buffer:
* #0: [01 01 00 16 03 58 00 4B 00 72 00 FF FF FF FF FF]
* | | | | | | | | | | | +-----------+--> Always FF
* | | | | | | +-----+-----+-----------------> Always 00
* | | | | | +-----+-----+--------------------> First 3 Chars of Manufacturer Name / Product Name
* | | | | +-----------------------------------> In #0: 0x03, After #0: 0x00
* | | | +--------------------------------------> (Length (Manufacturer Name) * 2) + 2 (after #0: chars of manufacturer name)
* | | +-----------------------------------------> Counter 0x00 .. 0x0F
* | +--------------------------------------------> MCP2200 Config Bit (MCP2200_CFG_MANU / PROD / VID_PID)
* +-----------------------------------------------> MCP2200_SECRET_CONFIGURE from usb trace
*/
if you put all this in a function, it could look like this:
void prepare_cfg_strings (char* manu, char* prod) {
char manuStr[64];
char prodStr[64];
unsigned int i, k = 0;
unsigned char tmp = 0;
memset (manuStr, 0x00, sizeof(manuStr));
memset (prodStr, 0x00, sizeof(prodStr));
// allocate mcp2200_{manu,prod}_string buffer, 2-dim array with 16 x 16 chars
if (( mcp2200_manu_string = ( unsigned char** )malloc( 16*sizeof( unsigned char* ))) == NULL ) {
// error
}
if (( mcp2200_prod_string = ( unsigned char** )malloc( 16*sizeof( unsigned char* ))) == NULL ) {
// error
}
for ( i = 0; i < 16; i++ )
{
if (( mcp2200_manu_string[i] = ( unsigned char* )malloc( 16 )) == NULL ) {
/* error */
}
if (( mcp2200_prod_string[i] = ( unsigned char* )malloc( 16 )) == NULL ) {
/* error */
}
/* init the rows here */
memset (mcp2200_manu_string[i], 0x00, sizeof(&mcp2200_manu_string[i]));
memset (mcp2200_prod_string[i], 0x00, sizeof(&mcp2200_prod_string[i]));
}
// manuStr holds (strlen(manuStr) * 2) + 2 in byte[0] and manufacturer string from byte[1] on
strcpy (&manuStr[1], manu);
manuStr[0] = ((strlen (&manuStr[1]) * 2) + 2);
// prodStr holds (strlen(prodStr) * 2) + 2 in byte[0] and product string from byte[1] on
strcpy (&prodStr[1], prod);
prodStr[0] = ((strlen (&prodStr[1]) * 2) + 2);
// build manufacturer / product strings
for (i=0, k=0; i<16; i++, k+=4) {
if (i==0) {
tmp = 0x03;
} else {
tmp = 0x00;
}
// manufacturer string
mcp2200_manu_string[i][0] = MCP2200_SECRET_CONFIGURE;
mcp2200_manu_string[i][1] = MCP2200_CFG_MANU;
mcp2200_manu_string[i][2] = i;
mcp2200_manu_string[i][3] = manuStr[k];
mcp2200_manu_string[i][4] = tmp;
mcp2200_manu_string[i][5] = manuStr[k+1];
mcp2200_manu_string[i][6] = 0x00;
mcp2200_manu_string[i][7] = manuStr[k+2];
mcp2200_manu_string[i][8] = 0x00;
mcp2200_manu_string[i][9] = manuStr[k+3];
mcp2200_manu_string[i][10] = 0x00;
mcp2200_manu_string[i][11] = 0xff;
mcp2200_manu_string[i][12] = 0xff;
mcp2200_manu_string[i][13] = 0xff;
mcp2200_manu_string[i][14] = 0xff;
mcp2200_manu_string[i][15] = 0xff;
// product string
mcp2200_prod_string[i][0] = MCP2200_SECRET_CONFIGURE;
mcp2200_prod_string[i][1] = MCP2200_CFG_PROD;
mcp2200_prod_string[i][2] = i;
mcp2200_prod_string[i][3] = prodStr[k];
mcp2200_prod_string[i][4] = tmp;
mcp2200_prod_string[i][5] = prodStr[k+1];
mcp2200_prod_string[i][6] = 0x00;
mcp2200_prod_string[i][7] = prodStr[k+2];
mcp2200_prod_string[i][8] = 0x00;
mcp2200_prod_string[i][9] = prodStr[k+3];
mcp2200_prod_string[i][10] = 0x00;
mcp2200_prod_string[i][11] = 0xff;
mcp2200_prod_string[i][12] = 0xff;
mcp2200_prod_string[i][13] = 0xff;
mcp2200_prod_string[i][14] = 0xff;
mcp2200_prod_string[i][15] = 0xff;
}
}
Call this function in your main loop:
prepare_cfg_strings ("MyManufacturerName, "MyProductName");
Open a hid handle to your mcp2200 and put this stuff on the bus:
// write manufacturer string configuration to usb device
for (i=0; i<16; i++) {
hid_write (handle, mcp2200_manu_string[i], 16);
}
// write product string configuration to usb device
for (i=0; i<16; i++) {
hid_write (handle, mcp2200_prod_string[i], 16);
}
If you want to flash the mcp2200 with your own VendorID / ProductID configure your message:
// Microchip VID: 0x04d8
// MCP2200 PID: 0x00df
mcp2200_pid_vid_cfg[] = 01 00 D8 04 DF 00 00 00 00 00 00 00 00 00 00 00
| | +---+ +---+--------------------------------> Product ID (bytes swapped)
| | +--------------------------------------> Vendor ID (bytes swapped)
| +--------------------------------------------> MCP2200 Config Bit (MCP2200_CFG_VID_PID)
+-----------------------------------------------> MCP2200_SECRET_CONFIGURE from usb trace
and put it on the bus:
hid_write (handle, mcp2200_pid_vid_cfg, 16);
Have Fun!
n.

You will not be able to control the GPIO ports from the console/terminal via USB tty...
The USB to serial/UART converter is one of the features of MCP2200, to control the GPIO, you need to send commands via USB & HID driver. to achieve this, you will need the following.
HIDAPI:
https://github.com/signal11/hidapi
USBtoUART:
https://github.com/Miceuz/USBtoUART
USBtoUART requires hid.o from the HIDAPI package.... so start with HIDAPI first...
good luck!
MikeF
ps: I made a few modifications to the code, to accept binary format for controlling the GPIO ports, etc... it has been compiled fine on x86 and ARM ( Raspberry Pi )

Related

Read DTC codes OBD2 using arduino

I try read dtc codes using a obd device (sparkfun obd based on stn1110) and an arduino. Running this code
uint16_t codes[6];
byte dtcCount = obd.readDTC(codes, 6);
if (dtcCount == 0) {
Serial.println("No DTC");
} else {
Serial.print(dtcCount);
Serial.print(" DTC:");
for (byte n = 0; n < dtcCount; n++) {
Serial.print(' ');
Serial.print(codes[n], HEX);
}
Serial.println();
}
delay(5000);
}
Returns:
2 DTC: 3303 100
How can I interpret those codes? I mean usually I saw error codes are like PXXXX ...
Thanks a lot
L.E.
I scanned same car using a "proffesional" tester and found following codes (see pictures).
What I am doing wrong with my code or how should I interpret my results in order to get same codes as the service scanner?
Basically my code show 2 dtc's but the scanner found 5 in total
Dig further and I think the function used for read dtc is somehow wrong:
this is the function
byte COBD::readDTC(uint16_t codes[], byte maxCodes)
{
byte codesRead = 0;
for (byte n = 0; n < 6; n++) {
char buffer[128];
sprintf_P(buffer, n == 0 ? PSTR("03\r") : PSTR("03%02X\r"), n);
write(buffer);
if (receive(buffer, sizeof(buffer)) > 0) {
Serial.print("received buffer :");
Serial.println(buffer);
if (!strstr_P(buffer, PSTR("NO DATA"))) {
char *p = strstr(buffer, "43");
if (p) {
while (codesRead < maxCodes && *p) {
p += 6;
if (*p == '\r') {
p = strchr(p, ':');
if (!p) break;
p += 2;
}
uint16_t code = hex2uint16(p);
if (code == 0) break;
codes[codesRead++] = code;
}
}
break;
}
}
}
return codesRead;
}
As you see I printed "received buffer" to see what I get from OBD and the result is:
received buffer :43 01 33 03 01 00 00
>
I think is something wrong here, or I miss something in the answer
why i get that">" on a new line?
also according to https://en.wikipedia.org/wiki/OBD-II_PIDs (chapter Service 03 (no PID required))
i delete "43" from my buffer and get "01 33 03 01 00 00"
then "01" means "C - Chassis"
but then nothing match to the decoding description...so I became almost sure that I don t ask / read as it should this thing. I think i get an invalid answer somehow ...
Again any help will be appreciated :)
Thanks
L.E.2 - did another progess step.
According to this document - https://www.elmelectronics.com/wp-content/uploads/2016/07/ELM327DS.pdf , on page 34
first should find out the number of dtc stored and then try to read them.
Sending >0101 to obd return me "41 01 82 07 61 01"
and if I do 82 - 80 => I have 2 trouble codes ?!?! why I have 5 of them on the tester?
From my previous response, also according to that document
"43 01 33 03 01 00 00" means P0133 and P0301
But on the tester, except those 2, I had also - P0303 , P0300 and C1513
How to get to read correctly the dtc codes?
Thanks again

Is fdisk divides address space for created partition?

On my system, it has one mem node created already in /dev (/dev/pmem). then i use fdisk command for creating a partition
After creating partition I apply lsblk command and my result is
pmem1 259:4 0 15.8G 0 disk
└─pmem1p2 259:7 0 14.3G 0 part
After that, I write mmap code (Refer devmam library) just like
off_t address = 0x00;
int width = 10;
void *virtladdr, *phyaddr;
int a = 5;
int *lendata = &a;
int main(void)
{
int mode = 0x0777;
char *filename = "/dev/pmem0";
int fdout;
if ((fdout = open (filename, O_RDWR | O_CREAT | O_TRUNC, mode )) < 0)//edited here
{
printf ("can't create file");
return 0;
}
mapped_size = page_size = getpagesize();
offset_in_page = (uint64_t)address & (page_size - 1);
if (offset_in_page + (width * 8) > page_size) {
mapped_size *= 2;
}
printf("map size %ld\n", mapped_size);
phyaddr = mmap(0, mapped_size, (PROT_READ | PROT_WRITE), MAP_SHARED, fdout, address & ~(off_t)(page_size - 1));
1 = I write value 10 on 0x00 address for /dev/pmem1
2 = I write value 20 on 0x00 address for /dev/pmem1p2
Then after I Read mmap
off_t address = 0x00;
int width = 10;
int main(void)
{
int retVal = -1;
int fd;
unsigned long mapped_size, page_size, offset_in_page;
void *virtladdr, *phyaddr;
fd = open("/dev/pmem0", O_RDWR | O_SYNC);
if(fd < 0)
{
printf("file not open \n");
}
mapped_size = page_size = getpagesize();
offset_in_page = (uint64_t)address & (page_size - 1);
if (offset_in_page + (width * 8) > page_size) {
mapped_size *= 2;
}
/* Map one page */
phyaddr = mmap(0, mapped_size, PROT_READ,MAP_PRIVATE , fd, address & ~(off_t)(page_size - 1));
1 = Read 0x00 address from /dev/pmem1 My output is 10
2 = Read 0x00 address from /dev/pmem1p2 My output is 20
So what happened here why 0th address value is different? Is fdisk create two partitions which address starts from 0x00? Or I am in the wrong way?

ESP32 reading DHT22 sensor in ULP coprocessor

I´m trying to read a dht22 sensor in ulp deep sleep, and it´s not working, can perhaps someone tell me what I´m doing wrong?
I´m reimplementing the arduino-DHT library because it´s working in non ulp mode with my sensor, it looks like this:
digitalWrite(pin, LOW); // Send start signal
pinMode(pin, OUTPUT);
delayMicroseconds(800);
pinMode(pin, INPUT);
digitalWrite(pin, HIGH); // Switch bus to receive data
// We're going to read 83 edges:
// - First a FALLING, RISING, and FALLING edge for the start bit
// - Then 40 bits: RISING and then a FALLING edge per bit
// To keep our code simple, we accept any HIGH or LOW reading if it's max 85 usecs long
uint16_t rawHumidity = 0;
uint16_t rawTemperature = 0;
uint16_t data = 0;
for ( int8_t i = -3 ; i < 2 * 40; i++ ) {
byte age;
startTime = micros();
do {
age = (unsigned long)(micros() - startTime);
if ( age > 90 ) {
error = ERROR_TIMEOUT;
return;
}
}
while ( digitalRead(pin) == (i & 1) ? HIGH : LOW );
if ( i >= 0 && (i & 1) ) {
// Now we are being fed our 40 bits
data <<= 1;
// A zero max 30 usecs, a one at least 68 usecs.
if ( age > 30 ) {
data |= 1; // we got a one
}
}
switch ( i ) {
case 31:
rawHumidity = data;
break;
case 63:
rawTemperature = data;
data = 0;
break;
}
}
Looks simple enough :D, I tried the first part with this code, but it doesn´t work:
rtc_gpio_init(15);
rtc_gpio_set_direction(15, RTC_GPIO_MODE_INPUT_OUTPUT);
And in my ulp script file:
.set temp_humidity_sensor_pin, 13 // gpio 15 (adc 13)
send_start_signal:
/* disable hold on gpio 15 (data pin) */
WRITE_RTC_REG(RTC_IO_TOUCH_PAD3_REG, RTC_IO_TOUCH_PAD3_HOLD_S, 1, 0)
/* switch to output mode */
WRITE_RTC_REG(RTC_GPIO_OUT_W1TS_REG, RTC_GPIO_OUT_DATA_W1TS_S + temp_humidity_sensor_pin, 1, 1)
/* send start signal (LOW) */
WRITE_RTC_REG(RTC_GPIO_OUT_REG, RTC_GPIO_OUT_DATA_S + temp_humidity_sensor_pin, 1, 0)
/* pull low for 800 microseconds (8Mhz) */
wait 6400
/* switch to input mode */
WRITE_RTC_REG(RTC_GPIO_OUT_W1TC_REG, RTC_GPIO_OUT_DATA_W1TC_S + temp_humidity_sensor_pin, 1, 1)
/* switch bus to receive data (HIGH) */
WRITE_RTC_REG(RTC_GPIO_OUT_REG, RTC_GPIO_OUT_DATA_S + temp_humidity_sensor_pin, 1, 1)
wait_for_sensor_preparation_low:
READ_RTC_REG(RTC_GPIO_IN_REG, RTC_GPIO_IN_NEXT_S + temp_humidity_sensor_pin, 1)
and r0, r0, 1
jump wait_for_sensor_preparation_low, eq
wait_for_sensor_preparation_high:
READ_RTC_REG(RTC_GPIO_IN_REG, RTC_GPIO_IN_NEXT_S + temp_humidity_sensor_pin, 1)
and r0, r0, 0
jump wait_for_sensor_preparation_high, eq
jump wake_up // <-- never called :(
Any ideas?
Your "and r0, r0, 0" instruction (near the end) always sets r0 to zero (x & 0 == 0 by definition), which means the following jump instruction will loop forever. Remember that the "eq" flag doesn't really mean "equal". It means "zero". I think you want:
wait_for_sensor_preparation_low:
READ_RTC_REG(RTC_GPIO_IN_REG, RTC_GPIO_IN_NEXT_S + temp_humidity_sensor_pin, 1)
and r0, r0, 1
jump wait_for_sensor_preparation_high, eq
jump wait_for_sensor_preparation_low
wait_for_sensor_preparation_high:
READ_RTC_REG(RTC_GPIO_IN_REG, RTC_GPIO_IN_NEXT_S + temp_humidity_sensor_pin, 1)
and r0, r0, 1
jump wait_for_sensor_preparation_high, eq
By the way, I wrote a C compiler for the ULP, which should make your life easier. It's on https://github.com/jasonful/lcc

How do you interpret a bit string using sharp snmp lib (hrPrinterDetectedErrorState)?

How do you interpret hrPrinterDetectedErrorState (http://cric.grenoble.cnrs.fr/Administrateurs/Outils/MIBS/?oid=1.3.6.1.2.1.25.3.5.1.2) or something like it using Sharp Snmp lib? Is there some kind of bit string type? It's kind of a bitmask, but you may only receive one byte instead of two (or I've seen four bytes).
Did it on my own in powershell.
[flags()] Enum hrPrinterDetectedErrorState
{
lowPaper = 0x8000
noPaper = 0x4000
lowToner = 0x2000
noToner = 0x1000
doorOpen = 0x0800
jammed = 0x0400
Offline = 0x0200
serviceRequested = 0x0100
inputTrayMissing = 0x0080
outputTrayMissing = 0x0040
markerSupplyMissing = 0x0020
outputNearFull = 0x0010
outputFull = 0x0008
inputTrayEmpty = 0x0004
overduePreventMaint = 0x0002
notUsed = 0x0001
}
function snmpmessage($data) {
$bytes = [byte[]][char[]]$data
# pack up to two bytes into an int left to right
$code = [int]$bytes[0]
$code = $code -shl 8
if ($bytes[1]) { $code = $code + $bytes[1] }
[hrPrinterDetectedErrorState]$code
}
PS C:\> snmpmessage -join [char[]](0x91,0x04)
inputTrayEmpty, serviceRequested, noToner, lowPaper

Javacard applet to subtract two hexadecimal array of byte

I'm try to write a javacard applet that need to add/sub two array of bytes.
the addition was success but the subtraction fail in some cases ("when there is a borrow from the procceding byte").
Can you check my code and improve it to work better?
package phase1;
import javacard.framework.APDU;
import javacard.framework.Applet;
import javacard.framework.ISO7816;
import javacard.framework.ISOException;
import javacard.framework.Util;
import javacard.security.CryptoException;
public class keygen extends Applet {
public static final short _0 = 0;
public final static byte[] one = {(byte) 0xff, (byte) 0xff, (byte) 0xff,(byte) 0xff,(byte) 0xff,(byte) 0xff};
byte [] G = {(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x11};
private keygen() {
}
public static void install(byte bArray[], short bOffset, byte bLength)throws ISOException {
try{
new keygen().register();
} catch (Exception e) {
ISOException.throwIt((short) 0x8888);
}
}
public void process(APDU apdu) throws ISOException {
// TODO Auto-generated method stub
if (selectingApplet()) return;
//short sendlen = 0;
byte[] buf = apdu.getBuffer();
byte ins = buf[ISO7816.OFFSET_INS];
byte [] val = new byte [(short) G.length];
short i;
short len = (short) G.length ;
short Alen = (short) (len - 1);
short b = (short) 0 ;
byte[] Z = new byte [(short) len];
byte[] y = new byte [(short) 2];
try{
switch (ins){
case (byte) 0x01: //0x0F
{
Z = addarray (G , one);
apdu.setOutgoing();
buf = Z;
apdu.setOutgoingLength(len);
apdu.sendBytesLong(Z, (short) 0,len);
break;
}
case (byte) 0x02: //0x0F
{ //Z = new byte [(short) 7];
Z = subarray1 (G , one);
apdu.setOutgoing();
buf= Z;
apdu.setOutgoingLength(len);
apdu.sendBytesLong(Z, (short) 0,len);
break;
}
default:
ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
}
}catch (CryptoException e) {
ISOException.throwIt(((CryptoException) e).getReason());
}
}
private byte [] addarray (byte [] Arr1, byte [] Arr2 )
{
short i;
short [] X = new short [(short) 6];
short len = (short) Arr1.length ;
short Alen = (short) (len - 1);
byte [] AddArr = new byte [len];
short R = (short) 0;
byte[] Z = new byte [(short) 2];
for (i = Alen; i >= 0 ; i--)
{
X[i] = (short) ((Arr1[i] & 0xFF) + (Arr2[i]&0xff) + R);
Util.setShort(Z, (short) 0, (short) X[i]);
AddArr[i] = (byte) Z[1];
R = (short) (Z[0]);
}
return AddArr;
}
private byte [] subarray1 (byte [] Arr1, byte [] Arr2)
{
short i;
byte [] X = new byte [(short) 6];
short len = (short) Arr1.length ;
short Alen = (short) (len - 1);
byte [] SubArr = new byte [len];
short R = (short) 0;
byte[] Z = new byte [(short) 2];
for (i = Alen; i > 0 ; i--)
{
X[i] = (byte) (Arr1[i] - Arr2[i] - (byte) R );
Util.setShort(Z, (short) 0, (short) X[i]);
SubArr[i] = (byte) Z[1];
R = (short) (Z[0] );
}
return SubArr;
}
}
There is an optional class in Java Card API named bigIntNumber. If your card doesn't implemented it, I share its source code with you:
/**
* Class BigIntNumber provides addition, subtraction and comparison functions
* for unsigned integers represented in byte array format in bug endian order.
*
*/
public class BigIntNumber {
/**
* Add two unsigned integers represented in array A and B. The sum stored in
* array C
*
* #param A the left operand
* #param AOff the starting position in array A.
* #param B the right operand.
* #param BOff the starting position in array B.
* #param C the result of (A+B)
* #param COff the starting position in array C.
* #param len the number of bytes in the operands as well in the computed
* result. this parameter can not be a negative number.
* #return false if the result overflows. if overflows occurs, the sum would
* be the true mathematical result with the most significant bytes discarded
* to fit into array C of the specified length.
* #throws ArrayOuutOfBoundException if array access out of bound.
*/
public static boolean add(byte[] A, byte AOff, byte[] B, byte BOff, byte[] C, byte COff, byte len) {
short result = 0;
for (len = (byte) (len - 1); len >= 0; len--) {
// add two unsigned bytes and the carry from the
// previous byte computation.
result = (short) (getUnsignedByte(A, AOff, len) + getUnsignedByte(B, BOff, len) + result);
// store the result in byte array C
C[(byte) (len + COff)] = (byte) result;
// has a carry?
if (result > 0x00FF) {
result = 1;
result = (short) (result + 0x100);
} else {
result = 0;
}
}
//produce overflow in the sum.
if (result == 1) {
return false;
}
return true;
}
/**
* Subtract two unsigned integers represented in array A and B. The sum stored in
* array C
*
* #param A the left operand
* #param AOff the starting position in array A.
* #param B the right operand.
* #param BOff the starting position in array B.
* #param C the result of (A-B)
* #param COff the starting position in array C.
* #param len the number of bytes in the operands as well in the computed
* result. this parameter can not be a negative number.
* #return false if the result underflows. if underflows occurs, the sum would
* be the mathematical result of A + ~B + 1.
* #throws ArrayOuutOfBoundException if array access out of bound.
*/
public static boolean subtract(byte[] A, byte AOff, byte[] B, byte BOff, byte[] C, byte COff, byte len) {
byte borrow = 0;
short result;
for (len = (byte) (len - 1); len >= 0; len--) {
// subtract one unsigned byte from the other.
// also subtract the borrow from the previous byte computation.
result = (short) (getUnsignedByte(A, AOff, len) - getUnsignedByte(B, BOff, len) - borrow);
// need to borrow?
if (result < 0) {
borrow = 1;
result = (short) (result + 0x100);
} else {
borrow = 0;
}
// store the result in C
C[(byte) (len + COff)] = (byte) result;
}
// is the result underflow?
if (borrow == 1) {
return false;
}
return true;
}
/**
* Compare two unsigned integers represented in array A and B. The sum stored in
* array C
*
* #param A the left operand
* #param AOff the starting position in array A.
* #param B the right operand.
* #param BOff the starting position in array B.
* #param C the result of (A-B)
* #param COff the starting position in array C.
* #param len the number of bytes in the operands as well in the computed
* result. this parameter can not be a negative number.
* #return the result of comparison as below:
* 0 if identical
* 1 if the left operand is bigger than the right operand
* -1 if the left operand is smaller than the right operand
* #throws ArrayOuutOfBoundException if array access out of bound.
*/
public static byte compare(byte[] A, byte AOff, byte[] B, byte BOff, byte len) {
byte count = (byte) 0;
for (; count < len; count++) {
short C = getUnsignedByte(A, AOff, count);
short D = getUnsignedByte(A, AOff, count);
if (C < D) {
return -1;
}
if (C > D) {
return 1;
}
}
return 0;
}
/**
*
* Get the unsigned byte at the index (AOff + count)
*/
private static short getUnsignedByte(byte[] A, byte AOff, byte count) {
return (short) (A[(short) (count + AOff)] & 0x00FF);
}
}
And this is a sample applet that I wroto to show you how does the above class methods work:
package phase1;
import javacard.framework.APDU;
import javacard.framework.Applet;
import javacard.framework.ISO7816;
import javacard.framework.ISOException;
import javacard.framework.Util;
import static phase1.BigIntNumber.*;
public class TestBigInt extends Applet {
// Defining global arrays for Operands A and B.
// LenA and LenB are defined to check if equal length of A and B are going
// to add, compare or subtract or not. Len of operands musb be equal between 1 byte to 8 bytes.
public static byte[] OpA = new byte[8];
public static byte[] OpB = new byte[8];
public static byte[] result = new byte[8];
public static byte lenA;
public static byte lenB;
// Defining supported INS valuse for APDU Command.
public static final byte INS_INIT_OPERAND = (byte) 0x10;
public static final byte INS_ADD = (byte) 0x20;
public static final byte INS_SUBTRACT = (byte) 0x30;
public static final byte INS_COMPARE = (byte) 0x40;
// P1 parameter in the APDU command
public static final byte OPERAND_A = 0x01;
public static final byte OPERAND_B = 0x02;
// Defining Exception Status Words
public static short SW_NOT_EQUAL_LENGTH = (short) 0x6910;
public static short SW_OVERFLOW_OCCURS = (short) 0x6911;
public static short SW_UNDERFLOW_OCCURS = (short) 0x6912;
private TestBigInt() {
}
public static void install(byte bArray[], short bOffset, byte bLength) throws ISOException {
new TestBigInt().register();
}
public void process(APDU apdu) throws ISOException {
if (selectingApplet()) {
return;
}
byte[] buf = apdu.getBuffer();
switch (buf[ISO7816.OFFSET_INS]) {
case INS_INIT_OPERAND:
apdu.setIncomingAndReceive();
if (buf[ISO7816.OFFSET_LC] > (byte) 0x08) {
ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
}
if (buf[ISO7816.OFFSET_P1] == OPERAND_A) {
Util.arrayCopyNonAtomic(buf, ISO7816.OFFSET_CDATA, OpA, (short) 0x00, buf[ISO7816.OFFSET_LC]);
lenA = buf[ISO7816.OFFSET_LC];
} else if (buf[ISO7816.OFFSET_P1] == OPERAND_B) {
Util.arrayCopyNonAtomic(buf, ISO7816.OFFSET_CDATA, OpB, (short) 0x00, buf[ISO7816.OFFSET_LC]);
lenB = buf[ISO7816.OFFSET_LC];
} else {
ISOException.throwIt(ISO7816.SW_WRONG_P1P2);
}
break;
case INS_ADD:
if (lenA != lenB) {
ISOException.throwIt(SW_NOT_EQUAL_LENGTH);
}
if (add(OpA, (byte) 0x00, OpB, (byte) 0x00, result, (byte) 0x00, lenA)) {
apdu.sendBytesLong(result, (short) 0x00, (short) lenA);
} else {
ISOException.throwIt(SW_OVERFLOW_OCCURS);
}
break;
case INS_SUBTRACT:
if (lenA != lenB) {
ISOException.throwIt(SW_NOT_EQUAL_LENGTH);
}
if (subtract(OpA, (byte) 0x00, OpB, (byte) 0x00, result, (byte) 0x00, lenA)) {
apdu.sendBytesLong(result, (short) 0x00, (short) lenA);
} else {
ISOException.throwIt(SW_UNDERFLOW_OCCURS);
}
break;
case INS_COMPARE:
// ...
break;
default:
ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
}
}
}
It seems works fine:
Connect successful.
Download Cap begin...
Download Cap successful.
Install Applet begin...
Install Applet successful.
Select Applet begin...
Select Applet successful.
Send: 00 10 01 00 07 11 22 33 44 55 66 77 00 //Initilizing Operand A
Recv: 90 00
Time used: 21.000 ms
Send: 00 10 02 00 07 11 22 33 44 55 66 77 00 //Initlizing Operand B
Recv: 90 00
Time used: 19.000 ms
Send: 00 20 00 00 00 // Compute A+B
Recv: 22 44 66 88 AA CC EE 90 00
Time used: 67.000 ms
Send: 00 30 00 00 00 // Compute A-B
Recv: 00 00 00 00 00 00 00 90 00
Time used: 73.000 ms
Send: 00 10 02 00 07 00 00 44 44 44 44 44 00 // Changing Operand B
Recv: 90 00
Time used: 14.000 ms
Send: 00 20 00 00 00 // Compute A+B again
Recv: 11 22 77 88 99 AA BB 90 00
Time used: 66.000 ms
Send: 00 30 00 00 00 // Compute A-B
Recv: 11 21 EF 00 11 22 33 90 00
Time used: 71.000 ms
Sorry, I didn't checked your code. Just two simple hint:
1- Try to don't use dynamic fields in methods. Java Card doesn't support automatic garbage collection, so the memory that you assign to a field dynamically (i.e. using new keyword), will not reclaimed automatically until calling requestObjectDeletion() method (and it's optional too!) :)
2- 0x8888 is not a standard status world in the ISO7816-4 standard and some smart cards has problem with non-standard status words. Try to choose 6XXX (60XX is also non-standard value) or 9XXX for status words.

Resources