package com.ai.ced.bluetooth;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Arrays;
import java.util.HashMap;

import ToBmp.Wlt;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.text.format.Time;
import android.util.Log;

import com.lzw.qlhs.Wlt2bmp;
import com.sdses.CRC16;
import com.sdses.Common;
import com.sdses.Communication;
import com.sdses.Files;
import com.sdses.ForeignerResidencePermitData;
import com.sdses.Id2Data;
import com.sdses.Util;
import com.sdses.globalEnum;

/**
 * 因为神思抄袭了卡尔的64位so包，wlt2map.so，
 * 所以神思的BtReaderClient.jar包里也含了和卡尔一模一样的一个package和class，
 * 导致和卡尔合用的情况下cordova build报重复定义类。
 * 解决如下:
 * (1)当app需要卡尔和神思2家的时候，用上图中1里的BtReaderClient.jar，
 *    然后写cordova插件的时候，需要把BtReaderClient.java这个类拷进去，这个类其实就是从jar包里提取出来的。
 * (2)当app只用神思一家的时候，只需要加载上图中2的BtReaderClient-wlt2bmp-in.jar包
 * @author xmh
 *
 */
public class BtReaderClient {
	
	// 成员变量
	private BluetoothDevice mDevice;
	private Context context;
	private Communication cc;
	private boolean bInit = false;
	private byte[] pNo = new byte[32];
	public byte[] samid = new byte[8];
	public static String tmpStr = "";
	private static Files ioFile;
	public long gRq, gBh;
	public boolean bShellOk = false;
	private static  int maxRecvBuffLen = 5120;
	private static byte[] sendBuff=new byte[1024];
	private static HashMap<String, Object> returnvalue = new HashMap<String, Object>();
	public byte[] wzTxt = new byte[256];
	public boolean bHaveRegReceiver = false;
	public boolean b100WS = false;

	public final static HashMap<String,String > CountryMap = new HashMap<String,String>(){{ 
		put("AFG","阿富汗");
		put("ALA","奥兰群岛");
		put("ALB","阿尔巴尼亚");
		put("DZA","阿尔及利亚");
		put("ASM","美属萨摩亚");
		put("AND","安道尔");
		put("AGO","安哥拉");
		put("AIA","安圭拉");
		put("ATA","南极洲");
		put("ATG","安提瓜和巴布达");
		put("ARG","阿根廷");
		put("ARM","亚美尼亚");
		put("ABW","阿鲁巴");
		put("AUS","澳大利亚");
		put("AUT","奥地利");
		put("AZE","阿塞拜疆");
		put("BHS","巴哈马");
		put("BHR","巴林");
		put("BGD","孟加拉国");
		put("BRB","巴巴多斯");
		put("BLR","白俄罗斯");
		put("BEL","比利时");
		put("BLZ","伯利兹");
		put("BEN","贝宁");
		put("BMU","百慕大");
		put("BTN","不丹");
		put("BOL","多民族玻利维亚国");
		put("BES","博内尔岛、圣尤斯特歇斯岛和萨巴岛");
		put("BIH","波斯尼亚和黑塞哥维那");
		put("BWA","博茨瓦纳");
		put("BVT","布韦岛");
		put("BRA","巴西");
		put("IOT","英属印度洋领地");
		put("BRN","文莱达鲁萨兰国");
		put("BGR","保加利亚");
		put("BFA","布基纳法索");
		put("BDI","布隆迪");
		put("CPV","佛得角");
		put("KHM","柬埔寨");
		put("CMR","喀麦隆");
		put("CAN","加拿大");
		put("CYM","开曼群岛");
		put("CAF","中非共和国");
		put("TCD","乍得");
		put("CHL","智利");
		put("CHN","中国");
		put("CXR","圣诞岛");
		put("CCK","科科斯（基灵）群岛");
		put("COL","哥伦比亚");
		put("COM","科摩罗");
		put("COG","刚果");
		put("COD","刚果民主共和国");
		put("COK","库克群岛");
		put("CRI","哥斯达黎加");
		put("CIV","科特迪瓦");
		put("HRV","克罗地亚");
		put("CUB","古巴");
		put("CUW","库拉索");
		put("CYP","塞浦路斯");
		put("CZE","捷克共和国");
		put("DNK","丹麦");
		put("DJI","吉布提");
		put("DMA","多米尼加");
		put("DOM","多米尼加共和国");
		put("ECU","厄瓜多尔");
		put("EGY","埃及");
		put("SLV","萨尔瓦多");
		put("GNQ","赤道几内亚");
		put("ERI","厄立特里亚");
		put("EST","爱沙尼亚");
		put("ETH","埃塞俄比亚");
		put("FLK","福克兰群岛（马尔维纳斯）");
		put("FRO","法罗群岛");
		put("FJI","斐济");
		put("FIN","芬兰");
		put("FRA","法国");
		put("GUF","法属圭亚那");
		put("PYF","法属玻利尼西亚");
		put("ATF","法属南领地");
		put("GAB","加蓬");
		put("GMB","冈比亚");
		put("GEO","格鲁吉亚");
		put("DEU","德国");
		put("GHA","加纳");
		put("GIB","直布罗陀");
		put("GRC","希腊");
		put("GRL","格陵兰");
		put("GRD","格林纳达");
		put("GLP","瓜德罗普");
		put("GUM","关岛");
		put("GTM","危地马拉");
		put("GGY","根西岛");
		put("GIN","几内亚");
		put("GNB","几内亚—比绍");
		put("GUY","圭亚那");
		put("HTI","海地");
		put("HMD","赫德岛和麦克唐纳群岛");
		put("VAT","教廷（梵蒂冈城国）");
		put("HND","洪都拉斯");
		put("HKG","中国香港特别行政区");
		put("HUN","匈牙利");
		put("ISL","冰岛");
		put("IND","印度");
		put("IDN","印度尼西亚");
		put("IRN","伊朗（伊斯兰共和国）");
		put("IRQ","伊拉克");
		put("IRL","爱尔兰");
		put("IMN","马恩岛");
		put("ISR","以色列");
		put("ITA","意大利");
		put("JAM","牙买加");
		put("JPN","日本");
		put("JEY","泽西");
		put("JOR","约旦");
		put("KAZ","哈萨克斯坦");
		put("KEN","肯尼亚");
		put("KIR","基里巴斯");
		put("PRK","朝鲜民主主义人民共和国");
		put("KOR","大韩民国");
		put("KWT","科威特");
		put("KGZ","吉尔吉斯斯坦");
		put("LAO","老挝人民民主共和国");
		put("LVA","拉脱维亚");
		put("LBN","黎巴嫩");
		put("LSO","莱索托");
		put("LBR","利比里亚");
		put("LBY","利比亚");
		put("LIE","列支敦士登");
		put("LTU","立陶宛");
		put("LUX","卢森堡");
		put("MAC","中国澳门特别行政区");
		put("MKD","前南斯拉夫马其顿共和国");
		put("MDG","马达加斯加");
		put("MWI","马拉维");
		put("MYS","马来西亚");
		put("MDV","马尔代夫");
		put("MLI","马里");
		put("MLT","马耳他");
		put("MHL","马绍尔群岛");
		put("MTQ","马提尼克");
		put("MRT","毛里塔尼亚");
		put("MUS","毛里求斯");
		put("MYT","马约特");
		put("MEX","墨西哥");
		put("FSM","密克罗尼西亚（联邦）");
		put("MDA","摩尔多瓦共和国");
		put("MCO","摩纳哥");
		put("MNG","蒙古");
		put("MNE","黑山");
		put("MSR","蒙特塞拉特");
		put("MAR","摩洛哥");
		put("MOZ","莫桑比克");
		put("MMR","缅甸");
		put("NAM","纳米尼亚");
		put("NRU","瑙鲁");
		put("NPL","尼泊尔");
		put("NLD","荷兰");
		put("ANT","荷属安的列斯");
		put("NTZ","中立区");
		put("NCL","新喀里多尼亚");
		put("NZL","新西兰");
		put("NIC","尼加拉瓜");
		put("NER","尼日尔");
		put("NGA","尼日利亚");
		put("NIU","纽埃");
		put("NFK","诺福克岛");
		put("MNP","北马里亚纳群岛");
		put("NOR","挪威");
		put("OMN","阿曼");
		put("PAK","巴基斯坦");
		put("PLW","帕劳");
		put("PSE","巴勒斯坦国");
		put("PAN","巴拿马");
		put("PNG","巴布亚新几内亚");
		put("PRY","巴拉圭");
		put("PER","秘鲁");
		put("PHL","菲律宾");
		put("PCN","皮特凯恩");
		put("POL","波兰");
		put("PRT","葡萄牙");
		put("PRI","波多黎各");
		put("QAT","卡塔尔");
		put("REU","留尼汪岛");
		put("ROU","罗马尼亚");
		put("RUS","俄罗斯联邦");
		put("RWA","卢旺达");
		put("BLM","圣巴泰勒米岛");
		put("SHN","圣赫勒拿岛、阿森松岛和特里斯坦达库尼亚群岛");
		put("KNA","圣基茨和尼维斯");
		put("LCA","圣卢西亚");
		put("MAF","圣马丁岛（法属）");
		put("SPM","圣皮埃尔和密克隆");
		put("VCT","圣文森特和格林纳丁斯");
		put("WSM","萨摩亚");
		put("SMR","圣马力诺");
		put("STP","圣多美和普林西比");
		put("SAU","沙特阿拉伯");
		put("SEN","塞内加尔");
		put("SRB","塞尔维亚");
		put("SYC","塞舌尔");
		put("SLE","塞拉利昂");
		put("SGP","新加坡");
		put("SXM","圣马丁岛（荷属）");
		put("SVK","斯洛伐克");
		put("SVN","斯洛文尼亚");
		put("SLB","所罗门群岛");
		put("SOM","索马里");
		put("ZAF","南非");
		put("SGS","南乔治亚和南桑威奇群岛");
		put("SSD","南苏丹");
		put("ESP","西班牙");
		put("LKA","斯里兰卡");
		put("SDN","苏丹");
		put("SUR","苏里南");
		put("SJM","斯瓦尔巴和扬马延群岛");
		put("SWZ","斯威士兰");
		put("SWE","瑞典");
		put("CHE","瑞士");
		put("SYR","阿拉伯叙利亚共和国");
		put("TWN","中国台湾省");
		put("TJK","塔吉克斯坦");
		put("TZA","坦桑尼亚联合共和国");
		put("THA","泰国");
		put("TLS","东蒂汶");
		put("TGO","多哥");
		put("TKL","托克劳群岛");
		put("TON","汤加");
		put("TTO","特里尼达和多巴哥");
		put("TUN","突尼斯");
		put("TUR","土耳其");
		put("TKM","土库曼斯坦");
		put("TCA","特克斯和凯科斯群岛");
		put("TUV","图瓦卢");
		put("UGA","乌干达");
		put("UKR","乌克兰");
		put("ARE","阿拉伯联合酋长国");
		put("GBR","英国公民");
		put("GBD","英国海外领土公民");
		put("GBN","英国国民（海外）");
		put("GBO","英国海外公民");
		put("GBP","英国被保护人");
		put("GBS","英国臣民");
		put("USA","美国");
		put("UMI","美国本土外小岛屿");
		put("URY","乌拉圭");
		put("UZB","乌兹别克斯坦");
		put("VUT","瓦奴阿图");
		put("VEN","委内瑞拉玻利瓦尔共和国");
		put("VNM","越南");
		put("VGB","维尔京群岛（英属）");
		put("VIR","维尔京群岛（美属）");
		put("WLF","瓦利斯和富图纳群岛");
		put("ESH","西撒哈拉");
		put("YEM","也门");
		put("ZMB","赞比亚");
		put("ZWE","津巴布韦");
	}};
	

