From 20dc72696556967e6dd5f182dd962538a3a06ae2 Mon Sep 17 00:00:00 2001 From: "Robert (Jamie) Munro" Date: Sat, 20 Oct 2012 22:51:36 +0100 Subject: [PATCH 01/21] First vague stab at adding ITSO Transit data --- .../farebot/transit/ItsoTransitData.java | 131 ++++++++++++++++++ 1 file changed, 131 insertions(+) create mode 100644 src/main/java/com/codebutler/farebot/transit/ItsoTransitData.java diff --git a/src/main/java/com/codebutler/farebot/transit/ItsoTransitData.java b/src/main/java/com/codebutler/farebot/transit/ItsoTransitData.java new file mode 100644 index 000000000..05a785d68 --- /dev/null +++ b/src/main/java/com/codebutler/farebot/transit/ItsoTransitData.java @@ -0,0 +1,131 @@ +/** + * + */ +package com.codebutler.farebot.transit; + +import com.codebutler.farebot.Utils; +import com.codebutler.farebot.mifare.Card; +import com.codebutler.farebot.mifare.DesfireCard; +import com.codebutler.farebot.transit.ClipperTransitData.ClipperRefill; +import com.codebutler.farebot.transit.ClipperTransitData.ClipperTrip; + +import android.os.Parcel; + +/** + * @author rjmunro + * + */ +public class ITSOTransitData extends TransitData { + + + + public static boolean check (Card card) + { + // Mifare Desfire + if ((card instanceof DesfireCard) && (((DesfireCard) card).getApplication(0x1602a0) != null)) + return true; + + return false; + } + + /* (non-Javadoc) + * @see android.os.Parcelable#writeToParcel(android.os.Parcel, int) + */ + @Override + public void writeToParcel(Parcel arg0, int arg1) { + // TODO Auto-generated method stub + + } + + public ITSOTransitData(Parcel parcel) { + mSerialNumber = parcel.readLong(); + mBalance = (short) parcel.readLong(); + + mTrips = new ClipperTrip[parcel.readInt()]; + parcel.readTypedArray(mTrips, ClipperTrip.CREATOR); + + mRefills = new ClipperRefill[parcel.readInt()]; + parcel.readTypedArray(mRefills, ClipperRefill.CREATOR); + } + + + public ITSOTransitData(Card card) { + if (card instanceof DesfireCard) { + DesfireCard desfireCard = (DesfireCard) card; + + byte[] data; + + try { + data = desfireCard.getApplication(0x1602a0).getFile(0x08).getData(); + mSerialNumber = Utils.byteArrayToLong(data, 1, 4); + } catch (Exception ex) { + throw new RuntimeException("Error parsing Clipper serial", ex); + } + + try { + data = desfireCard.getApplication(0x9011f2).getFile(0x02).getData(); + mBalance = (short) (((0xFF & data[18]) << 8) | (0xFF & data[19])); + } catch (Exception ex) { + throw new RuntimeException("Error parsing Clipper balance", ex); + } + + try { + mTrips = parseTrips(desfireCard); + } catch (Exception ex) { + throw new RuntimeException("Error parsing Clipper trips", ex); + } + + try { + mRefills = parseRefills(desfireCard); + } catch (Exception ex) { + throw new RuntimeException("Error parsing Clipper refills", ex); + } + } + } + + /* (non-Javadoc) + * @see com.codebutler.farebot.transit.TransitData#getBalanceString() + */ + @Override + public String getBalanceString() { + // TODO Auto-generated method stub + return null; + } + + /* (non-Javadoc) + * @see com.codebutler.farebot.transit.TransitData#getSerialNumber() + */ + @Override + public String getSerialNumber() { + // TODO Auto-generated method stub + return null; + } + + /* (non-Javadoc) + * @see com.codebutler.farebot.transit.TransitData#getTrips() + */ + @Override + public Trip[] getTrips() { + // TODO Auto-generated method stub + return null; + } + + /* (non-Javadoc) + * @see com.codebutler.farebot.transit.TransitData#getRefills() + */ + @Override + public Refill[] getRefills() { + // TODO Auto-generated method stub + return null; + } + + /* (non-Javadoc) + * @see com.codebutler.farebot.transit.TransitData#getCardName() + */ + @Override + public String getCardName() { + // TODO Auto-generated method stub + return null; + } + +} From 2a9a13ae6fe20bfc9413936885c71be0ed857418 Mon Sep 17 00:00:00 2001 From: "Robert (Jamie) Munro" Date: Sun, 28 Oct 2012 22:02:09 +0000 Subject: [PATCH 02/21] Added ITSO to list of supported cards --- res/drawable-hdpi/itso_card.png | Bin 0 -> 10889 bytes .../activities/SupportedCardsActivity.java | 1 + src/main/res/values/strings.xml | 1 + 3 files changed, 2 insertions(+) create mode 100644 res/drawable-hdpi/itso_card.png diff --git a/res/drawable-hdpi/itso_card.png b/res/drawable-hdpi/itso_card.png new file mode 100644 index 0000000000000000000000000000000000000000..985cca6a5f95a6fb9466ff07a6f7c44dc1f77a78 GIT binary patch literal 10889 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 U+XuzuUqz{!lD1-The Netherlands São Paulo, Brazil Helsinki, Finland + UK Block: %s Sector: 0x%s Sector: 0x%s (Unauthorized) From c0c09d8b4d676ba784778322f62656eea715d867 Mon Sep 17 00:00:00 2001 From: "Robert (Jamie) Munro" Date: Sun, 28 Oct 2012 22:11:49 +0000 Subject: [PATCH 03/21] Add beginnings of working ITSO card support --- .../farebot/card/desfire/DesfireCard.java | 5 + .../farebot/transit/ItsoTransitData.java | 224 ++++++++++++------ 2 files changed, 155 insertions(+), 74 deletions(-) diff --git a/src/main/java/com/codebutler/farebot/card/desfire/DesfireCard.java b/src/main/java/com/codebutler/farebot/card/desfire/DesfireCard.java index ccad6207c..a20274415 100644 --- a/src/main/java/com/codebutler/farebot/card/desfire/DesfireCard.java +++ b/src/main/java/com/codebutler/farebot/card/desfire/DesfireCard.java @@ -36,6 +36,7 @@ import com.codebutler.farebot.transit.ClipperTransitData; import com.codebutler.farebot.transit.HSLTransitData; import com.codebutler.farebot.transit.OrcaTransitData; +import com.codebutler.farebot.transit.ItsoTransitData; import com.codebutler.farebot.transit.TransitData; import com.codebutler.farebot.transit.TransitIdentity; import org.w3c.dom.Document; @@ -122,6 +123,8 @@ public TransitIdentity parseTransitIdentity() { return ClipperTransitData.parseTransitIdentity(this); if (HSLTransitData.check(this)) return HSLTransitData.parseTransitIdentity(this); + if (ItsoTransitData.check(this)) + return ItsoTransitData.parseTransitIdentity(this); return null; } @@ -133,6 +136,8 @@ public TransitData parseTransitData() { return new ClipperTransitData(this); if (HSLTransitData.check(this)) return new HSLTransitData(this); + if (ItsoTransitData.check(this)) + return new ItsoTransitData(this); return null; } diff --git a/src/main/java/com/codebutler/farebot/transit/ItsoTransitData.java b/src/main/java/com/codebutler/farebot/transit/ItsoTransitData.java index 05a785d68..2eae79745 100644 --- a/src/main/java/com/codebutler/farebot/transit/ItsoTransitData.java +++ b/src/main/java/com/codebutler/farebot/transit/ItsoTransitData.java @@ -1,34 +1,42 @@ /** - * + * */ package com.codebutler.farebot.transit; +import android.os.Parcel; import com.codebutler.farebot.Utils; +//import com.codebutler.farebot.Utils; import com.codebutler.farebot.mifare.Card; +import com.codebutler.farebot.mifare.DesfireApplication; import com.codebutler.farebot.mifare.DesfireCard; -import com.codebutler.farebot.transit.ClipperTransitData.ClipperRefill; -import com.codebutler.farebot.transit.ClipperTransitData.ClipperTrip; +import com.codebutler.farebot.mifare.DesfireFile; -import android.os.Parcel; +import java.text.NumberFormat; +import java.util.*; -/** - * @author rjmunro - * - */ -public class ITSOTransitData extends TransitData { +public class ItsoTransitData extends TransitData { + private long mSerialNumber; + + public static boolean check(Card card) { + // Mifare Desfire + if ((card instanceof DesfireCard) + && (((DesfireCard) card).getApplication(0x1602a0) != null)) { + + /* Need to check IIN is 633597 + if (ItsoTransitData.bytesToHexString(data, 2, 3) != "633597") { + */ - - - public static boolean check (Card card) - { - // Mifare Desfire - if ((card instanceof DesfireCard) && (((DesfireCard) card).getApplication(0x1602a0) != null)) - return true; - return false; - } - /* (non-Javadoc) + return true; + } + + return false; + } + + /* + * (non-Javadoc) + * * @see android.os.Parcelable#writeToParcel(android.os.Parcel, int) */ @Override @@ -36,54 +44,98 @@ public void writeToParcel(Parcel arg0, int arg1) { // TODO Auto-generated method stub } - - public ITSOTransitData(Parcel parcel) { - mSerialNumber = parcel.readLong(); - mBalance = (short) parcel.readLong(); - - mTrips = new ClipperTrip[parcel.readInt()]; - parcel.readTypedArray(mTrips, ClipperTrip.CREATOR); - - mRefills = new ClipperRefill[parcel.readInt()]; - parcel.readTypedArray(mRefills, ClipperRefill.CREATOR); - } - - - public ITSOTransitData(Card card) { - if (card instanceof DesfireCard) { - DesfireCard desfireCard = (DesfireCard) card; - - byte[] data; - - try { - data = desfireCard.getApplication(0x1602a0).getFile(0x08).getData(); - mSerialNumber = Utils.byteArrayToLong(data, 1, 4); - } catch (Exception ex) { - throw new RuntimeException("Error parsing Clipper serial", ex); - } - - try { - data = desfireCard.getApplication(0x9011f2).getFile(0x02).getData(); - mBalance = (short) (((0xFF & data[18]) << 8) | (0xFF & data[19])); - } catch (Exception ex) { - throw new RuntimeException("Error parsing Clipper balance", ex); - } - - try { - mTrips = parseTrips(desfireCard); - } catch (Exception ex) { - throw new RuntimeException("Error parsing Clipper trips", ex); - } - - try { - mRefills = parseRefills(desfireCard); - } catch (Exception ex) { - throw new RuntimeException("Error parsing Clipper refills", ex); - } - } - } - - /* (non-Javadoc) + + public ItsoTransitData(Parcel parcel) { + /* + * mSerialNumber = parcel.readLong(); mBalance = (short) + * parcel.readLong(); + * + * mTrips = new ClipperTrip[parcel.readInt()]; + * parcel.readTypedArray(mTrips, ClipperTrip.CREATOR); + * + * mRefills = new ClipperRefill[parcel.readInt()]; + * parcel.readTypedArray(mRefills, ClipperRefill.CREATOR); + */ + } + + /** + * Turn bytes into hex string representation. Also useful for decoding BCD + * + * @param bytes + * The data to convert + * @return The hex representation. + */ + public static String bytesToHexString(byte[] bytes) { + return bytesToHexString(bytes, 0, bytes.length); + } + + /** + * Turn bytes into hex string representation. Also useful for decoding BCD + * + * @param b + * The data to convert + * @param offset + * @param length + * @return + */ + public static String bytesToHexString(byte[] b, int offset, int length) { + if (b.length < length + offset) + throw new IllegalArgumentException( + "length must be less than or equal to b.length"); + + StringBuilder sb = new StringBuilder(length * 2); + + Formatter formatter = new Formatter(sb); + for (int i = 0; i < length; i++) { + formatter.format("%02x", b[offset + i]); + } + + formatter.close(); + return sb.toString(); + } + + public ItsoTransitData(Card card) { + if (card instanceof DesfireCard) { + DesfireCard desfireCard = (DesfireCard) card; + + DesfireApplication application = desfireCard + .getApplication(0x1602a0); + + // See page 100 of + // http://www.itso.org.uk/content/Specification/Spec_v2.1.4/ITSO_TS_1000-10_V2_1_4_2010-02.pdf + byte[] directoryBytes = application.getFile(0x00).getData(); + byte[] logBytes = application.getFile(0x01).getData(); + byte[] shellBytes = application.getFile(0xf).getData(); + + // ISSN = Utils.byteArrayToLong(shellBytes,6,7); + + byte[] data; + /* + * try { data = + * desfireCard.getApplication(0x1602a0).getFile(0x08).getData(); + * mSerialNumber = Utils.byteArrayToLong(data, 1, 4); } catch + * (Exception ex) { throw new + * RuntimeException("Error parsing Clipper serial", ex); } + * + * try { data = + * desfireCard.getApplication(0x9011f2).getFile(0x02).getData(); + * mBalance = (short) (((0xFF & data[18]) << 8) | (0xFF & + * data[19])); } catch (Exception ex) { throw new + * RuntimeException("Error parsing Clipper balance", ex); } + * + * try { mTrips = parseTrips(desfireCard); } catch (Exception ex) { + * throw new RuntimeException("Error parsing Clipper trips", ex); } + * + * try { mRefills = parseRefills(desfireCard); } catch (Exception + * ex) { throw new RuntimeException("Error parsing Clipper refills", + * ex); } + */ + } + } + + /* + * (non-Javadoc) + * * @see com.codebutler.farebot.transit.TransitData#getBalanceString() */ @Override @@ -92,16 +144,19 @@ public String getBalanceString() { return null; } - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see com.codebutler.farebot.transit.TransitData#getSerialNumber() */ @Override public String getSerialNumber() { - // TODO Auto-generated method stub - return null; + return Long.toString(mSerialNumber); } - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see com.codebutler.farebot.transit.TransitData#getTrips() */ @Override @@ -110,7 +165,9 @@ public Trip[] getTrips() { return null; } - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see com.codebutler.farebot.transit.TransitData#getRefills() */ @Override @@ -119,13 +176,32 @@ public Refill[] getRefills() { return null; } - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see com.codebutler.farebot.transit.TransitData#getCardName() */ @Override public String getCardName() { // TODO Auto-generated method stub - return null; + return "ITSO"; + } + + public static TransitIdentity parseTransitIdentity(Card card) { + try { + + byte[] data = ((DesfireCard) card).getApplication(0x1602a0) + .getFile(0x0f).getData(); + + return new TransitIdentity("ITSO", + ItsoTransitData.bytesToHexString(data, 5, 2) + + " " + + ItsoTransitData.bytesToHexString(data, 7, 2) + + " " + + ItsoTransitData.bytesToHexString(data, 9, 2)); + } catch (Exception ex) { + throw new RuntimeException("Error parsing ITSO serial", ex); + } } } From 4d4b129f398181f6b560946c7ecaf29dc1178f9b Mon Sep 17 00:00:00 2001 From: "Robert (Jamie) Munro" Date: Wed, 14 Nov 2012 23:27:16 +0000 Subject: [PATCH 04/21] Move bytesToHexString to Utils.getHexString() Also remove some unneeded imports from ITSOTransitData. --- .../java/com/codebutler/farebot/Utils.java | 25 ++++++++++ .../farebot/transit/ItsoTransitData.java | 48 ++----------------- 2 files changed, 29 insertions(+), 44 deletions(-) diff --git a/src/main/java/com/codebutler/farebot/Utils.java b/src/main/java/com/codebutler/farebot/Utils.java index c0398a8a2..ab91059ee 100644 --- a/src/main/java/com/codebutler/farebot/Utils.java +++ b/src/main/java/com/codebutler/farebot/Utils.java @@ -43,6 +43,7 @@ import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import java.io.StringWriter; +import java.util.Formatter; import java.util.List; public class Utils { @@ -109,6 +110,30 @@ public static String getHexString (byte[] b, String defaultResult) { } } + /** + * Turn bytes into hex string representation. Also useful for decoding BCD + * + * @param b The data to convert + * @param offset + * @param length + * @return + */ + public static String getHexString(byte[] b, int offset, int length) { + if (b.length < length + offset) + throw new IllegalArgumentException( + "length must be less than or equal to b.length"); + + StringBuilder sb = new StringBuilder(length * 2); + + Formatter formatter = new Formatter(sb); + for (int i = 0; i < length; i++) { + formatter.format("%02x", b[offset + i]); + } + + formatter.close(); + return sb.toString(); + } + public static byte[] hexStringToByteArray (String s) { if ((s.length() % 2) != 0) { throw new IllegalArgumentException("Bad input string: " + s); diff --git a/src/main/java/com/codebutler/farebot/transit/ItsoTransitData.java b/src/main/java/com/codebutler/farebot/transit/ItsoTransitData.java index 2eae79745..f480b87f4 100644 --- a/src/main/java/com/codebutler/farebot/transit/ItsoTransitData.java +++ b/src/main/java/com/codebutler/farebot/transit/ItsoTransitData.java @@ -5,15 +5,11 @@ import android.os.Parcel; import com.codebutler.farebot.Utils; -//import com.codebutler.farebot.Utils; import com.codebutler.farebot.mifare.Card; import com.codebutler.farebot.mifare.DesfireApplication; import com.codebutler.farebot.mifare.DesfireCard; import com.codebutler.farebot.mifare.DesfireFile; -import java.text.NumberFormat; -import java.util.*; - public class ItsoTransitData extends TransitData { private long mSerialNumber; @@ -23,7 +19,7 @@ public static boolean check(Card card) { && (((DesfireCard) card).getApplication(0x1602a0) != null)) { /* Need to check IIN is 633597 - if (ItsoTransitData.bytesToHexString(data, 2, 3) != "633597") { + if (Utils.getHexString(data, 2, 3) != "633597") { */ @@ -58,42 +54,6 @@ public ItsoTransitData(Parcel parcel) { */ } - /** - * Turn bytes into hex string representation. Also useful for decoding BCD - * - * @param bytes - * The data to convert - * @return The hex representation. - */ - public static String bytesToHexString(byte[] bytes) { - return bytesToHexString(bytes, 0, bytes.length); - } - - /** - * Turn bytes into hex string representation. Also useful for decoding BCD - * - * @param b - * The data to convert - * @param offset - * @param length - * @return - */ - public static String bytesToHexString(byte[] b, int offset, int length) { - if (b.length < length + offset) - throw new IllegalArgumentException( - "length must be less than or equal to b.length"); - - StringBuilder sb = new StringBuilder(length * 2); - - Formatter formatter = new Formatter(sb); - for (int i = 0; i < length; i++) { - formatter.format("%02x", b[offset + i]); - } - - formatter.close(); - return sb.toString(); - } - public ItsoTransitData(Card card) { if (card instanceof DesfireCard) { DesfireCard desfireCard = (DesfireCard) card; @@ -194,11 +154,11 @@ public static TransitIdentity parseTransitIdentity(Card card) { .getFile(0x0f).getData(); return new TransitIdentity("ITSO", - ItsoTransitData.bytesToHexString(data, 5, 2) + Utils.getHexString(data, 5, 2) + " " - + ItsoTransitData.bytesToHexString(data, 7, 2) + + Utils.getHexString(data, 7, 2) + " " - + ItsoTransitData.bytesToHexString(data, 9, 2)); + + Utils.getHexString(data, 9, 2)); } catch (Exception ex) { throw new RuntimeException("Error parsing ITSO serial", ex); } From e8065036f122a60207f22e8c22e523335d7906ae Mon Sep 17 00:00:00 2001 From: "Robert (Jamie) Munro" Date: Wed, 14 Nov 2012 23:34:55 +0000 Subject: [PATCH 05/21] Get ISSN from shell --- .../java/com/codebutler/farebot/transit/ItsoTransitData.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/codebutler/farebot/transit/ItsoTransitData.java b/src/main/java/com/codebutler/farebot/transit/ItsoTransitData.java index f480b87f4..682bce89a 100644 --- a/src/main/java/com/codebutler/farebot/transit/ItsoTransitData.java +++ b/src/main/java/com/codebutler/farebot/transit/ItsoTransitData.java @@ -12,6 +12,7 @@ public class ItsoTransitData extends TransitData { private long mSerialNumber; + private long ISSN; public static boolean check(Card card) { // Mifare Desfire @@ -67,7 +68,8 @@ public ItsoTransitData(Card card) { byte[] logBytes = application.getFile(0x01).getData(); byte[] shellBytes = application.getFile(0xf).getData(); - // ISSN = Utils.byteArrayToLong(shellBytes,6,7); + // We go via hex strings because these are binary coded decimal. + ISSN = Long.parseLong(Utils.getHexString(shellBytes, 5, 2)); byte[] data; /* From 86f923d9821c5edd7ad9597e2f2f48612ddb3391 Mon Sep 17 00:00:00 2001 From: "Robert (Jamie) Munro" Date: Wed, 14 Nov 2012 23:35:10 +0000 Subject: [PATCH 06/21] Get serial number --- .../java/com/codebutler/farebot/transit/ItsoTransitData.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/com/codebutler/farebot/transit/ItsoTransitData.java b/src/main/java/com/codebutler/farebot/transit/ItsoTransitData.java index 682bce89a..ce7f9745e 100644 --- a/src/main/java/com/codebutler/farebot/transit/ItsoTransitData.java +++ b/src/main/java/com/codebutler/farebot/transit/ItsoTransitData.java @@ -70,6 +70,7 @@ public ItsoTransitData(Card card) { // We go via hex strings because these are binary coded decimal. ISSN = Long.parseLong(Utils.getHexString(shellBytes, 5, 2)); + mSerialNumber = Long.parseLong(Utils.getHexString(shellBytes, 7, 4)); byte[] data; /* From a8006214cb77cef725b3ad41f7184ff6d320592b Mon Sep 17 00:00:00 2001 From: "Robert (Jamie) Munro" Date: Wed, 14 Nov 2012 23:35:54 +0000 Subject: [PATCH 07/21] Add TODO about other card types --- .../java/com/codebutler/farebot/transit/ItsoTransitData.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/com/codebutler/farebot/transit/ItsoTransitData.java b/src/main/java/com/codebutler/farebot/transit/ItsoTransitData.java index ce7f9745e..6c575bb39 100644 --- a/src/main/java/com/codebutler/farebot/transit/ItsoTransitData.java +++ b/src/main/java/com/codebutler/farebot/transit/ItsoTransitData.java @@ -28,6 +28,8 @@ public static boolean check(Card card) { return true; } + // TODO: Support Mifare classic etc. here + return false; } From 9c447cf8c828565dd13cb1deb012054c3cdde0c7 Mon Sep 17 00:00:00 2001 From: "Robert (Jamie) Munro" Date: Thu, 15 Nov 2012 00:43:01 +0000 Subject: [PATCH 08/21] Upgrade to newer version of Farebot --- .../farebot/transit/ItsoTransitData.java | 23 +++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/codebutler/farebot/transit/ItsoTransitData.java b/src/main/java/com/codebutler/farebot/transit/ItsoTransitData.java index 6c575bb39..f64e2ecb3 100644 --- a/src/main/java/com/codebutler/farebot/transit/ItsoTransitData.java +++ b/src/main/java/com/codebutler/farebot/transit/ItsoTransitData.java @@ -3,12 +3,15 @@ */ package com.codebutler.farebot.transit; +import java.util.List; + import android.os.Parcel; + +import com.codebutler.farebot.ListItem; import com.codebutler.farebot.Utils; -import com.codebutler.farebot.mifare.Card; -import com.codebutler.farebot.mifare.DesfireApplication; -import com.codebutler.farebot.mifare.DesfireCard; -import com.codebutler.farebot.mifare.DesfireFile; +import com.codebutler.farebot.card.Card; +import com.codebutler.farebot.card.desfire.DesfireApplication; +import com.codebutler.farebot.card.desfire.DesfireCard; public class ItsoTransitData extends TransitData { private long mSerialNumber; @@ -169,4 +172,16 @@ public static TransitIdentity parseTransitIdentity(Card card) { } } + @Override + public Subscription[] getSubscriptions() { + // TODO Auto-generated method stub + return null; + } + + @Override + public List getInfo() { + // TODO Auto-generated method stub + return null; + } + } From 6cdcc2e43c028da652d2452b522010b69de0b6a4 Mon Sep 17 00:00:00 2001 From: "Robert (Jamie) Munro" Date: Sat, 3 Aug 2013 00:45:48 +0100 Subject: [PATCH 09/21] Split serial no with space and include ISSN --- .../com/codebutler/farebot/transit/ItsoTransitData.java | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/codebutler/farebot/transit/ItsoTransitData.java b/src/main/java/com/codebutler/farebot/transit/ItsoTransitData.java index f64e2ecb3..e848c6dc9 100644 --- a/src/main/java/com/codebutler/farebot/transit/ItsoTransitData.java +++ b/src/main/java/com/codebutler/farebot/transit/ItsoTransitData.java @@ -15,7 +15,7 @@ public class ItsoTransitData extends TransitData { private long mSerialNumber; - private long ISSN; + private long issn; public static boolean check(Card card) { // Mifare Desfire @@ -26,8 +26,6 @@ public static boolean check(Card card) { if (Utils.getHexString(data, 2, 3) != "633597") { */ - - return true; } @@ -74,7 +72,7 @@ public ItsoTransitData(Card card) { byte[] shellBytes = application.getFile(0xf).getData(); // We go via hex strings because these are binary coded decimal. - ISSN = Long.parseLong(Utils.getHexString(shellBytes, 5, 2)); + issn = Long.parseLong(Utils.getHexString(shellBytes, 5, 2)); mSerialNumber = Long.parseLong(Utils.getHexString(shellBytes, 7, 4)); byte[] data; @@ -119,7 +117,8 @@ public String getBalanceString() { */ @Override public String getSerialNumber() { - return Long.toString(mSerialNumber); + String stringSerialNo = String.format("%08d", mSerialNumber); + return String.format("%04d", issn) + " " + stringSerialNo.substring(0, 4) + " " + stringSerialNo.substring(4); } /* From 8c16b5cae95f6247ddc024b1c743ee3f7fe40be4 Mon Sep 17 00:00:00 2001 From: "Robert (Jamie) Munro" Date: Sat, 3 Aug 2013 00:50:35 +0100 Subject: [PATCH 10/21] Make directoryBytes, logs and shellBytes properties of the object Split logs into 4 arrays of 48 bytes each. --- .../farebot/transit/ItsoTransitData.java | 34 +++++++++++++++++-- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/codebutler/farebot/transit/ItsoTransitData.java b/src/main/java/com/codebutler/farebot/transit/ItsoTransitData.java index e848c6dc9..aa1b31402 100644 --- a/src/main/java/com/codebutler/farebot/transit/ItsoTransitData.java +++ b/src/main/java/com/codebutler/farebot/transit/ItsoTransitData.java @@ -3,6 +3,7 @@ */ package com.codebutler.farebot.transit; +import java.util.Arrays; import java.util.List; import android.os.Parcel; @@ -16,6 +17,9 @@ public class ItsoTransitData extends TransitData { private long mSerialNumber; private long issn; + private byte[] directoryBytes; + private byte[][] logs; + private byte[] shellBytes; public static boolean check(Card card) { // Mifare Desfire @@ -67,9 +71,9 @@ public ItsoTransitData(Card card) { // See page 100 of // http://www.itso.org.uk/content/Specification/Spec_v2.1.4/ITSO_TS_1000-10_V2_1_4_2010-02.pdf - byte[] directoryBytes = application.getFile(0x00).getData(); - byte[] logBytes = application.getFile(0x01).getData(); - byte[] shellBytes = application.getFile(0xf).getData(); + directoryBytes = application.getFile(0x00).getData(); + logs = divideArray(application.getFile(0x01).getData(), 48); + shellBytes = application.getFile(0xf).getData(); // We go via hex strings because these are binary coded decimal. issn = Long.parseLong(Utils.getHexString(shellBytes, 5, 2)); @@ -183,4 +187,28 @@ public List getInfo() { return null; } + /** + * Divide an array of bytes into equal sized chunks + * + * Taken from: http://stackoverflow.com/a/3405233/3408 + * + * @param source The array to divide + * @param chunksize Number of bytes to put in each chunk + * @return + */ + public static byte[][] divideArray(byte[] source, int chunksize) { + + byte[][] ret = new byte[(int) Math.ceil(source.length + / (double) chunksize)][chunksize]; + + int start = 0; + + for (int i = 0; i < ret.length; i++) { + ret[i] = Arrays.copyOfRange(source, start, start + chunksize); + start += chunksize; + } + + return ret; + } + } From 2a5d93bfa1bb9759acad3189c3a3d2b4955f3e2a Mon Sep 17 00:00:00 2001 From: "Robert (Jamie) Munro" Date: Mon, 5 Aug 2013 09:38:03 +0100 Subject: [PATCH 11/21] Add ItsoTrip subclass and populate getTrips We can now see two trips and what dates they are on. --- .../farebot/transit/ItsoTransitData.java | 120 +++++++++++++++++- 1 file changed, 119 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/codebutler/farebot/transit/ItsoTransitData.java b/src/main/java/com/codebutler/farebot/transit/ItsoTransitData.java index aa1b31402..9bde4f61f 100644 --- a/src/main/java/com/codebutler/farebot/transit/ItsoTransitData.java +++ b/src/main/java/com/codebutler/farebot/transit/ItsoTransitData.java @@ -133,7 +133,22 @@ public String getSerialNumber() { @Override public Trip[] getTrips() { // TODO Auto-generated method stub - return null; + Trip[] trips = new Trip[logs.length]; + + int tripCount = 0; + + for(byte[] logEntry : logs) { + //Util.logEntry; + long minutes = (0xFF & logEntry[4]) * 65536 + (0xFF & logEntry[5]) * 256 + (0xFF & logEntry[6]); + if (minutes > 0) { + trips[tripCount] = new ItsoTrip(minutes * 60 + 852076800L); // 852076800L is the timestamp of 1st Jan 1997 + tripCount++; + } + // .setRoute() + // .setAgency() + // .setMode() etc. + } + return Arrays.copyOfRange(trips, 0, tripCount); } /* @@ -211,4 +226,107 @@ public static byte[][] divideArray(byte[] source, int chunksize) { return ret; } + public static class ItsoTrip extends Trip { + + private final long mTimestamp; + + public ItsoTrip (Long startTime) { + mTimestamp = startTime; + } + + @Override + public int describeContents() { + // TODO Auto-generated method stub + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + // TODO Auto-generated method stub + + } + + @Override + public long getTimestamp() { + return mTimestamp; + } + + @Override + public long getExitTimestamp() { + // TODO Auto-generated method stub + return 0; + } + + @Override + public String getRouteName() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getAgencyName() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getShortAgencyName() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getFareString() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getBalanceString() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getStartStationName() { + // TODO Auto-generated method stub + return null; + } + + @Override + public Station getStartStation() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getEndStationName() { + // TODO Auto-generated method stub + return null; + } + + @Override + public Station getEndStation() { + // TODO Auto-generated method stub + return null; + } + + @Override + public double getFare() { + // TODO Auto-generated method stub + return 0; + } + + @Override + public Mode getMode() { + return Mode.BUS; + } + + @Override + public boolean hasTime() { + // TODO Auto-generated method stub + return false; + } + } + } From 6cd74bb863e161fb2125c27d82dba0b8c7e4647f Mon Sep 17 00:00:00 2001 From: "Robert (Jamie) Munro" Date: Tue, 6 Aug 2013 10:30:26 +0100 Subject: [PATCH 12/21] Add 2 Oxford bus companies and some routes Display the hex for unknown companies and routes --- .../farebot/transit/ItsoTransitData.java | 66 ++++++++++++++----- 1 file changed, 51 insertions(+), 15 deletions(-) diff --git a/src/main/java/com/codebutler/farebot/transit/ItsoTransitData.java b/src/main/java/com/codebutler/farebot/transit/ItsoTransitData.java index 9bde4f61f..ae8745385 100644 --- a/src/main/java/com/codebutler/farebot/transit/ItsoTransitData.java +++ b/src/main/java/com/codebutler/farebot/transit/ItsoTransitData.java @@ -4,7 +4,11 @@ package com.codebutler.farebot.transit; import java.util.Arrays; +import java.util.HashMap; import java.util.List; +import java.util.Map; + +import net.kazzz.felica.lib.Util; import android.os.Parcel; @@ -133,7 +137,7 @@ public String getSerialNumber() { @Override public Trip[] getTrips() { // TODO Auto-generated method stub - Trip[] trips = new Trip[logs.length]; + ItsoTrip[] trips = new ItsoTrip[logs.length]; int tripCount = 0; @@ -142,11 +146,10 @@ public Trip[] getTrips() { long minutes = (0xFF & logEntry[4]) * 65536 + (0xFF & logEntry[5]) * 256 + (0xFF & logEntry[6]); if (minutes > 0) { trips[tripCount] = new ItsoTrip(minutes * 60 + 852076800L); // 852076800L is the timestamp of 1st Jan 1997 + trips[tripCount].setAgency((0xFF & logEntry[21]) * 256 + (0xFF & logEntry[22])); + trips[tripCount].setRoute((0xFF & logEntry[23]) * 256 + (0xFF & logEntry[24])); tripCount++; } - // .setRoute() - // .setAgency() - // .setMode() etc. } return Arrays.copyOfRange(trips, 0, tripCount); } @@ -226,13 +229,15 @@ public static byte[][] divideArray(byte[] source, int chunksize) { return ret; } - public static class ItsoTrip extends Trip { + public static class ItsoTrip extends Trip { - private final long mTimestamp; + private final long mTimestamp; + private int route; + private int agency; - public ItsoTrip (Long startTime) { - mTimestamp = startTime; - } + public ItsoTrip (Long startTime) { + mTimestamp = startTime; + } @Override public int describeContents() { @@ -257,22 +262,53 @@ public long getExitTimestamp() { return 0; } + public ItsoTrip setRoute(int routeID) { + this.route = routeID; + return this; + } + + private static Map routes = new HashMap() {{ + put(0x1fff, "3"); + put(0x27ff, "4"); + put(0x22bf, "4A"); + put(0x233f, "4C"); + put(0x2fff, "5"); + put(0x087f, "11"); + put(0x08ff, "13"); + put(0x28ff, "U1"); + put(0xC07f, "S1"); + put(0xe047, "X13"); + }}; + @Override public String getRouteName() { - // TODO Auto-generated method stub - return null; + if (routes.containsKey(route)) { + return routes.get(route); + } + return "Unknown Route: " + Util.getHexString(Util.toBytes(route)); + } + + private static Map agencys = new HashMap() {{ + put(0x0000, "Stagecoach"); + put(0x206c, "Oxford Bus company"); + }}; + + public ItsoTrip setAgency(int agencyID) { + this.agency = agencyID; + return this; } @Override public String getAgencyName() { - // TODO Auto-generated method stub - return null; + if (agencys.containsKey(agency)) { + return agencys.get(agency); + } + return "Unknown operator: " + Util.getHexString(Util.toBytes(agency)); } @Override public String getShortAgencyName() { - // TODO Auto-generated method stub - return null; + return getAgencyName(); } @Override From 7c12b41c317eb8065a1765210b06f43b265e5748 Mon Sep 17 00:00:00 2001 From: "Robert (Jamie) Munro" Date: Tue, 6 Aug 2013 23:37:03 +0100 Subject: [PATCH 13/21] Use SparseArray rather than HashMap for data --- .../farebot/transit/ItsoTransitData.java | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/src/main/java/com/codebutler/farebot/transit/ItsoTransitData.java b/src/main/java/com/codebutler/farebot/transit/ItsoTransitData.java index ae8745385..4c245dcc4 100644 --- a/src/main/java/com/codebutler/farebot/transit/ItsoTransitData.java +++ b/src/main/java/com/codebutler/farebot/transit/ItsoTransitData.java @@ -4,13 +4,12 @@ package com.codebutler.farebot.transit; import java.util.Arrays; -import java.util.HashMap; import java.util.List; -import java.util.Map; import net.kazzz.felica.lib.Util; import android.os.Parcel; +import android.util.SparseArray; import com.codebutler.farebot.ListItem; import com.codebutler.farebot.Utils; @@ -267,7 +266,7 @@ public ItsoTrip setRoute(int routeID) { return this; } - private static Map routes = new HashMap() {{ + private static SparseArray routes = new SparseArray() {{ put(0x1fff, "3"); put(0x27ff, "4"); put(0x22bf, "4A"); @@ -282,13 +281,10 @@ public ItsoTrip setRoute(int routeID) { @Override public String getRouteName() { - if (routes.containsKey(route)) { - return routes.get(route); - } - return "Unknown Route: " + Util.getHexString(Util.toBytes(route)); + return routes.get(route, "Unknown Route: " + Util.getHexString(Util.toBytes(route))); } - private static Map agencys = new HashMap() {{ + private static SparseArray agencys = new SparseArray() {{ put(0x0000, "Stagecoach"); put(0x206c, "Oxford Bus company"); }}; @@ -300,10 +296,7 @@ public ItsoTrip setAgency(int agencyID) { @Override public String getAgencyName() { - if (agencys.containsKey(agency)) { - return agencys.get(agency); - } - return "Unknown operator: " + Util.getHexString(Util.toBytes(agency)); + return agencys.get(agency, "Unknown operator: " + Util.getHexString(Util.toBytes(agency))); } @Override From 817f5a81595c3e45e38686609b88fa7ad2298516 Mon Sep 17 00:00:00 2001 From: "Robert (Jamie) Munro" Date: Wed, 7 Aug 2013 00:05:34 +0100 Subject: [PATCH 14/21] Sort returned trips --- .../farebot/transit/ItsoTransitData.java | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/codebutler/farebot/transit/ItsoTransitData.java b/src/main/java/com/codebutler/farebot/transit/ItsoTransitData.java index 4c245dcc4..6abc3c0ef 100644 --- a/src/main/java/com/codebutler/farebot/transit/ItsoTransitData.java +++ b/src/main/java/com/codebutler/farebot/transit/ItsoTransitData.java @@ -150,7 +150,9 @@ public Trip[] getTrips() { tripCount++; } } - return Arrays.copyOfRange(trips, 0, tripCount); + trips = Arrays.copyOfRange(trips, 0, tripCount); + Arrays.sort(trips); + return trips; } /* @@ -228,7 +230,7 @@ public static byte[][] divideArray(byte[] source, int chunksize) { return ret; } - public static class ItsoTrip extends Trip { + public static class ItsoTrip extends Trip implements Comparable { private final long mTimestamp; private int route; @@ -356,6 +358,17 @@ public boolean hasTime() { // TODO Auto-generated method stub return false; } + + @Override + public int compareTo(ItsoTrip another) { + if (this.mTimestamp > another.mTimestamp) { + return -1; + } else if (this.mTimestamp < another.mTimestamp) { + return 1; + } else { + return 0; + } + } } } From ca782d72162d259666225b5bfe5c64e6552b15b1 Mon Sep 17 00:00:00 2001 From: "Robert (Jamie) Munro" Date: Wed, 7 Aug 2013 00:08:16 +0100 Subject: [PATCH 15/21] Make ItsoTrip parcelable --- .../farebot/transit/ItsoTransitData.java | 23 ++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/codebutler/farebot/transit/ItsoTransitData.java b/src/main/java/com/codebutler/farebot/transit/ItsoTransitData.java index 6abc3c0ef..e90ff5fa7 100644 --- a/src/main/java/com/codebutler/farebot/transit/ItsoTransitData.java +++ b/src/main/java/com/codebutler/farebot/transit/ItsoTransitData.java @@ -9,6 +9,7 @@ import net.kazzz.felica.lib.Util; import android.os.Parcel; +import android.os.Parcelable; import android.util.SparseArray; import com.codebutler.farebot.ListItem; @@ -248,8 +249,9 @@ public int describeContents() { @Override public void writeToParcel(Parcel dest, int flags) { - // TODO Auto-generated method stub - + dest.writeLong(mTimestamp); + dest.writeInt(route); + dest.writeInt(agency); } @Override @@ -369,6 +371,21 @@ public int compareTo(ItsoTrip another) { return 0; } } - } + protected ItsoTrip(Parcel in) { + mTimestamp = in.readLong(); + route = in.readInt(); + agency = in.readInt(); + } + + public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { + public ItsoTrip createFromParcel(Parcel in) { + return new ItsoTrip(in); + } + + public ItsoTrip[] newArray(int size) { + return new ItsoTrip[size]; + } + }; + } } From cb28e8ef263a2770171e09ff1fda041b2b4c11d1 Mon Sep 17 00:00:00 2001 From: "Robert (Jamie) Munro" Date: Wed, 7 Aug 2013 22:46:52 +0100 Subject: [PATCH 16/21] Add 1 more bus company and 9 more routes I now have all 3 companies for which my ticket is valid Route 300 thanks to @pandalion --- .../codebutler/farebot/transit/ItsoTransitData.java | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/codebutler/farebot/transit/ItsoTransitData.java b/src/main/java/com/codebutler/farebot/transit/ItsoTransitData.java index e90ff5fa7..4ab8f7e51 100644 --- a/src/main/java/com/codebutler/farebot/transit/ItsoTransitData.java +++ b/src/main/java/com/codebutler/farebot/transit/ItsoTransitData.java @@ -271,15 +271,24 @@ public ItsoTrip setRoute(int routeID) { } private static SparseArray routes = new SparseArray() {{ + put(0x0fff, "1"); put(0x1fff, "3"); put(0x27ff, "4"); put(0x22bf, "4A"); put(0x233f, "4C"); put(0x2fff, "5"); + put(0x47ff, "8"); + put(0x083f, "10"); put(0x087f, "11"); put(0x08ff, "13"); - put(0x28ff, "U1"); + put(0xc18d, "66"); + put(0x1801, "300"); + put(0x2001, "400"); put(0xC07f, "S1"); + put(0xc87f, "T1"); + put(0xc8ff, "T3"); + put(0x28ff, "U1"); + put(0x29bf, "U5"); put(0xe047, "X13"); }}; @@ -291,6 +300,7 @@ public String getRouteName() { private static SparseArray agencys = new SparseArray() {{ put(0x0000, "Stagecoach"); put(0x206c, "Oxford Bus company"); + put(0x207f, "Thames Travel"); }}; public ItsoTrip setAgency(int agencyID) { From edbcd7249539e675cad00f73f4c6b7bbe938c29f Mon Sep 17 00:00:00 2001 From: "Robert (Jamie) Munro" Date: Thu, 8 Aug 2013 10:19:13 +0100 Subject: [PATCH 17/21] Remove commented out bits copied from clipper --- .../farebot/transit/ItsoTransitData.java | 31 ------------------- 1 file changed, 31 deletions(-) diff --git a/src/main/java/com/codebutler/farebot/transit/ItsoTransitData.java b/src/main/java/com/codebutler/farebot/transit/ItsoTransitData.java index 4ab8f7e51..9cf053261 100644 --- a/src/main/java/com/codebutler/farebot/transit/ItsoTransitData.java +++ b/src/main/java/com/codebutler/farebot/transit/ItsoTransitData.java @@ -54,16 +54,6 @@ public void writeToParcel(Parcel arg0, int arg1) { } public ItsoTransitData(Parcel parcel) { - /* - * mSerialNumber = parcel.readLong(); mBalance = (short) - * parcel.readLong(); - * - * mTrips = new ClipperTrip[parcel.readInt()]; - * parcel.readTypedArray(mTrips, ClipperTrip.CREATOR); - * - * mRefills = new ClipperRefill[parcel.readInt()]; - * parcel.readTypedArray(mRefills, ClipperRefill.CREATOR); - */ } public ItsoTransitData(Card card) { @@ -83,27 +73,6 @@ public ItsoTransitData(Card card) { issn = Long.parseLong(Utils.getHexString(shellBytes, 5, 2)); mSerialNumber = Long.parseLong(Utils.getHexString(shellBytes, 7, 4)); - byte[] data; - /* - * try { data = - * desfireCard.getApplication(0x1602a0).getFile(0x08).getData(); - * mSerialNumber = Utils.byteArrayToLong(data, 1, 4); } catch - * (Exception ex) { throw new - * RuntimeException("Error parsing Clipper serial", ex); } - * - * try { data = - * desfireCard.getApplication(0x9011f2).getFile(0x02).getData(); - * mBalance = (short) (((0xFF & data[18]) << 8) | (0xFF & - * data[19])); } catch (Exception ex) { throw new - * RuntimeException("Error parsing Clipper balance", ex); } - * - * try { mTrips = parseTrips(desfireCard); } catch (Exception ex) { - * throw new RuntimeException("Error parsing Clipper trips", ex); } - * - * try { mRefills = parseRefills(desfireCard); } catch (Exception - * ex) { throw new RuntimeException("Error parsing Clipper refills", - * ex); } - */ } } From b40e96f8ccbcf3a04029c472ca827ccba4d251ac Mon Sep 17 00:00:00 2001 From: "Robert (Jamie) Munro" Date: Thu, 8 Aug 2013 10:20:21 +0100 Subject: [PATCH 18/21] Save raw sector data --- .../java/com/codebutler/farebot/transit/ItsoTransitData.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/com/codebutler/farebot/transit/ItsoTransitData.java b/src/main/java/com/codebutler/farebot/transit/ItsoTransitData.java index 9cf053261..6ea4f0ad3 100644 --- a/src/main/java/com/codebutler/farebot/transit/ItsoTransitData.java +++ b/src/main/java/com/codebutler/farebot/transit/ItsoTransitData.java @@ -24,6 +24,7 @@ public class ItsoTransitData extends TransitData { private byte[] directoryBytes; private byte[][] logs; private byte[] shellBytes; + private byte[][] sectorData; public static boolean check(Card card) { // Mifare Desfire @@ -73,6 +74,10 @@ public ItsoTransitData(Card card) { issn = Long.parseLong(Utils.getHexString(shellBytes, 5, 2)); mSerialNumber = Long.parseLong(Utils.getHexString(shellBytes, 7, 4)); + sectorData = new byte[14][]; + for (int sector=0; sector<13; sector++) { + sectorData[sector] = application.getFile(14-sector).getData(); + } } } From 6192adadd0a6b32bfa4615c562bc37693eed4371 Mon Sep 17 00:00:00 2001 From: "Robert (Jamie) Munro" Date: Thu, 8 Aug 2013 10:22:51 +0100 Subject: [PATCH 19/21] Look for cardholder name sector & extract name --- .../codebutler/farebot/transit/ItsoTransitData.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/main/java/com/codebutler/farebot/transit/ItsoTransitData.java b/src/main/java/com/codebutler/farebot/transit/ItsoTransitData.java index 6ea4f0ad3..42f1d9f0a 100644 --- a/src/main/java/com/codebutler/farebot/transit/ItsoTransitData.java +++ b/src/main/java/com/codebutler/farebot/transit/ItsoTransitData.java @@ -10,6 +10,7 @@ import android.os.Parcel; import android.os.Parcelable; +import android.util.Log; import android.util.SparseArray; import com.codebutler.farebot.ListItem; @@ -25,6 +26,8 @@ public class ItsoTransitData extends TransitData { private byte[][] logs; private byte[] shellBytes; private byte[][] sectorData; + private String firstName; + private String lastName; public static boolean check(Card card) { // Mifare Desfire @@ -77,6 +80,15 @@ public ItsoTransitData(Card card) { sectorData = new byte[14][]; for (int sector=0; sector<13; sector++) { sectorData[sector] = application.getFile(14-sector).getData(); + + byte[] thisSector = sectorData[sector]; + if (Utils.getHexString(thisSector, 1, 3).equals("41ff00")) { + byte firstNameLength = thisSector[29]; + firstName = new String (thisSector, 30, (int) firstNameLength); + byte lastNameLength = thisSector[30 + firstNameLength]; + lastName = new String (thisSector, 31 + firstNameLength, lastNameLength); + Log.i("CardholderName",firstName + " / " + lastName); + } } } } From 1ad7e3f280e7d3536e049872c77011cd10288a99 Mon Sep 17 00:00:00 2001 From: "Robert (Jamie) Munro" Date: Sat, 10 Aug 2013 00:51:19 +0100 Subject: [PATCH 20/21] Extract Cardholder DOB --- .../java/com/codebutler/farebot/transit/ItsoTransitData.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/com/codebutler/farebot/transit/ItsoTransitData.java b/src/main/java/com/codebutler/farebot/transit/ItsoTransitData.java index 42f1d9f0a..eda2c3093 100644 --- a/src/main/java/com/codebutler/farebot/transit/ItsoTransitData.java +++ b/src/main/java/com/codebutler/farebot/transit/ItsoTransitData.java @@ -28,6 +28,7 @@ public class ItsoTransitData extends TransitData { private byte[][] sectorData; private String firstName; private String lastName; + private String dob; public static boolean check(Card card) { // Mifare Desfire @@ -88,6 +89,10 @@ public ItsoTransitData(Card card) { byte lastNameLength = thisSector[30 + firstNameLength]; lastName = new String (thisSector, 31 + firstNameLength, lastNameLength); Log.i("CardholderName",firstName + " / " + lastName); + dob = Util.getHexString(thisSector, 7, 2) + "-" + + Util.getHexString(thisSector, 9, 1) + "-" + + Util.getHexString(thisSector, 10, 1); + Log.i("CardholderDOB",dob); } } } From c012cc3157560b174b79b780e0339cc92b816486 Mon Sep 17 00:00:00 2001 From: "Robert (Jamie) Munro" Date: Mon, 23 Sep 2013 16:59:20 +0100 Subject: [PATCH 21/21] Add some more routes --- .../java/com/codebutler/farebot/transit/ItsoTransitData.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/com/codebutler/farebot/transit/ItsoTransitData.java b/src/main/java/com/codebutler/farebot/transit/ItsoTransitData.java index eda2c3093..d3b50a59b 100644 --- a/src/main/java/com/codebutler/farebot/transit/ItsoTransitData.java +++ b/src/main/java/com/codebutler/farebot/transit/ItsoTransitData.java @@ -269,8 +269,10 @@ public ItsoTrip setRoute(int routeID) { put(0x233f, "4C"); put(0x2fff, "5"); put(0x47ff, "8"); + put(0x4fff, "9"); put(0x083f, "10"); put(0x087f, "11"); + put(0x0899, "12C"); put(0x08ff, "13"); put(0xc18d, "66"); put(0x1801, "300"); @@ -280,7 +282,9 @@ public ItsoTrip setRoute(int routeID) { put(0xc8ff, "T3"); put(0x28ff, "U1"); put(0x29bf, "U5"); + put(0xe0ff, "X3"); put(0xe047, "X13"); + put(0xe0c1, "X30"); }}; @Override