	public static boolean parse(byte[] buffer, HarleyData hd) {
		byte[] in;
		int x;
		int y;
		in = bytes_to_hex(buffer);
		if (crc(in) != (byte)0xc4) {
			hd.setBadCRC(buffer);
			return false;
		}
		x = y = 0;
		if (in.length >= 4)
			x = ((in[0] << 24) & 0xff000000) |
			    ((in[1] << 16) & 0x00ff0000) |
			    ((in[2] <<  8) & 0x0000ff00) |
			     (in[3]        & 0x000000ff);
		if (in.length >= 6)
			y = ((in[4] << 8) & 0x0000ff00) |
			     (in[5]       & 0x000000ff);
		if (x == 0x281b1002)
			hd.setRPM(y);
		else if (x == 0x48291002)
			hd.setSpeed(y);
		else if (x == 0xa8491010)
			hd.setEngineTemp((int)in[4] & 0xff);
		else if (x == 0xa83b1003) {
			if (in[4] != 0) {
				int gear = 0;
				while ((in[4] >>= 1) != 0)
					gear++;
				hd.setGear(gear);
			} else
				hd.setGear(-1);
		} else if ((x == 0x48da4039) && ((in[4] & 0xfc) == 0))
			hd.setTurnSignals(in[4] & 0x03);
		else if ((x & 0xffffff7f) == 0xa8691006) {
			odolast = y - odolast;
			if (odolast < 0)	
				odolast += 65536;
			odoaccum += odolast;
			odolast = y;
			hd.setOdometer(odoaccum);
		} else if ((x & 0xffffff7f) == 0xa883100a) {
			fuellast = y - fuellast;
			if (fuellast < 0)	
				fuellast += 65536;
			fuelaccum += fuellast;
			fuellast = y;
			hd.setFuel(fuelaccum);
		} else if ((x == 0xa8836112) && ((in[4] & 0xd0) == 0xd0))
			hd.setFuelGauge(in[4] & 0x0f);
		else if ((x & 0xffffff5d) == 0x483b4000) {
			if ((in[3] & 0x20) == 0x20)
				hd.setNeutral(false);
			else if ((in[3] & 0xa0) == 0xa0)
				hd.setNeutral(true);
			hd.setClutch((in[3] & 0x80) != 0);
		} else if ((x & 0xffffff7f) == 0x68881003) {
			if ((in[3] & 0x80) != 0)
				hd.setCheckEngine(true);
			else
				hd.setCheckEngine(false);
		} else if (x == 0x0c10f13c) {
		} else if (x == 0x0cf1107c) {
			switch (in[4]) {
			case 0x01:
				System.arraycopy(in, 5, ecmPN, 0, 6);
				break;
			case 0x02:
				System.arraycopy(in, 5, ecmPN, 6, 6);
				hd.setECMPN(new String(ecmPN).trim());
				break;
			case 0x03:
				System.arraycopy(in, 5, ecmCalID, 0, 6);
				break;
			case 0x04:
				System.arraycopy(in, 5, ecmCalID, 6, 6);
				hd.setECMCalID(new String(ecmCalID).trim());
				break;
			case 0x0b:
				hd.setECMSWLevel((int)in[5] & 0xff);
				break;
			case 0x0f:
				System.arraycopy(in, 5, vin, 0, 6);
				break;
			case 0x10:
				System.arraycopy(in, 5, vin, 6, 6);
				break;
			case 0x11:
				System.arraycopy(in, 5, vin, 12, 5);
				hd.setVIN(new String(vin).trim());
				break;
			default:
				hd.setUnknown(buffer);
			}
		} else if (x == 0x6cfef119)
			if (D) Log.d(TAG, "DTC start");
		else if ((x & 0xffff0fff) == 0x6cf10059) {
			int dtc = (((int)in[4] & 0xff) << 8) | ((int)in[5] & 0xff);
			if (in[2] == 0x10) {
				if (D) Log.d(TAG, "historic DTC: 0x" + Integer.toString(dtc, 16));
				hd.addHistoricDTC(dtc);
			} else if (in[2] == 0x40) {
				if (D) Log.d(TAG, "current DTC: 0x" + Integer.toString(dtc, 16));
				hd.addCurrentDTC(dtc);
			} else
				hd.setUnknown(buffer);
		} else if (x == 0x6c10f114)
			if (D) Log.d(TAG, "DTC clear");
		else
			hd.setUnknown(buffer);
		return true;
	}

	public static boolean parse(byte[] buffer, HarleyData hd) {
		byte[] in;
		int x;
		int y;
		in = bytes_to_hex(buffer);
		hd.setRaw(buffer);
		if (crc(in) != (byte)0xc4) {
			hd.setBadCRC(buffer);
			return false;
		}
		x = y = 0;
		if (in.length >= 4)
			x = ((in[0] << 24) & 0xff000000) |
			    ((in[1] << 16) & 0x00ff0000) |
			    ((in[2] <<  8) & 0x0000ff00) |
			     (in[3]        & 0x000000ff);
		if (in.length >= 6)
			y = ((in[4] << 8) & 0x0000ff00) |
			     (in[5]       & 0x000000ff);
		if (x == 0x281b1002)
			hd.setRPM(y);
		else if (x == 0x48291002)
			hd.setSpeed(y);
		else if (x == 0xa8491010)
			hd.setEngineTemp((int)in[4] & 0xff);
		else if (x == 0xa83b1003) {
			if (in[4] != 0) {
				int gear = 0;
				while ((in[4] >>= 1) != 0)
					gear++;
				hd.setGear(gear);
			} else
				hd.setGear(-1);
		} else if ((x == 0x48da4039) && ((in[4] & 0xfc) == 0))
			hd.setTurnSignals(in[4] & 0x03);
		else if ((x & 0xffffff7f) == 0xa8691006) {
			odolast = y - odolast;
			if (odolast < 0)	
				odolast += 65536;
			odoaccum += odolast;
			odolast = y;
			hd.setOdometer(odoaccum);
		} else if ((x & 0xffffff7f) == 0xa883100a) {
			fuellast = y - fuellast;
			if (fuellast < 0)	
				fuellast += 65536;
			fuelaccum += fuellast;
			fuellast = y;
			hd.setFuel(fuelaccum);
		} else if ((x == 0xa8836112) && ((in[4] & 0xd0) == 0xd0))
			hd.setFuelGauge(in[4] & 0x0f);
		else if ((x & 0xffffff5d) == 0x483b4000) {
			if ((in[3] & 0x20) == 0x20)
				hd.setNeutral(false);
			else if ((in[3] & 0xa0) == 0xa0)
				hd.setNeutral(true);
			hd.setClutch((in[3] & 0x80) != 0);
		} else if ((x & 0xffffff7f) == 0x68881003) {
			if ((in[3] & 0x80) != 0)
				hd.setCheckEngine(true);
			else
				hd.setCheckEngine(false);
		} else if (x == 0x0c10f13c) {
		} else if (x == 0x0cf1107c) {
			switch (in[4]) {
			case 0x01:
				System.arraycopy(in, 5, ecmPN, 0, 6);
				break;
			case 0x02:
				System.arraycopy(in, 5, ecmPN, 6, 6);
				hd.setECMPN(new String(ecmPN).trim());
				break;
			case 0x03:
				System.arraycopy(in, 5, ecmCalID, 0, 6);
				break;
			case 0x04:
				System.arraycopy(in, 5, ecmCalID, 6, 6);
				hd.setECMCalID(new String(ecmCalID).trim());
				break;
			case 0x0b:
				hd.setECMSWLevel((int)in[5] & 0xff);
				break;
			case 0x0f:
				System.arraycopy(in, 5, vin, 0, 6);
				break;
			case 0x10:
				System.arraycopy(in, 5, vin, 6, 6);
				break;
			case 0x11:
				System.arraycopy(in, 5, vin, 12, 5);
				hd.setVIN(new String(vin).trim());
				break;
			default:
				hd.setUnknown(buffer);
			}
		} else if (x == 0x6cfef119) {
			if (D) Log.d(TAG, "DTC start");
		} else if ((x & 0xffff0fff) == 0x6cf10059) {
			int dtc = (((int)in[4] & 0xff) << 8) | ((int)in[5] & 0xff);
			if (in[2] == 0x10) {
				if (D) Log.d(TAG, "historic DTC: 0x" + Integer.toString(dtc, 16));
				hd.addHistoricDTC(dtc);
			} else if (in[2] == 0x40) {
				if (D) Log.d(TAG, "current DTC: 0x" + Integer.toString(dtc, 16));
				hd.addCurrentDTC(dtc);
			} else
				hd.setUnknown(buffer);
		} else if (x == 0x6c10f114)
			if (D) Log.d(TAG, "DTC clear");
		else
			hd.setUnknown(buffer);
		return true;
	}