	/**
	 * 包头
	 */
	private static final byte PAK_HEAD = 0X04;  
	/**
	 * 包尾
	 */
	private static final byte PAK_END  = 0X06;
	/**
	 * 固定长度
	 */
	private static final int  SOLID_LENGH  = 5;
	/**
	 * 加密方式
	 */
	private static final int ENCRPT = 0;
	/**
	 * 数据区位置索引
	 */
	private static final int DATA_POS_INDEX = 14;
	
	private static final int READCARD_FNUM = 0X04;
	
	private static final int READCARD_MNUM = 0X0A;
	
	private static final int HANDSHK_MNUM = 0X0;
	
	private static final int HANDSHK_FNUM = 0X01;

	private static byte lxTable[][] = { { 1, 2, 4, 3, 6, 5, 0, 7 },
			{ 4, 2, 1, 6, 5, 0, 3, 7 }, { 2, 5, 4, 6, 0, 3, 1, 7 },
			{ 5, 1, 0, 4, 2, 6, 3, 7 }, { 3, 5, 1, 0, 6, 2, 4, 7 },
			{ 5, 0, 2, 3, 4, 6, 1, 7 }, { 6, 3, 5, 2, 1, 4, 0, 7 } };

	private HashMap<String, Object> hashData = new HashMap<String, Object>();

	private BtStateCallback mBtStateCallback;

	public interface BtStateCallback {
		void onBtState(int btState, int len, Activity theThis);
	}

	private Activity This;

	public BtReaderClient(Activity theThis) {
		// mDevice = bt;
		This = theThis;
		this.context = This.getApplicationContext();
		try {
			// cc = new Communication(mDevice);
			ioFile = new Files(context);
			bInit = true;
			mBtStateCallback = null;
			IntentFilter intent = new IntentFilter();
			intent.addAction(BluetoothDevice.ACTION_ACL_CONNECTED);
			intent.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);

			This.registerReceiver(connectDevices, intent);
			bHaveRegReceiver = true;
			//03160316 Thread.sleep(2000);
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	public void connectBt(String bt_mac,String bt_name) {
		try {
			int btNameLen = bt_name.length();
			if(btNameLen == 0){
				bShellOk = false;
				disconnect();
			}else{
				if(bt_name.substring(btNameLen-2, btNameLen).equalsIgnoreCase("ws"))
					b100WS = true;
				else
					b100WS = false;
				Log.w("Comshell","In connectBt bt_name is:"+bt_name);
				Log.w("Comshell","In connectBt b100WS is:"+b100WS);
				cc = new Communication(bt_mac);
				bShellOk = cc.ccOk;
			}
		} catch (IOException e) {
			bShellOk = false;
			disconnect();
			e.printStackTrace();
		}
	}

	public void setCallBack(BtStateCallback callback) {
		this.mBtStateCallback = callback;
	}

	// if(mReceiveCallBack != null){
	// mReceiveCallBack.onReceiveData((byte[])msg.obj,(int )msg.arg1,mTty);
	// }

	private BroadcastReceiver connectDevices = new BroadcastReceiver() {
		public void onReceive(Context context, Intent intent) {
			String action = intent.getAction();
			if (action.equals(BluetoothDevice.ACTION_ACL_CONNECTED)) {
				mBtStateCallback.onBtState(Common.MESSAGE_CONNECT_SUCCEED, 0,This);
			} else if (action.equals(BluetoothDevice.ACTION_ACL_DISCONNECTED)) {
				mBtStateCallback.onBtState(Common.MESSAGE_CONNECT_LOST, 0,This);
			}
		}
	};
	public void Destroy() {
		if(bHaveRegReceiver){
			bHaveRegReceiver = false;
			This.unregisterReceiver(connectDevices);
		}
	}
	public void disconnect() {
		if(cc!=null){	
		//	This.unregisterReceiver(connectDevices);
			cc.Destroy();
		}
	}

	//***********************For ChinaUnicom**********************//
	/*public boolean id2ShakeHand(){  100WT
	    byte[] sendBuff = new byte[1024];
		byte[] recvData = new byte[4196];
	    
	    Byte encry = 0x00;
	    Byte moduleNum = 0x00;
	    Byte funcNum = 0x01;
	    int dataLen = 1;
	    sendBuff[0] =  'S';
	    

	    int nRet = sendCmdChinaUnicom(encry,moduleNum,funcNum,dataLen,sendBuff,1000,18);
	    if(nRet == 0){
			recvData = GetDataFromHash(returnvalue);
	        if(recvData[0]==0x00){
	            return true;
	        }
	    }
	    return false;
	}*/
	
	public int id2ShakeHand(){
	    byte[] sendBuff = new byte[1024];
		byte[] recvData = new byte[4196];
	    
	    Byte encry = 0x00;
	    Byte moduleNum = 0x00;
	    Byte funcNum = 0x01;
	    int dataLen = 1;
	    sendBuff[0] =  'S';

	    int nRet = sendCmdChinaUnicom(encry,moduleNum,funcNum,dataLen,sendBuff,1000);
	    Log.w("ComShell","id2ShakeHand nRet is:"+nRet);
	    if(nRet == 0){
			recvData = GetDataFromHash(returnvalue);
	        if(recvData[0]==0x00){
	        	if(GetBytesFromHash(returnvalue)>1){
	        		return recvData[1];//厂家编码；随机交互运算时确认约定算法
	        	}
	        }
	    }
	    return -1;
	}
	public boolean id2InteractionCheck(byte[] key){
	    byte[] sendBuff = new byte[1024];
		byte[] recvData = new byte[4196];
		if(!b100WS)
			return false;
	    
	    Byte encry = 0x02;
	    Byte moduleNum = 0x0A;
	    Byte funcNum = 0x06;
	    int dataLen = 8;
	    System.arraycopy(key, 0, sendBuff, 0, 8);

	    int nRet = sendCmdChinaUnicom(encry,moduleNum,funcNum,dataLen,sendBuff,1000);
	    if(nRet == 0){
			recvData = GetDataFromHash(returnvalue);
	        if(recvData[0]==0x00){
	        	return true;
	        }
	    }
	    return false;
	}
	public Id2Data  id2ReadCard(){
	    byte[] sendBuff = new byte[1024];
		byte[] recvData = new byte[4196];
		byte[] chkData = new byte[4196];
		byte[] txt = new byte[256];
		byte[] BMPDATA = new byte[1024];
	
	    Byte encry = 0x00;
	    Byte moduleNum = 0x0A;
	    Byte funcNum = 0x04;
	    int dataLen = 0;
	
	    int nRet = sendCmdChinaUnicom(encry,moduleNum,funcNum,dataLen,sendBuff,4000);
	    //int nRet = sendCmdChinaUnicom(encry,moduleNum,funcNum,dataLen,sendBuff,4000,18+1295);
	    if(nRet == 0){//命令执行成功
			int recvBuffLen = Integer.parseInt(String.valueOf(returnvalue.get("recvBuffLen")));
			Log.w("ComShell","recvBuffLen is:"+recvBuffLen);
	        if(recvBuffLen > 1000){
				recvData = GetDataFromHash(returnvalue);
				System.arraycopy(recvData, 6, chkData, 0, recvBuffLen-6);
				if(!checkId2Data(chkData,recvBuffLen-6)){
					Log.w("ComShell","checkId2Data error");
					return null;
				}
				System.arraycopy(recvData, 15, txt, 0, 256);
				System.arraycopy(recvData, 15, wzTxt, 0, 256);
				System.arraycopy(recvData, 15 + 256, BMPDATA, 0, 1024);

				Id2Data id2data = new Id2Data();
				try {
					if(GetCardTypeFlag(wzTxt)==0){
						try {
							id2data.setName(GetName(wzTxt));
							id2data.setGender(GetGender(wzTxt));
							id2data.setNation(GetNationalCode(wzTxt));
							id2data.setBirthDay(GetBirthday(wzTxt));
							id2data.setAddress(GetAddress(wzTxt));
							id2data.setIdNum(GetIndentityCard(wzTxt));
							id2data.setIssue(GetIssued(wzTxt));
							id2data.setEffDate(GetStartDate(wzTxt));
							id2data.setExpDate(GetEndDate(wzTxt));
						} catch (UnsupportedEncodingException e1) {
							// TODO Auto-generated catch block
							e1.printStackTrace();
						}
						byte[] bmpBuff = new byte[38862];
					    nRet = GetPicByBuff(BMPDATA,  bmpBuff);
						
						Bitmap bm = BitmapFactory.decodeByteArray(
								bmpBuff, 0, 38862);
						id2data.setPic(bm);
					}
				} catch (IOException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
				try {
					ioFile.WriteByteToFile("wz.txt", txt, 0, 256, false);
					ioFile.WriteByteToFile("zp.wlt", BMPDATA, 0, 1024, false);
				} catch (IOException e) {
					e.printStackTrace();
				}
				writeWltFile(BMPDATA);
				return id2data;
	        }
	    }
	    return null;
	}
	public int id2ReadCardEncrypt(byte[] encryptId2Data){//1296加密字节
	    byte[] sendBuff = new byte[1024];
		byte[] recvData = new byte[4196];

		if(!b100WS)
			return -9;
		
	    Byte encry = 0x02;
	    Byte moduleNum = 0x0A;
	    Byte funcNum = 0x07;
	    int dataLen = 0;

	    int nRet = sendCmdChinaUnicom(encry,moduleNum,funcNum,dataLen,sendBuff,4000);
	    if(nRet == 0){//命令执行成功
			int recvBuffLen = Integer.parseInt(String.valueOf(returnvalue.get("recvBuffLen")));
			Log.w("ComShell","recvBuffLen is:"+recvBuffLen);
	        if(recvBuffLen > 1000){
				recvData = GetDataFromHash(returnvalue);
				System.arraycopy(recvData, 1, encryptId2Data, 0, recvBuffLen-1);
				return 0;
	        }
	    }
	    return -1;
	}
	
	public ForeignerResidencePermitData  ReadForeignerCard(){
	    byte[] sendBuff = new byte[1024];
		byte[] recvData = new byte[4196];
		byte[] chkData = new byte[4196];
		byte[] txt = new byte[256];
		byte[] BMPDATA = new byte[1024];
	
	    Byte encry = 0x00;
	    Byte moduleNum = 0x0A;
	    Byte funcNum = 0x04;
	    int dataLen = 0;
	
	    int nRet = sendCmdChinaUnicom(encry,moduleNum,funcNum,dataLen,sendBuff,4000);
	    //int nRet = sendCmdChinaUnicom(encry,moduleNum,funcNum,dataLen,sendBuff,4000,18+1295);
	    if(nRet == 0){//命令执行成功
			int recvBuffLen = Integer.parseInt(String.valueOf(returnvalue.get("recvBuffLen")));
			Log.w("ComShell","recvBuffLen is:"+recvBuffLen);
	        if(recvBuffLen > 1000){
				recvData = GetDataFromHash(returnvalue);
				System.arraycopy(recvData, 6, chkData, 0, recvBuffLen-6);
				if(!checkId2Data(chkData,recvBuffLen-6)){
					Log.w("ComShell","checkId2Data error");
					return null;
				}
				System.arraycopy(recvData, 15, txt, 0, 256);
				System.arraycopy(recvData, 15, wzTxt, 0, 256);
				System.arraycopy(recvData, 15 + 256, BMPDATA, 0, 1024);
				ForeignerResidencePermitData frdata = null;
				try {
					if(GetCardTypeFlag(wzTxt)==1){
						frdata = new ForeignerResidencePermitData();
						try {
							frdata.setFEName(GetFEName(wzTxt));
							frdata.setFGender(GetFGender(wzTxt));
							frdata.setFNationCode(GetFCountryCode(wzTxt));
							frdata.setFNationName(GetFCountryName(wzTxt));
							frdata.setFBirthDay(GetFBirthday(wzTxt));
							frdata.setFCName(GetFCName(wzTxt));
							frdata.setFIdNum(GetFIndentityCard(wzTxt));
							frdata.setFIssue(GetFIssued(wzTxt));
							frdata.setFEffDate(GetFStartDate(wzTxt));
							frdata.setFExpDate(GetFEndDate(wzTxt));
							frdata.setFVersion(GetFVersion(wzTxt));
							frdata.setFTypeFlag(GetFTypeFlag(wzTxt));
						} catch (UnsupportedEncodingException e1) {
							// TODO Auto-generated catch block
							e1.printStackTrace();
						}
						byte[] bmpBuff = new byte[38862];
					    nRet = GetPicByBuff(BMPDATA,  bmpBuff);
						
						Bitmap bm = BitmapFactory.decodeByteArray(
								bmpBuff, 0, 38862);
						frdata.setPic(bm);
					}
				} catch (IOException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
				
				try {
					ioFile.WriteByteToFile("wz.txt", txt, 0, 256, false);
					ioFile.WriteByteToFile("zp.wlt", BMPDATA, 0, 1024, false);
				} catch (IOException e) {
					e.printStackTrace();
				}
				writeWltFile(BMPDATA);
				return frdata;
	        }
	    }
	    return null;
	}
	/*
	public int  id2ReadCard(){//1296加密字节
	    byte[] sendBuff = new byte[1024];
		byte[] recvData = new byte[4196];
		byte[] chkData = new byte[4196];
		byte[] txt = new byte[256];
		byte[] BMPDATA = new byte[1024];

	    Byte encry = 0x02;
	    Byte moduleNum = 0x0A;
	    Byte funcNum = 0x07;
	    int dataLen = 0;

	    int nRet = sendCmdChinaUnicom(encry,moduleNum,funcNum,dataLen,sendBuff,4000);
	    if(nRet == 0){//命令执行成功
			int recvBuffLen = Integer.parseInt(String.valueOf(returnvalue.get("recvBuffLen")));
			Log.w("ComShell","recvBuffLen is:"+recvBuffLen);
	        if(recvBuffLen > 1000){
				recvData = GetDataFromHash(returnvalue);
				System.arraycopy(recvData, 6, chkData, 0, recvBuffLen-6);
				//Log.w("ComShell","recvData is:"+ Util.toHexStringNoSpace(recvData,  recvBuffLen));
				if(!checkId2Data(chkData,recvBuffLen-6)){
					Log.w("ComShell","checkId2Data error");
					return -1;
				}
//				recvData is:00AAAAAA96 
				          //6905080000
				//			9001000400 
				//205FA27EF653200020002000200020002000200020002000200020002000
				//320030003100
				//31003900380038003100310031003800B36C17530177AF90F890025E344E336FBF53F079FE524795F079FE521C4E51670D597451EF8D32003500F7532000200020002000200020002000200020002000200020002000310033003000340032003300310039003800380031003100310038003400330032003800344E336FBF536C51895B405C2000200020002000200020002000200020003200300031003100300033003300300032003000320031003000330033003000200020002000200020002000200020002000200020002000200020002000200020002000574C66007E00320000FF851F5151513E710DD564F3D383EA7237A5BA6299BBB7B9A6F86EB4E17E415D2D096FE31DD88616FA138FB6C8F1CF68404D0853404F7F4E3B02A623B2DF04CFB0029E9E320DF9F83497518AA89F3A5E874351AED45251515A3E802710D7CEE3341A8C88A86A4338D4D2779B0766B30116EF176A8F2B3DA32CEEA05A768DDD80853E45D6B49A096BAE5133B44AF8091FB892D91255C811C92CE5799B1C09464B84FA63D7A5CA2E94F220CB7506C8091DF5658A844317C38E8E3B1F61E2FAB63ED450CA13F5A84436171F2638048EB424D85EDCFB715BD03494B75A2C5D6C16FB0B5A5C46C0CFDDD2779ECF237403AB09D935710DF76A0D45222D26615A30BD183FD7EF77C430326F9DCF21B4B804222B082AD2125766FA4422B016B09ACFF996134B3011FACFBD83E51D98FA57A7BA6408B0787C18BC7A81899C0380CEE1DC05610639C766A86262F795268C5FCF3EC20C97D365998520D793BC2F6A6ABAABBC7292751031246FDDBCB7327A07C72E919E45E64005C850C12EA976474E8F230CE7B1D61C989C1A40B52ABD9C9FB6EACCC790AE51EC3540200F43B5423BCE710894A3A62002CEE4F89B2A86A2A3CF31CE4EF31F7A85673407BFF7E7FB46227F3FA80335AC90A5BAF7D4AA62C038CFBC8ED7564F0F7B18070E791733D3F7C1BE02AE510F7498D6D5432180AADB323E55DC4E48DD9131642766D3089E7644C69904926EFFD3C2CCB9CD6D51AA6EFCB5CE40AD1246943F584544806A48B1B5C4285AB0F041130A24228BB8155505C71FFDB1735DBEC9427E4684CBE50DC3637CE9AA4C99BABFEC58A14889A0C069052DDF3676C6ABCE58FD632913D5FE91EF8D355A1281E6BF1C1D98B43B616D171CAFF584ED4E79861946204C74570B12507A3BCE26A6B3F1E52D6FBA143EDFCE24326B68A874C8C187D88D4EABAB96CFF7165FDE7B038606FE0DD0399E9F0C8FE8621B6079B05B58FC07A33C90D00D201DADD641D60355E48D542447078889173A152F0290A1BCCC7F5BBEBE3AAD32E87F75FC0DE12FB5718B5A1A262B49FD8E61CA9C2213421AC237B8E334CF8956E340B422856E57B615BA9CF4BBAE51BFD3D8B415C67A5ED381E70A2E38C4724D286958DF576651C477DBC864AA2B28F86ABAA25575244A29AF7642BCDD056CC8007FA72B58748D7058E4CCAFC2A13E4FBFD8DF952385F72FFBE172D3CEAF7965525A3E09687F68E14BEA2BF7C7F0AE5185DAAA89066668FC7FC30CA155815081EBFBFE95DD905EB882A6B8D467515B44D842F929FDAC492087B41BA02AB57E41536563F00AF1F4EE37510B21056695CEE7A05A3EC2F2009250ACE90F02EFF6995C6597AF1A5D86B4574AF94981A5C93C5ABEBF9EDB86C593620AFFEB5581767399F5CF9B8B957ECC0164A637035A7267F21841A58E9376050B8074E452

				System.arraycopy(recvData, 15, txt, 0, 256);
				System.arraycopy(recvData, 15, wzTxt, 0, 256);
				System.arraycopy(recvData, 15 + 256, BMPDATA, 0, 1024);
				try {
					ioFile.WriteByteToFile("wz.txt", txt, 0, 256, false);
					ioFile.WriteByteToFile("zp.wlt", BMPDATA, 0, 1024, false);
				} catch (IOException e) {
					e.printStackTrace();
				}
				writeWltFile(BMPDATA);
	        	
				return 0;
	        }
	    }
	    return -1;
	}
	*/
	//SIM卡 相关操作

	public HashMap<String, Object>  readSIMInfo(byte simType){
	    byte[] sendBuff = new byte[1024];
		byte[] recvData = new byte[1024];
		byte[] tmpData = new byte[1024];
		
		//测试指令：555555555555555504060000030A007A3B06
		//备注说明：读出的IMSI格式应为460018650475157，长度为0x0F(即十进制数15)。（如果卡片为白卡或目录不存在，则返回数据为空，长度为0x00）
		
		Log.w("ComShell","in new readSIMInfo ...");
		
		HashMap<String, Object> simHm = new HashMap<String, Object>();

		simHm.put("ST", 0xFF);
		simHm.put("Result", 0);
		simHm.put("G2_len", 0);
		simHm.put("G2_IMSI", "");
		simHm.put("G3_len", 0);
		simHm.put("G3_IMSI", "");
		if(!b100WS){
			simHm.put("ST", -9);
			return simHm;
		}
		
	    Byte encry = 0x00;
	    Byte moduleNum = 0x03;
	    Byte funcNum = 0x0A;
	    sendBuff[0] =  simType;
	    int dataLen = 1;
	    //:555555555555555504170000030A 00 01 0F3436303032373634313134313133354BF306

	    int nRet = sendCmdChinaUnicom(encry,moduleNum,funcNum,dataLen,sendBuff,4000);
	    if(nRet == 0){//命令执行成功
			int recvBuffLen = Integer.parseInt(String.valueOf(returnvalue.get("recvBuffLen")));
			Log.w("ComShell","recvBuffLen is:"+recvBuffLen);
	        if(recvBuffLen > 3){
				recvData = GetDataFromHash(returnvalue);
				if(recvData[0]==0x00){
					simHm.put("ST", (int)recvData[0]);
					simHm.put("Result", (int)recvData[1]);
					
					int G2_len = recvData[2];
					Log.w("ComShell","G2_len is:"+G2_len);
					simHm.put("G2_len", G2_len);
					if(G2_len<0)
						G2_len += 256;
					if(G2_len>0){
						System.arraycopy(recvData, 3, tmpData, 0, G2_len);
						simHm.put("G2_IMSI", new String (tmpData).trim());
					}
					
					Arrays.fill(tmpData, (byte) 0x0);
					int G3_len = recvData[3+G2_len];
					if(G3_len<0)
						G3_len += 256;
					simHm.put("G3_len", G3_len);
					if(G3_len>0){
						System.arraycopy(recvData, 3+G2_len+1, tmpData, 0, G3_len);
						simHm.put("G3_IMSI", new String (tmpData).trim());
					}
					return simHm;
				}
	        }
	    }
	    return simHm;
	}

	public int writeBlankSim(byte[] data1,int len1,byte[] data2,int len2){
	    byte[] sendBuff = new byte[1024];
		byte[] recvData = new byte[1024];

		if(!b100WS)
			return -9;
	    Byte encry = 0x00;
	    Byte moduleNum = 0x03;
	    Byte funcNum = 0x0B;
	    int dataLen = len1 + len2 +2;//03180318
	    sendBuff[0] = (byte) len1;
	    System.arraycopy(data1, 0, sendBuff, 1, len1);
	    sendBuff[len1+1]= (byte) len2;
	    System.arraycopy(data2, 0, sendBuff, len1 + 2, len2);

	    int nRet = sendCmdChinaUnicom(encry,moduleNum,funcNum,dataLen,sendBuff,3000);
	    if(nRet == 0){
			recvData = GetDataFromHash(returnvalue);
	        if(recvData[0]==0x00){
	        	return 0;
	        }
	    }
	    return -1;
	}
	public int writeSmsCenter(byte[] data,int len){//CLEN smc总长度，2byte，低端模式
	    byte[] sendBuff = new byte[1024];
		byte[] recvData = new byte[1024];
		if(!b100WS)
			return -9;
	    
	    Byte encry = 0x00;
	    Byte moduleNum = 0x03;
	    Byte funcNum = 0x0C;
	    int dataLen = len+2;
	    sendBuff[0] = (byte)(len % 0x100);         //低位在前
	    sendBuff[1] = (byte)(len / 0x100);        //高位在后
	    
	    System.arraycopy(data, 0, sendBuff, 2, len);

	    int nRet = sendCmdChinaUnicom(encry,moduleNum,funcNum,dataLen,sendBuff,1000);
	    if(nRet == 0){
			recvData = GetDataFromHash(returnvalue);
	        if(recvData[0]==0x00){
	        	return 0;
	        }
	    }
	    return -1;
	}

	public HashMap<String, Object> readICCID(){
	    byte[] sendBuff = new byte[1024];
		byte[] recvData = new byte[1024];
		byte[] tmpData = new byte[1024];//1185917915  18516982980

		HashMap<String, Object> simHm = new HashMap<String, Object>();

		simHm.put("ST", 0xFF);
		simHm.put("ICCID_LEN", 0);
		simHm.put("ICCID", "");
		if(!b100WS){
			simHm.put("ST", -9);
			return simHm;
		}
		
	    Byte encry = 0x00;
	    Byte moduleNum = 0x03;
	    Byte funcNum = 0x0F;
	    int dataLen = 0;
	    Log.w("ComShell","readICCID start ...");
	    int nRet = sendCmdChinaUnicom(encry,moduleNum,funcNum,dataLen,sendBuff,4000);
	    if(nRet == 0){//命令执行成功
			int recvBuffLen = Integer.parseInt(String.valueOf(returnvalue.get("recvBuffLen")));
			Log.w("ComShell","readICCID recvBuffLen is:"+recvBuffLen);
	        if(recvBuffLen > 18){
				recvData = GetDataFromHash(returnvalue);
				if(recvData[0]==0x00){
					simHm.put("ST", (int)recvData[0]);
					int len = recvData[1];
					simHm.put("ICCID_LEN", (int)len);
					if(len<0)
						len += 256;
					System.arraycopy(recvData, 2, tmpData, 0, len);
					simHm.put("ICCID", new String(tmpData).trim());
					return simHm;
				}
	        }
	    }
	    return simHm;
	}
    private boolean checkId2Data(byte[] data,int len){
    	byte byParity = 0;
		//Log.w("ComShell","checkId2Data  is:"+ Util.toHexStringNoSpace(data,  len));
		//Log.w("ComShell","checkId2Data len is:"+len);//1290
		for (int i = 0; i < len-1; i++) {
			byParity ^= data[i];
		}
		//Log.w("ComShell","checkId2Data byParity  is:"+ byParity);
		
		if (data[len - 1] == byParity){
			Log.w("ComShell","checkId2Data true");
			return true;
		}else{
			Log.w("ComShell","checkId2Data false");
			return false;
		}
    }
	public int sendCmdChinaUnicom(byte encrypt,byte moduleNum, byte functionNum,int dataLen,byte[] data,int timeOut) {
	    //recvLen 为整个的要接收的数据长度  握手时为18
	
		int nRet = 0;
        byte[] senddd = new byte[256];
        byte[] tmpData = new byte[256];
    	
    	byte byParityLow = 0;
    	byte byParityHigh = 0;
    	int nSize = 0;
	    byte[] tmpRecvBuff = new byte[4196];
		byte[] recvData = new byte[maxRecvBuffLen];	
    	
    	
    	Util.memset(senddd, 0x55, 8);              //同步码，8字节 0x55H
    	senddd[8] = PAK_HEAD;                      //包头
    	nSize = SOLID_LENGH + dataLen;		       //固定长度（5）+ 数据长度
    	senddd[9] = (byte)(nSize % 0x100);         //低位在前
    	senddd[10] = (byte)(nSize / 0x100);        //高位在后
    	senddd[11] = (byte) encrypt;
    	senddd[12] = (byte) moduleNum;
    	senddd[13] = (byte) functionNum;
    	if( dataLen >0){
    		Util.memcpy(senddd, DATA_POS_INDEX, data, 0, dataLen);
    	}
    	
    	Util.memcpy(tmpData, 0, senddd, 9, 5+dataLen);
    	short lCrc = CRC16.getCrc16(tmpData, 5+dataLen);
    	byParityLow = (byte) (lCrc & 0xff);
    	byParityHigh = (byte) ((lCrc >> 8) & 0xff);
    	senddd[DATA_POS_INDEX+dataLen] = byParityLow;
    	senddd[DATA_POS_INDEX+dataLen+1] = byParityHigh;
    	senddd[DATA_POS_INDEX+dataLen+2] = PAK_END;

    	int len = DATA_POS_INDEX+dataLen+3;
	    try {
	       	try {
	       	    cc.ClearBuff();
				Log.w("ComShell","SendMessage senddd is:"+ Util.toHexStringNoSpace(senddd, len));
				cc.SendMessage(senddd,len);//,nSize);
			} catch (IOException e) {
				e.printStackTrace();
			}
			hashData.clear();
			hashData = cc.ReceiveMessage(timeOut);
			if (hashData.size() == 0){ 
		        return -2;
			}
			recvData = GetDataFromHash(hashData);
			len = GetBytesFromHash(hashData);
			Log.w("ComShell","In sendCmdChinaUnicom rLen is:"+len);
	        if (len >= 18){
	            System.arraycopy(recvData, 0, tmpRecvBuff, 0, len);
	            nRet = recvUnicomCheck(tmpRecvBuff,len);
	            Log.w("ComShell","recvUnicomCheck nRet is:"+ nRet);
				//Log.w("ComShell","tmpRecvBuff is:"+ Util.toHexStringNoSpace(tmpRecvBuff,  len));
	    		returnvalue.put("returnFlag", nRet);
	    		returnvalue.put("recvBuffLen", len -17);
	    		System.arraycopy(tmpRecvBuff, 14, tmpRecvBuff, 0,  len-17);
	    		returnvalue.put("recvData", tmpRecvBuff);
	    		return nRet;
	        }
		} catch (IOException e) {
			e.printStackTrace();
		}
	    return  -1;
	}
	private static int recvUnicomCheck(byte[] _rData,int rLen){
		byte[] chkBuff = new byte[4196];
		int crcValue = 0;
	    // 1.校验协议头
	    if (_rData[0] != 0x55 && _rData[8] != 0x04 && _rData[rLen-1] != 0x06) {
	        return -1;
	    }

	    if(rLen != 12+ _rData[10]*0x100 + _rData[9]){
	        return -2;
	    }
	    System.arraycopy(_rData, 9, chkBuff, 0, rLen-12);

	    crcValue = CRC16.getCrc16(chkBuff, rLen-12);
	    if(crcValue < 0)
	    	crcValue = 65536 + crcValue;
	    int ge,shi;
	    if(_rData[rLen -3]<0)
	    	ge = 256+ _rData[rLen -3];
	    else
	    	ge = _rData[rLen -3];

	    if(_rData[rLen -2]<0)
	    	shi = 256+ _rData[rLen -2];
	    else
	    	shi = _rData[rLen -2];
	    
//	    Log.w("ComShell","_rData[rLen -2] is:"+_rData[rLen -2]);//be  190
//	    Log.w("ComShell","_rData[rLen -3] is:"+_rData[rLen -3]);//d0  208

//	    Log.w("ComShell","crcValue is:"+crcValue);
//	    Log.w("ComShell","crcValue222 is:"+(shi*256+ge));
	    
	    //if ((_rData[rLen -2] == ((crcValue >> 8) & 0xFF))&&(_rData[rLen -3] == (crcValue&0xff))){
	    if(crcValue == shi*256+ge){
	        return 0;
	    }else {
	        return -3;
	    }
	}
	@SuppressLint("SdCardPath")
	private void writeWltFile(byte[] wltBuff){
		Log.w("ComShell","In writeWltFile 00");
		String wltFilename = "/mnt/sdcard/zp.wlt";
		File file = new File(wltFilename);
		if (!file.exists()) {
			try {
				file.createNewFile();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		FileOutputStream fos;
		try {
			fos = new FileOutputStream(wltFilename);
			fos.write(wltBuff);
			fos.flush();
			fos.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}catch (IOException e) {
			e.printStackTrace();
		}
	}
	//***********************For ChinaTelecom**********************//

	
/*
	private boolean GetPNO() throws InterruptedException {
		short[] PNO = new short[16];
		byte[] strNo = new byte[32];
		byte[] data = new byte[27];
		short head1, head2;
		long data1, data2, data3;
		int len;
		cc.ClearBuff();
		Thread.sleep(3000);
		//sendCommand(0x12FF, 10);
		// Util.writeLogToSD("After sendCommand 0x12FF");
		Thread.sleep(300);
		hashData.clear();
		hashData = cc.ReceiveMessage(27,3000);
		if (hashData.size() == 0) {
			Log.w("ComShell", "GetPNO ReceiveMessage len0 is 0");
			cc.ClearBuff();
			Thread.sleep(1000);
			//sendCommand(0x12FF, 10);
			Thread.sleep(300);
			hashData.clear();
			hashData = cc.ReceiveMessage(27,3000);
		}

		if (hashData.size() == 0) {
			Log.w("ComShell", "GetPNO ReceiveMessage len1 is 0");
			return false;
		}
		data = GetDataFromHash(hashData);
		len = data.length;
		Log.w("ComShell",
				"In GetPNO data is:" + Util.toHexStringNoSpace(data, len));
		if (len > 0) {
			if ((data[9] == 0x90) || (data[9] == -112))// -97
			{
				// System.arraycopy(data,10,PNO,0,16);
				Log.w("GetPNO",
						"macno data is:" + Util.toHexStringWithSpace(data, len));
				for (int j = 0; j < 16; j++) {
					if (data[10 + j] < 0) {
						PNO[j] = (short) (256 + data[10 + j]);
					} else {
						PNO[j] = (short) data[10 + j];
					}

				}
				head1 = (short) (PNO[1] * 0x100 + PNO[0]);
				head2 = (short) (PNO[3] * 0x100 + PNO[2]);

				data1 = (long) PNO[4] + (long) PNO[5] * 0x100 + (long) PNO[6]
						* 0x100 * 0x100 + (long) PNO[7] * 0x100 * 0x100 * 0x100;
				data2 = (long) PNO[8] + (long) PNO[9] * 0x100 + (long) PNO[10]
						* 0x100 * 0x100 + (long) PNO[11] * 0x100 * 0x100
						* 0x100;
				data3 = (long) PNO[12] + (long) PNO[13] * 0x100
						+ (long) PNO[14] * 0x100 * 0x100 + (long) PNO[15]
						* 0x100 * 0x100 * 0x100;

				gRq = data1;
				gBh = data2;
				return true;
			} else {
				return false;
			}
		} else {
			return false;
		}
	}
*/
	public void Start() {
	/*03160316	sendCommand(0x2001, 10);
		try {
			Thread.sleep(600);
			cc.ClearBuff();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}*/
	}

	public globalEnum ReadCard() {// hhhjj
		byte[] data = new byte[1295];
		byte[] txt = new byte[256];
		byte[] BMPDATA = new byte[1024];

		//sendCommand(0x3001, 10);
		try {
			Thread.sleep(1500);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		hashData.clear();
		try {
			hashData = cc.ReceiveMessage(1295);
		} catch (IOException e1) {
			bShellOk = false;
			disconnect();
			e1.printStackTrace();
			return globalEnum.D_ERROR;// ;
		}
		if (hashData.size() == 0)
			return globalEnum.D_ERROR;// ;

		if (GetDataFromHash(hashData).length > 0) {
			data = GetDataFromHash(hashData);
			if ((data[9] == 0x90) || (data[9] == -112)) {
				System.arraycopy(data, 14, txt, 0, 256);
				System.arraycopy(data, 14 + 256, BMPDATA, 0, 1024);
				try {
					ioFile.WriteByteToFile("wz.txt", txt, 0, 256, false);
					ioFile.WriteByteToFile("zp.wlt", BMPDATA, 0, 1024, false);
				} catch (IOException e) {
					e.printStackTrace();
				}
				Log.w("ComShell", "ReadCard ok");
				return globalEnum.GetDataSuccess;
			} else {
				cc.ClearBuff();
				return globalEnum.D_VALIDATE_ERROR;// ;
			}
		} else {
			return globalEnum.D_ERROR;// ;
		}
	}

	/**
	 * 以字符串形式返回卡信息
	 * 
	 * @return String 卡信息
	 * */
	public String ReadCardInfo() {
		Files ioFile = new Files(context);
		byte[] cardInfo = new byte[256];

		String str = "";

		int nlen = 0;
		try {
			nlen = ioFile.ReadByteToBuf("wz.txt", cardInfo);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		if (nlen > 0) {
			ioFile.DeleteFile("wz.txt");
			// 没有模块号，所以屏蔽
			if (pNo != null) {
				str = new String(pNo);
				// Log.w("ReadCardInfo", "pNo.toString():"+str);
				try {
					tmpStr = MakeCode(GetSID(gRq, gBh));
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}

			try {
				return String
						.format("姓名：%s 性别：%s 民族：%s 出生日期：%s 住址：%s 身份证号：%s 签发机关：%s 有效期：%s-%s",
								GetName(cardInfo), GetGender(cardInfo),
								GetNationalName(cardInfo), GetBirthday(cardInfo),
								GetAddress(cardInfo),
								GetIndentityCard(cardInfo),
								GetIssued(cardInfo), GetStartDate(cardInfo),
								GetEndDate(cardInfo));
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			}
		} else {
			return "读取身份证信息文件失败！";
		}
		return str;
	}

	static String toHexStringNoSpace(byte b) {
		char[] buffer = new char[2];
		buffer[0] = Character.forDigit((b >> 4) & 0x0F, 16);
		buffer[1] = Character.forDigit(b & 0x0F, 16);
		return new String(buffer);
	}

	public static String HexToString(byte[] b, int len) {
		StringBuffer buffer = new StringBuffer();
		for (int i = 0; i < len; ++i) {
			buffer.append(toHexStringNoSpace(b[i]));
		}
		return buffer.toString().toUpperCase();
	}

	public static byte[] GetSID(String instr) {
		String str, srq, sbh;
		byte[] brq = new byte[4];
		byte[] bbh = new byte[4];
		byte[] pNo = new byte[32];
		byte[] sid = new byte[8];

		str = instr;
		srq = str.substring(4, 12);
		sbh = str.substring(12, 22);

		int rq = Integer.parseInt(srq);
		int bh = Integer.parseInt(sbh);

		brq = intToByte(rq);
		bbh = intToByte(bh);

		System.arraycopy(brq, 0, sid, 0, 4);
		System.arraycopy(bbh, 0, sid, 4, 4);

		// 已通过验证，读取正确
		return sid;
	}

	public static byte[] GetSID(long rq, long bh) {
		byte[] brq = new byte[4];
		byte[] bbh = new byte[4];
		byte[] sid = new byte[8];

		Log.w("GetSID", "rq is:" + rq);
		Log.w("GetSID", "bh is:" + bh);

		brq = intToByte(rq); // int max 2147483648
		bbh = intToByte(bh);

		System.arraycopy(brq, 0, sid, 0, 4);
		System.arraycopy(bbh, 0, sid, 4, 4);

		// 已通过验证，读取正确
		return sid;
	}

	public static String MakeCode(byte[] buf) throws IOException {

		String str;
		byte mark[] = new byte[8];
		int nday, ntime, nsec, n, i;

		Time t = new Time(); // or new Time("GMT+8");
		t.setToNow();
		int y = t.year;
		int mon = t.month + 1;
		int d = t.monthDay;
		int h = t.hour;
		int min = t.minute;
		int s = t.second;
		nday = (y * 100 + mon) * 100 + d;
		ntime = (h * 100 + min) * 100 + s;

		nsec = s;

		mark[0] = (byte) (nday & 0xFF);
		mark[1] = (byte) ((nday >> 8) & 0xFF);
		mark[2] = (byte) ((nday >> 16) & 0xFF);
		mark[3] = (byte) ((nday >> 24) & 0xFF);

		mark[4] = (byte) (ntime & 0xFF);
		mark[5] = (byte) ((ntime >> 8) & 0xFF);
		mark[6] = (byte) ((ntime >> 16) & 0xFF);
		mark[7] = 0x0;

		buf[3] = (byte) (buf[3] + nsec);
		n = nsec % 7;
		for (i = 0; i < 7; i++) {
			if (i < 3) {
				buf[i] ^= mark[lxTable[n][i]];
			} else {
				buf[i + 1] ^= mark[lxTable[n][i]];
			}
		}
		// buf.toString())
		str = HexToString(buf, 8);// buf.toString(); //new String(buf) ;
		return str;
	}

	public int GetPicByBuff(byte[] wltBuff,byte[] bmpBuff) {
    	//Wlt w = new Wlt();
    	String s="";
    	String filename="";
    	String sq="";
		Log.w("ComShell","picUnpack start");
		try {
			s = MakeCode(GetSID(gRq, gBh));
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}   //306 +2 62 0A
		String head ="424DCE970000000000003600000028000000660000007E00000001001800000000000000000000000000000000000000000000000000";
		byte[] tmpBmpBuff1 = new byte[38862];
		byte[] tmpBmpBuff2 = new byte[38862];
		byte[] headbuff = new byte[54];
		headbuff = Util.hexStringToBytes(head);
		int nRet = Wlt2bmp.picUnpack(wltBuff,tmpBmpBuff1);
		Log.w("ComShell","picUnpack end");
		
		int hLen =head.length()/2;
		System.arraycopy(headbuff, 0, bmpBuff, 0, hLen);
		
		for(int j=0;j<38862/3;j++){
			tmpBmpBuff2[j*3+0] = tmpBmpBuff1[j*3+2];
			tmpBmpBuff2[j*3+1] = tmpBmpBuff1[j*3+1];
			tmpBmpBuff2[j*3+2] = tmpBmpBuff1[j*3+0];
		}
		
		for(int i=0;i<126;i++){
			System.arraycopy(tmpBmpBuff2,i*306, bmpBuff, hLen+i*308,306);
			bmpBuff[hLen+i*308+306+0] = 0x00;
			bmpBuff[hLen+i*308+306+1] = 0x00;
		}
		
		Log.w("ComShell","picUnpack nRet is:"+nRet);
		//Log.w("ComShell","picUnpack bmpBuff is:"+Util.toHexStringNoSpace(bmpBuff, 38862));
//		int j;
//		for( j=0;j<38862;j++){
////			if(bmpBuff[j]==0x00)
////				break;
//			Log.w("ComShell","picUnpack bmpBuff["+j+"] is:"+bmpBuff[j]);
////		}
//		Log.w("ComShell","picUnpack j is:"+j);
		//int nRet = w.GetBmp(filename, s, sq);
		return nRet; 
	}
	private int GetPic(String wltPath, String termBPath) throws IOException {
		Wlt w = new Wlt();
		String s = "";
		String filename = "";
		String sq = "";
		// filename="/data/data/com.testjar/files/zp.wlt";
		filename = wltPath + "zp.wlt";
		sq = termBPath + "Termb.Lic";
		try {
			s = GetTmpStr();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		Log.w("GetPic", "filename is:" + filename);
		Log.w("GetPic", "sq is:" + sq);
		Log.w("GetPic", "TmpStr is:" + s);
		int nRet = w.GetBmp(filename, s, sq);
		return nRet;
	}

	private String GetTmpStr() throws IOException {
		String s = "";
		s = tmpStr;
		return s;
	}
	public byte[] GetCardWltBytes() {
		Files ioFile = new Files(context);
		byte[] wltBuff = new byte[1024];
		String str;
		
		String path = context.getFilesDir().getAbsolutePath()+"/";
		File f = new File(path+"zp.wlt");
		if(!f.exists()){
			Log.w("ComShell","zp.txt is null");
			return null;
		}
		
		int nlen;
		try {
			nlen = ioFile.ReadByteToBuf("zp.wlt", wltBuff);
			if (nlen > 0) {
				ioFile.DeleteFile("zp.wlt");
				return wltBuff;
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}
	/**
	 * 以byte数组返回卡信息
	 * 
	 * @return byte[] 卡信息
	 * */
	public byte[] GetCardInfoBytes() {
		Files ioFile = new Files(context);
		byte[] cardInfo = new byte[256];
		String str;
		
		String path = context.getFilesDir().getAbsolutePath()+"/";
		File f = new File(path+"wz.txt");
		if(!f.exists()){
			Log.w("ComShell","wz.txt is null");
			return null;
		}
		
		int nlen;
		try {
			nlen = ioFile.ReadByteToBuf("wz.txt", cardInfo);
			if (nlen > 0) {
				ioFile.DeleteFile("wz.txt");
				// 没有模块号，所以屏蔽
				if (pNo != null) {
					str = new String(pNo);
					// Log.w("ReadCardInfo", "pNo.toString():"+str);
					tmpStr = MakeCode(GetSID(gRq, gBh));
				}
				return cardInfo;
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 取证件类型，0:二代证；1:外国人居住证 其他:失败
	 * */
	public int GetCardTypeFlag(byte[] cardInfo) throws IOException{
		String typeFlag="";
		if(cardInfo.length>250){
			byte[] type = new byte[2];
			Util.memcpy(type, 0, cardInfo, 248, 2);
			typeFlag = new String(type, "UTF-16LE"); 
			if(typeFlag.endsWith("I"))
				return 1;
			else 
				return 0;
		}else{
			return -1;
		}
	}
	/**
	 * 读取外国人居住证英文名字
	 * */
	public String GetFEName(byte[] data) throws UnsupportedEncodingException {
		byte[] buff = new byte[120];
		Util.memcpy(buff, 0, data, 0, 120);
		return new String(buff, "UTF-16LE");
	}
	/**
	 * 读取外国人居住证英文名字性别
	 * */
	public String GetFGender(byte[] data) throws UnsupportedEncodingException {
		byte[] buff = new byte[2];
		Util.memcpy(buff, 0, data, 120, 2);
		String sGender = new String(buff, "UTF-16LE");
		return Integer.valueOf(sGender) == 1 ? "男" : "女";
	}
	/**
	 * 读取外国人居住证证件号码
	 * */
	public String GetFIndentityCard(byte[] data) throws UnsupportedEncodingException {
		byte[] buff = new byte[30];
		Util.memcpy(buff, 0, data, 122, 30);
		return new String(buff, "UTF-16LE");
	}
	/**
	 * 读取外国人居住证国籍三位码
	 * */
	public String GetFCountryCode(byte[] data) throws UnsupportedEncodingException {
		byte[] buff = new byte[6];
		Util.memcpy(buff, 0, data,152, 6);
		return new String(buff, "UTF-16LE");
	}	
	/**
	 * 读取外国人居住证国籍中文名字
	 * */
	public  String GetFCountryName(byte[] data) throws UnsupportedEncodingException {
		String strNation = GetFCountryCode(data);
		return CountryMap.get(strNation);
	}
	/**
	 * 读取外国人居住证中文姓名
	 * */
	public String GetFCName(byte[] data) throws UnsupportedEncodingException {
		byte[] buff = new byte[30];
		Util.memcpy(buff, 0, data, 158, 30);
		return new String(buff, "UTF-16LE");
	}
	/**
	 * 读取外国人居住证签发日期
	 * */
	public String GetFStartDate(byte[] data) throws UnsupportedEncodingException {
		byte[] buff = new byte[16];
		Util.memcpy(buff, 0, data, 188, 16);
		String sStart = new String(buff, "UTF-16LE");
		return String.format("%s%s%s", sStart.substring(0, 4),
				sStart.substring(4, 6), sStart.substring(6, 8));
	}
	/**
	 * 读取外国人居住证截止日期
	 * */
	public String GetFEndDate(byte[] data) throws UnsupportedEncodingException {
		byte[] buff = new byte[16];
		Util.memcpy(buff, 0, data,204, 16);
		String sEnd = new String(buff, "UTF-16LE");
		String mEnd ="";
		
		String strTem = sEnd.substring(0,4);
		if (sEnd.length()<5) {
			mEnd = strTem;
		}else {
			mEnd = String.format("%s%s%s", sEnd.substring(0, 4),
					sEnd.substring(4, 6), sEnd.substring(6, 8));
		}		
		Log.w("777","mEnd is:"+mEnd);
		return mEnd;
	}
	/**
	 * 读取外国人居住证出生日期
	 * */
	public String GetFBirthday(byte[] data) throws UnsupportedEncodingException {
		byte[] buff = new byte[16];
		Util.memcpy(buff, 0, data, 220, 16);

		Log.w("ComShell","data is:"+Util.toHexStringNoSpace(data,256));
		Log.w("ComShell","buff is:"+Util.toHexStringNoSpace(buff, 16));
		String sBirthday = new String(buff, "UTF-16LE");
		Log.w("ComShell","sBirthday is:"+sBirthday);
		Log.w("ComShell","sBirthday.substring(0, 4) is:"+sBirthday.substring(0, 4));
		Log.w("ComShell","sBirthday.substring(4, 6) is:"+sBirthday.substring(4, 6));
		Log.w("ComShell","sBirthday.substring(6, 8) is:"+sBirthday.substring(6, 8));
		return String.format("%s%s%s", sBirthday.substring(0, 4),
				sBirthday.substring(4, 6), sBirthday.substring(6, 8));

		
//		Util.memcpy(birthday, 0, data, 36, 16);
//		String sBirthday = new String(birthday, "UTF-16LE");
//		return String.format("%s%s%s", sBirthday.substring(0, 4),
//				sBirthday.substring(4, 6), sBirthday.substring(6, 8));
	}
	/**
	 * 读取外国人居住证证件版本号
	 * */
	public String GetFVersion(byte[] data) throws UnsupportedEncodingException {
		byte[] buff = new byte[4];
		Util.memcpy(buff, 0, data, 236, 4);
		return new String(buff, "UTF-16LE");
	}
	/**
	 * 读取外国人居住证申请机关代码
	 * */
	public String GetFIssued(byte[] data) throws UnsupportedEncodingException {
		byte[] buff = new byte[8];
		Util.memcpy(buff, 0, data, 240, 8);
		return new String(buff, "UTF-16LE");
	}
	/**
	 * 读取外国人居住证类型标识
	 * */
	public String GetFTypeFlag(byte[] data) throws UnsupportedEncodingException {
		byte[] buff = new byte[2];
		Util.memcpy(buff, 0, data, 248, 2);
		return new String(buff, "UTF-16LE");
	}
	/**
	 * 读取外国人居住证预留项
	 * */
	public String GetFReserve(byte[] data) throws UnsupportedEncodingException {
		byte[] buff = new byte[6];
		Util.memcpy(buff, 0, data,250, 6);
		return new String(buff, "UTF-16LE");
	}
	
	/**
	 * 读取二代证姓名
	 * 
	 * @param data
	 *            byte[]类型，由GetCardInfoBytes函数获取
	 * @return String 二代证姓名
	 * */
	public String GetName(byte[] data) throws UnsupportedEncodingException {
		byte[] name = new byte[30];
		Util.memcpy(name, 0, data, 0, 30);
		return new String(name, "UTF-16LE");
	}

	/**
	 * 读取二代证性别
	 * 
	 * @param data
	 *            byte[]类型，由GetCardInfoBytes函数获取
	 * @return String 二代证性别
	 * */
	public String GetGender(byte[] data)  {
		/*byte[] gender = new byte[2];
		Util.memcpy(gender, 0, data, 30, 2);
		String sGender="";
		try {
			sGender = new String(gender, "UTF-16LE");
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		return Integer.valueOf(sGender) == 1 ? 1 : 0;*/
		byte[] gender = new byte[2];
		System.arraycopy(data, 30, gender, 0, 2);
		String sGender;
		try {
			sGender = new String(gender, "UTF-16LE");
			int i = 0 ;
			try{
				i = Integer.valueOf(sGender);
			}catch (NumberFormatException e){
				e.printStackTrace();	
			}
			if(i==1)
				return "男";
			else if(i==2)
				return "女";
			else 
				return "未知";
		} catch (UnsupportedEncodingException e1) {
			e1.printStackTrace();
		}
		return "未知";
	}
	
	/**
	 * 读取二代证民族编码
	 * 
	 * @param data
	 *            byte[]类型，由GetCardInfoBytes函数获取
	 * @return String 二代证民族
	 * */
	public String GetNationalCode(byte[] data)  {
		byte[] national = new byte[4];
		Util.memcpy(national, 0, data, 32, 4);
		String strNational;
		try {
			strNational = new String(national, "UTF-16LE");
			return strNational;
		} catch (UnsupportedEncodingException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		return "";
	}

	/**
	 * 读取二代证民族名称
	 * 
	 * @param data
	 *            byte[]类型，由GetCardInfoBytes函数获取
	 * @return String 二代证民族
	 * */
	public String GetNationalName(byte[] data)  {
		byte[] national = new byte[4];
		Util.memcpy(national, 0, data, 32, 4);
		String strNational;
		try {
			strNational = new String(national, "UTF-16LE");
			return GetNationalFromCode(strNational);
		} catch (UnsupportedEncodingException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		return "";
	}

	/**
	 * 读取二代证生日
	 * 
	 * @param data
	 *            byte[]类型，由GetCardInfoBytes函数获取
	 * @return String 二代证生日
	 * */
	public String GetBirthday(byte[] data) throws UnsupportedEncodingException {
		byte[] birthday = new byte[16];
		Util.memcpy(birthday, 0, data, 36, 16);
		String sBirthday = new String(birthday, "UTF-16LE");
		return String.format("%s%s%s", sBirthday.substring(0, 4),
				sBirthday.substring(4, 6), sBirthday.substring(6, 8));
	}

	/**
	 * 读取二代证住址
	 * 
	 * @param data
	 *            byte[]类型，由GetCardInfoBytes函数获取
	 * @return String 二代证住址
	 * */
	public String GetAddress(byte[] data) throws UnsupportedEncodingException {
		byte[] address = new byte[70];
		Util.memcpy(address, 0, data, 52, 70);
		return new String(address, "UTF-16LE");
	}

	/**
	 * 读取二代证身份证号
	 * 
	 * @param data
	 *            byte[]类型，由GetCardInfoBytes函数获取
	 * @return String 二代证身份证号
	 * */
	public String GetIndentityCard(byte[] data)
			throws UnsupportedEncodingException {
		byte[] identity = new byte[36];
		Util.memcpy(identity, 0, data, 122, 36);
		return new String(identity, "UTF-16LE");
	}

	/**
	 * 读取二代证签发机关
	 * 
	 * @param data
	 *            byte[]类型，由GetCardInfoBytes函数获取
	 * @return String 二代证签发机关
	 * */
	public String GetIssued(byte[] data) throws UnsupportedEncodingException {
		byte[] issued = new byte[30];
		Util.memcpy(issued, 0, data, 158, 30);
		return new String(issued, "UTF-16LE");
	}

	/**
	 * 读取二代证有效起始日期
	 * 
	 * @param data
	 *            byte[]类型，由GetCardInfoBytes函数获取
	 * @return String 二代证有效起始日期
	 * */
	public String GetStartDate(byte[] data) throws UnsupportedEncodingException {
		byte[] start = new byte[16];
		Util.memcpy(start, 0, data, 188, 16);
		String sStart = new String(start, "UTF-16LE");
		return String.format("%s%s%s", sStart.substring(0, 4),
				sStart.substring(4, 6), sStart.substring(6, 8));
	}

	/**
	 * 读取二代证有效结束日期
	 * 
	 * @param data
	 *            byte[]类型，由GetCardInfoBytes函数获取
	 * @return String 二代证有效结束日期
	 * */
	public String GetEndDate(byte[] data) throws UnsupportedEncodingException {
		byte[] end = new byte[16];
		Util.memcpy(end, 0, data, 204, 16);
		String sEnd = new String(end, "UTF-16LE");
		String mEnd = "";

		String strTem = sEnd.substring(0, 4);
		// Log.w("777","sEnd is:"+sEnd);
		// Log.w("777","sEnd.length is:"+sEnd.length());
		if (sEnd.length() < 5) {
			mEnd = strTem;
		} else {
			mEnd = String.format("%s%s%s", sEnd.substring(0, 4),
					sEnd.substring(4, 6), sEnd.substring(6, 8));
		}
		Log.w("777", "mEnd is:" + mEnd);
		return mEnd;
	}

	private String GetNationalFromCode(String nationalCode) {
		int n = Integer.valueOf(nationalCode);
		switch (n) {
		case 1:
			return "汉族";
		case 2:
			return "蒙古族";
		case 3:
			return "回族";
		case 4:
			return "藏族";
		case 5:
			return "维吾尔族";
		case 6:
			return "苗族";
		case 7:
			return "彝族";
		case 8:
			return "壮族";
		case 9:
			return "布依族";
		case 10:
			return "朝鲜族";
		case 11:
			return "满族";
		case 12:
			return "侗族";
		case 13:
			return "瑶族";
		case 14:
			return "白族";
		case 15:
			return "土家族";
		case 16:
			return "哈尼族";
		case 17:
			return "哈萨克族";
		case 18:
			return "傣族";
		case 19:
			return "黎族";
		case 20:
			return "傈僳族";
		case 21:
			return "佤族";
		case 22:
			return "畲族";
		case 23:
			return "高山族";
		case 24:
			return "拉祜族";
		case 25:
			return "水族";
		case 26:
			return "东乡族";
		case 27:
			return "纳西族";
		case 28:
			return "景颇族";
		case 29:
			return "柯尔克孜族";
		case 30:
			return "土族";
		case 31:
			return "达斡尔族";
		case 32:
			return "仫佬族";
		case 33:
			return "羌族";
		case 34:
			return "布朗族";
		case 35:
			return "撒拉族";
		case 36:
			return "毛难族";
		case 37:
			return "仡佬族";
		case 38:
			return "锡伯族";
		case 39:
			return "阿昌族";
		case 40:
			return "普米族";
		case 41:
			return "塔吉克族";
		case 42:
			return "怒族";
		case 43:
			return "乌孜别克族";
		case 44:
			return "俄罗斯族";
		case 45:
			return "鄂温克族";
		case 46:
			return "崩龙族";
		case 47:
			return "保安族";
		case 48:
			return "裕固族";
		case 49:
			return "京族";
		case 50:
			return "塔塔尔族";
		case 51:
			return "独龙族";
		case 52:
			return "鄂伦春族";
		case 53:
			return "赫哲族";
		case 54:
			return "门巴族";
		case 55:
			return "珞巴族";
		case 56:
			return "基诺族";
		default:
			return "其他";
		}
	}

	private byte[] GetDataFromHash(HashMap<String, Object> hashData) {
		int len = GetBytesFromHash(hashData);
		if(len>0){
			byte[] tmpData = new byte[len];
			try {
				Util.memcpy(tmpData, 0, (byte[]) hashData.get("recvData"), 0,
						GetBytesFromHash(hashData));
				return tmpData;
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return null;
	}

	private int GetBytesFromHash(HashMap<String, Object> hashData) {
		if(hashData.get("recvBuffLen")!=null)
			return Integer.parseInt(String.valueOf(hashData.get("recvBuffLen")));
		else
			return 0;
	}

	private static byte[] intToByte(long i) {
		byte[] abyte0 = new byte[4];
		abyte0[0] = (byte) (0xff & i);
		abyte0[1] = (byte) ((0xff00 & i) >> 8);
		abyte0[2] = (byte) ((0xff0000 & i) >> 16);
		abyte0[3] = (byte) ((0xff000000 & i) >> 24);
		return abyte0;
	}

}
