当前位置:   article > 正文

Java读写t5557卡源码

Java读写t5557卡源码

       T5557卡是美国Atmel公司生产的多功能非接触式射频卡芯片,属于125KHz的低频卡,在国内有广大的应用市场。该芯片共有330bit(比特)的EPROM(分布为10个区块, 每个区块33bit)。0页的块0是被保留用于设置T5557操作模式的参数配置块。第0页第7块可以作用户数据块使用,也可以作为保护全部数据的密码(假如在配置块中启用密码功能的话),防止非法改写数据。 第1页的1、2块保存了出厂商信息及唯一出厂ID,只能读取不可更改,T5567、T5577是T5557的升级版。

本示例使用的发卡器:T5557 T5567 T5577低频RFID读写器 EM4100 HID卡复制器 酒店门卡-淘宝网 (taobao.com) 

  1. import com.sun.jna.Library ;
  2. import com.sun.jna.Native;
  3. import com.sun.jna.WString;
  4. interface CLibrary extends Library {
  5. //DLL绝对路径的地址获取,注意要去空格
  6. String filePath = CLibrary.class.getResource("").getPath().replaceFirst("/","").replaceAll("%20"," ")+"OUR_IDR";
  7. CLibrary sdtapi = (CLibrary) Native.loadLibrary(filePath, CLibrary.class);
  8. //动态链接库中的方法
  9. byte idr_beep(int xms); //让设备发出声音
  10. byte pcdgetdevicenumber(byte[] devicenumber); //读取设备编号
  11. String pcdgetdevicenumber_str(); //读取设备编号,输出字符串
  12. byte idr_read(byte[] mypiccserial ); //轻松读ID卡,只要卡在感应区,每次执行此方法都可以读到卡号
  13. byte hid_read(byte[] mypiccserial ); //轻松读ID卡,只要卡在感应区,每次执行此方法都可以读到卡号
  14. String idr_read_8h10d_str(); //读ID卡,输出十位十进制卡号
  15. byte t5557_read(byte ctrlword, byte[] mypiccserial,byte[] oldkey,byte[] blockflag,byte[] blockdata); //读t5557卡,
  16. byte t5557_write(byte ctrlword, byte[] mypiccserial,byte[] oldkey,byte[] blockflag,byte[] blockdata); //写t5557卡,
  17. byte t5557_init(byte ctrlword, byte[] mypiccserial,byte[] oldkey,byte[] configdata,byte[] newkey); //写t5557卡配置值
  18. byte t5557_changekey(byte ctrlword, byte[] mypiccserial,byte[] oldkey,byte[] newkey); //修改t5557卡密钥
  19. }
  20. public class IDReader {
  21. public static final byte NEEDSERIAL=1; //只对指定UID列号的卡操作
  22. public static final byte NEEDKEY=2; //需要用密码认证卡
  23. public static final byte LOCKBIT=4; //锁定配置块或数据块,仅对 t5557_init,t5557_write ,t5557_changekey函数有效
  24. public static final byte KEYENABLE=8; //启用本卡的密码功能
  25. public static final byte RESETCARD=16; //操作成功后重启卡片
  26. public static void main(String[] args) {
  27. System.setProperty("jna.encoding", "GBK");
  28. String filePath = CLibrary.class.getResource("").getPath().replaceFirst("/", "").replaceAll("%20", " ") + "OUR_IDR.DLL";
  29. System.out.println("本示例引用的DLL文件:" + filePath);
  30. if (args.length == 0) {
  31. System.out.println("\n请先输入运行参数!");
  32. System.out.println("\n参数 0:驱动读卡器嘀一声");
  33. System.out.println("\n参数 1:读取设备编号");
  34. System.out.println("\n参数 2:读取设备编号,输出字符串");
  35. System.out.println("\n参数 3:轻松读ID卡");
  36. System.out.println("\n参数 4:轻松读HID卡");
  37. System.out.println("\n参数 5:轻松读ID卡,输出十位十进制卡号");
  38. System.out.println("\n参数 6:读T5557卡");
  39. System.out.println("\n参数 7:写T5557卡");
  40. System.out.println("\n参数 8:写T5557卡配置值");
  41. System.out.println("\n参数 9:修改T5557卡密钥");
  42. return;
  43. }
  44. //Java中只能使用string1.equals(string2)的方式来比较字符串
  45. if (args[0].equals("0")) { //驱动读卡器发嘀一声
  46. System.out.print("\n0-驱动读卡器嘀一声\n");
  47. CLibrary.sdtapi.idr_beep(50);
  48. System.out.print("结果:如果能听到读卡器嘀一声表示成功,否则请检查读卡器是否已连上线!\n\n");
  49. } else if (args[0].equals("1")) //读取设备编号,可做为软件加密狗用,也可以根据此编号在公司网站上查询保修期限
  50. {
  51. int status; //存放返回值
  52. byte[] devicenumber = new byte[4]; //4字节设备编号
  53. System.out.print("\n1-读取设备编号\n");
  54. status = (int) (CLibrary.sdtapi.pcdgetdevicenumber(devicenumber) & 0xff);//& 0xff用于转为无符号行数据
  55. System.out.print("结果:");
  56. if (status == 0) {
  57. CLibrary.sdtapi.idr_beep(38);
  58. System.out.print("读取成功!设备编号为:" + (devicenumber[0] & 0xff) + "-" + (devicenumber[1] & 0xff) + "-" + (devicenumber[2] & 0xff) + "-" + (devicenumber[3] & 0xff));
  59. } else {
  60. PrintErrInf(status); //错误代码提示
  61. }
  62. }else if (args[0].equals("2")) //读取设备编号,直接输出字符串
  63. {
  64. System.out.print("\n2-读取设备编号\n");
  65. String statustr = CLibrary.sdtapi.pcdgetdevicenumber_str().trim(); //设备编号
  66. if(statustr.length()==10) {
  67. CLibrary.sdtapi.idr_beep(38);
  68. System.out.print("读取成功!设备编号为:" + statustr + "\n");
  69. }else{
  70. PrintErrStr(statustr); //错误字符串代码提示
  71. }
  72. }else if (args[0].equals("3")) //轻松读ID卡
  73. {
  74. int status; //存放返回值
  75. byte[] mypiccserial = new byte[5]; //5字节卡序列号
  76. System.out.print("\n3-轻松读卡\n");
  77. status = (int) (CLibrary.sdtapi.idr_read(mypiccserial ) & 0xff); //只要卡在感应区,每次执行此方法都可以读到卡号
  78. System.out.print("结果:");
  79. if (status == 0) {
  80. CLibrary.sdtapi.idr_beep(38);
  81. String serialnumber = "";
  82. for (int i = 0; i < 5; i++) {
  83. String bytestr = "00" + Integer.toHexString(mypiccserial[i] & 0xff);
  84. serialnumber = serialnumber + bytestr.substring(bytestr.length() - 2, bytestr.length());
  85. }
  86. System.out.print("读取成功!16进制卡序列号为:" + serialnumber+"\n");
  87. long cardnum;
  88. cardnum=mypiccserial[4] & 0xff;
  89. cardnum=cardnum+(mypiccserial[3] & 0xff) *256;
  90. cardnum=cardnum+(mypiccserial[2] & 0xff) *65536;
  91. cardnum=cardnum+(mypiccserial[1] & 0xff) *16777216;
  92. long cardno10 = 0;
  93. for (int j=28; j>=0; j-=4) {
  94. cardno10 = cardno10<<4 | (cardnum>>>j & 0xF);
  95. }
  96. System.out.print("换算成10进制卡号:"+String.format("%010d", cardno10)+"\n");
  97. } else {
  98. PrintErrInf(status); //错误代码提示
  99. }
  100. }else if (args[0].equals("4")) //轻松读HID卡
  101. {
  102. int status; //存放返回值
  103. byte[] mypiccserial = new byte[7]; //7字节卡序列号
  104. System.out.print("\n4-轻松读HID卡\n");
  105. status = (int) (CLibrary.sdtapi.hid_read(mypiccserial ) & 0xff);
  106. System.out.print("结果:");
  107. if (status == 0) {
  108. CLibrary.sdtapi.idr_beep(38);
  109. String serialnumber = "";
  110. for (int i = 0; i < 7; i++) {
  111. String bytestr = "00" + Integer.toHexString(mypiccserial[i] & 0xff);
  112. serialnumber = serialnumber + bytestr.substring(bytestr.length() - 2, bytestr.length());
  113. }
  114. System.out.print("读取成功!16进制卡序列号为:" + serialnumber+"\n");
  115. long cardnum;
  116. cardnum=mypiccserial[6] & 0xff;
  117. cardnum=cardnum+(mypiccserial[5] & 0xff) *256;
  118. cardnum=cardnum+(mypiccserial[4] & 0xff) *65536;
  119. cardnum=cardnum+(mypiccserial[3] & 0xff) *16777216;
  120. long cardno10 = 0;
  121. for (int j=28; j>=0; j-=4) {
  122. cardno10 = cardno10<<4 | (cardnum>>>j & 0xF);
  123. }
  124. System.out.print("换算成8H10D卡号:"+String.format("%010d", cardno10)+"\n");
  125. } else {
  126. PrintErrInf(status); //错误代码提示
  127. }
  128. }else if (args[0].equals("5")) //读ID卡,输出十位十进制卡号
  129. {
  130. System.out.print("\n5-读10进制ID卡号\n");
  131. String statustr = CLibrary.sdtapi.idr_read_8h10d_str().trim(); //只要卡在感应区,每次执行此方法都可以读到卡号
  132. if(statustr.length()==10) {
  133. CLibrary.sdtapi.idr_beep(38);
  134. System.out.print("读卡成功!8H10D卡号为:" + statustr + "\n");
  135. }else{
  136. PrintErrStr(statustr); //错误字符串代码提示
  137. }
  138. }else if (args[0].equals("6")) //读T5557卡
  139. {
  140. System.out.print("\n6-读t5557卡\n");
  141. byte status; //存放返回值
  142. byte myctrlword=0; //控制字
  143. byte[] oldpicckey=new byte[4]; //认证密钥
  144. byte[] mypiccserial=new byte[6]; //卡UID序列号
  145. byte[] mypiccdata=new byte[100]; //读卡数据缓冲:卡无线转输分频比、卡内容长度(字节数),及最多返回12个块的数据
  146. byte[] mypiccblockflag=new byte[2]; //指定本次操作的块
  147. boolean withkey=false; //是否要认证卡密钥
  148. boolean thiscarduit =false; //是否只操作指定UID序号的卡
  149. if (withkey){ //本次操作需要密码验证,将认证密钥加入oldpicckey
  150. myctrlword=(byte)(myctrlword+NEEDKEY);
  151. String Keyhexstr="12345678"; //认证密钥
  152. for(int i=0;i<4;i++){
  153. oldpicckey[i]=(byte)Integer.parseInt(Keyhexstr.substring(i*2,(i+1)*2),16);
  154. }
  155. }
  156. if(thiscarduit){ //本次只操作指定UID号的卡,mypiccserial
  157. myctrlword=(byte)(myctrlword+NEEDSERIAL);
  158. String Uidhexstr="000000000000"; //卡片uid
  159. for(int i=0;i<6;i++){
  160. mypiccserial[i]=(byte)Integer.parseInt(Uidhexstr.substring(i*2,(i+1)*2),16);
  161. }
  162. }
  163. String Seleblockstr0="11111111"; //第0页每块选取状态,从左到右依次表示第7、6、5、4、3、2、1、0块是否要操作,取1表示该块要读,取0表示该块不读,如要读0、1、3 块取值为 00001011,读第0页全部块为 11111111
  164. String Seleblockstr1="11110"; //第1页每块选取状态,从左到右依次表示第3、2、1、0块是否要操作,取1表示该块要读,取0表示该块不读,该页总计4块,最右边表示页选取值0
  165. mypiccblockflag[0]=(byte)Integer.parseInt(Seleblockstr0,2);
  166. mypiccblockflag[1]=(byte)Integer.parseInt(Seleblockstr1,2);
  167. status = CLibrary.sdtapi.t5557_read(myctrlword,mypiccserial,oldpicckey,mypiccblockflag,mypiccdata);
  168. if(status == 0) {
  169. CLibrary.sdtapi.idr_beep(38);
  170. String cardnohex="";
  171. for (int i=0;i<6;i++){
  172. String bytestr = "00" + Integer.toHexString(mypiccserial[i] & 0xff);
  173. cardnohex = cardnohex + bytestr.substring(bytestr.length() - 2, bytestr.length()) ;
  174. }
  175. System.out.print("读卡成功,16进制卡序列号:"+cardnohex+"\n");
  176. System.out.print("卡无线转输分频比:"+Integer.toString(mypiccdata[0])+"\n");
  177. if(mypiccdata[1]>0) {
  178. String blockdata = "块内数据:";
  179. for (int i = 0; i < mypiccdata[1]; i++) {
  180. String bytestr = "00" + Integer.toHexString(mypiccdata[2 + i] & 0xff);
  181. blockdata = blockdata + bytestr.substring(bytestr.length() - 2, bytestr.length()) + " ";
  182. }
  183. System.out.print(blockdata+"\n");
  184. }
  185. }else {
  186. PrintErrInf(status); //错误代码提示
  187. }
  188. }else if (args[0].equals("7")) //写T5557卡
  189. {
  190. System.out.print("\n7-写t5557卡块\n");
  191. byte status; //存放返回值
  192. byte myctrlword=0; //控制字
  193. byte[] oldpicckey=new byte[4]; //认证密钥
  194. byte[] mypiccserial=new byte[6]; //卡UID序列号
  195. byte[] mypiccdata=new byte[50]; //读卡数据缓冲:卡无线转输分频比、卡内容长度(字节数),及最多返回12个块的数据
  196. byte[] mypiccblockflag=new byte[2]; //指定本次操作的块
  197. boolean withkey=false; //是否要认证卡密钥
  198. boolean thiscarduit =false; //是否只操作指定UID序号的卡
  199. if (withkey){ //本次操作需要密码验证,将认证密钥加入oldpicckey
  200. myctrlword=(byte)(myctrlword+NEEDKEY);
  201. String Keyhexstr="12345678"; //认证密钥
  202. for(int i=0;i<4;i++){
  203. oldpicckey[i]=(byte)Integer.parseInt(Keyhexstr.substring(i*2,(i+1)*2),16);
  204. }
  205. }
  206. if(thiscarduit){ //本次只操作指定UID号的卡,mypiccserial
  207. myctrlword=(byte)(myctrlword+NEEDSERIAL);
  208. String Uidhexstr="000000000000"; //卡片uid
  209. for(int i=0;i<6;i++){
  210. mypiccserial[i]=(byte)Integer.parseInt(Uidhexstr.substring(i*2,(i+1)*2),16);
  211. }
  212. }
  213. String Seleblockstr0="11111110"; //第0页每块选取状态,从左到右依次表示第7、6、5、4、3、2、1、0块是否要操作,取1表示该块要写,取0表示该块不写,如要写1、3 块取值为 00001010,第0块是配置块不能用此功能写入,如开启了密码功能,第7块为密码块也不能用此功能写
  214. String Seleblockstr1="00000"; //第1页每块选取状态,此页只读不可写,
  215. mypiccblockflag[0]=(byte)Integer.parseInt(Seleblockstr0,2);
  216. mypiccblockflag[1]=(byte)Integer.parseInt(Seleblockstr1,2);
  217. String writedatahex="11111111222222223333333344444444555555556666666677777777"; //写入的数据,实际写入数据的块 由mypiccblockflag值决定
  218. for (int i=0;i<28;i++){
  219. mypiccdata[i]=(byte)Integer.parseInt(writedatahex.substring(i*2,(i+1)*2),16);
  220. }
  221. status = CLibrary.sdtapi.t5557_write(myctrlword,mypiccserial,oldpicckey,mypiccblockflag,mypiccdata);
  222. if(status == 0) {
  223. CLibrary.sdtapi.idr_beep(38);
  224. String cardnohex = "";
  225. for (int i = 0; i < 6; i++) {
  226. String bytestr = "00" + Integer.toHexString(mypiccserial[i] & 0xff);
  227. cardnohex = cardnohex + bytestr.substring(bytestr.length() - 2, bytestr.length());
  228. }
  229. System.out.print("写卡成功,16进制卡序列号:" + cardnohex + "\n");
  230. }else {
  231. PrintErrInf(status); //错误代码提示
  232. }
  233. }else if (args[0].equals("8")) //写T5557卡配置块
  234. {
  235. System.out.print("\n8-写t5557卡配置块\n");
  236. byte status; //存放返回值
  237. byte myctrlword=0; //控制字
  238. byte[] oldpicckey=new byte[4]; //认证密钥
  239. byte[] newpicckey=new byte[4]; //卡片新密钥
  240. byte[] mypiccserial=new byte[6]; //卡UID序列号
  241. byte[] configdata=new byte[4]; //配置值
  242. boolean withkey=false; //是否要认证卡密钥
  243. boolean newkeyEn=false; //是否要开启卡片密钥功能
  244. if (withkey){ //本次操作需要密码验证,将认证密钥加入oldpicckey
  245. myctrlword=(byte)(myctrlword+NEEDKEY);
  246. String oldKeyhexstr="12345678"; //认证密钥
  247. for(int i=0;i<4;i++){
  248. oldpicckey[i]=(byte)Integer.parseInt(oldKeyhexstr.substring(i*2,(i+1)*2),16);
  249. }
  250. }
  251. String configdatahex="00088028"; //卡片出厂默认配置值,不同功能配置值不一样,请查询相关资料
  252. if (newkeyEn){ //卡片启用密钥保护功能
  253. myctrlword=(byte)(myctrlword+KEYENABLE);
  254. configdatahex="00088038"; //开启密钥配置值,不同功能配置值不一样,请查询相关资料
  255. String newKeyhexstr="12345678"; //新密钥
  256. for(int i=0;i<4;i++){
  257. newpicckey[i]=(byte)Integer.parseInt(newKeyhexstr.substring(i*2,(i+1)*2),16);
  258. }
  259. }
  260. for (int i=0;i<4;i++){
  261. configdata[i]=(byte)Integer.parseInt(configdatahex.substring(i*2,(i+1)*2),16);
  262. }
  263. status = CLibrary.sdtapi.t5557_init(myctrlword,mypiccserial,oldpicckey,configdata,newpicckey);
  264. if(status == 0) {
  265. CLibrary.sdtapi.idr_beep(38);
  266. String cardnohex = "";
  267. for (int i = 0; i < 6; i++) {
  268. String bytestr = "00" + Integer.toHexString(mypiccserial[i] & 0xff);
  269. cardnohex = cardnohex + bytestr.substring(bytestr.length() - 2, bytestr.length());
  270. }
  271. System.out.print("写配置块成功,16进制卡序列号:" + cardnohex + "\n");
  272. }else {
  273. PrintErrInf(status); //错误代码提示
  274. }
  275. }else if (args[0].equals("9")) //修改T5557卡密钥
  276. {
  277. System.out.print("\n9-修改T5557卡密钥\n");
  278. byte status; //存放返回值
  279. byte myctrlword=0; //控制字
  280. byte[] oldpicckey=new byte[4]; //认证密钥
  281. byte[] newpicckey=new byte[4]; //卡片新密钥
  282. byte[] mypiccserial=new byte[6]; //卡UID序列号
  283. boolean withkey=true; //是否要认证卡密钥
  284. boolean thiscarduit =false; //是否只操作指定卡号的卡
  285. if (withkey){ //本次操作需要密码验证,将认证密钥加入oldpicckey
  286. myctrlword=(byte)(myctrlword+NEEDKEY);
  287. String oldKeyhexstr="12345678"; //认证密钥
  288. for(int i=0;i<4;i++){
  289. oldpicckey[i]=(byte)Integer.parseInt(oldKeyhexstr.substring(i*2,(i+1)*2),16);
  290. }
  291. }
  292. if(thiscarduit){ //本次只操作指定UID号的卡,mypiccserial
  293. myctrlword=(byte)(myctrlword+NEEDSERIAL);
  294. String Uidhexstr="000000000000"; //卡片uid
  295. for(int i=0;i<6;i++){
  296. mypiccserial[i]=(byte)Integer.parseInt(Uidhexstr.substring(i*2,(i+1)*2),16);
  297. }
  298. }
  299. String newKeyhexstr="12345678"; //新密钥
  300. for(int i=0;i<4;i++){
  301. newpicckey[i]=(byte)Integer.parseInt(newKeyhexstr.substring(i*2,(i+1)*2),16);
  302. }
  303. status = CLibrary.sdtapi.t5557_changekey(myctrlword,mypiccserial,oldpicckey,newpicckey);
  304. if(status == 0) {
  305. CLibrary.sdtapi.idr_beep(38);
  306. String cardnohex = "";
  307. for (int i = 0; i < 6; i++) {
  308. String bytestr = "00" + Integer.toHexString(mypiccserial[i] & 0xff);
  309. cardnohex = cardnohex + bytestr.substring(bytestr.length() - 2, bytestr.length());
  310. }
  311. System.out.print("修改卡密钥成功,16进制卡序列号:" + cardnohex + "\n");
  312. }else {
  313. PrintErrInf(status); //错误代码提示
  314. }
  315. }
  316. }
  317. //----------------------------------------------------------------------------------错误字符串代码提示
  318. static void PrintErrStr(String Errstr){
  319. if(Errstr.equals("ER08")){
  320. System.out.print("错误代码:ER08,未寻到卡,请重新拿开卡后再放到感应区!\n");
  321. } else if(Errstr.equals("ER22")){
  322. System.out.print("错误代码:ER22,动态库或驱动程序异常!\n");
  323. } else if(Errstr.equals("ER23")){
  324. System.out.print("错误代码:ER23,驱动程序错误或尚未安装!\n");
  325. } else if(Errstr.equals("ER24")){
  326. System.out.print("错误代码:ER24,操作超时,一般是动态库没有反映!\n");
  327. }else {
  328. System.out.print("错误代码:"+Errstr);
  329. }
  330. }
  331. //----------------------------------------------------------------------------------错误代码提示
  332. static void PrintErrInf(int errcode) {
  333. switch(errcode){
  334. case 1:
  335. System.out.print("错误代码:1,写入配置的值不正确,请重新写入!\n");
  336. break;
  337. case 2:
  338. System.out.print("错误代码:2,本卡尚未开启密码功能,函数myctrlword中无需加入NEEDKEY!\n");
  339. break;
  340. case 3:
  341. System.out.print("错误代码:3,需要密码才能读卡,函数myctrlword要加入NEEDKEY!\n");
  342. break;
  343. case 5:
  344. System.out.print("错误代码:5,密码错误!\n");
  345. break;
  346. case 8:
  347. System.out.print("错误代码:8,未寻到卡,请重新拿开卡后再放到感应区!\n");
  348. break;
  349. case 21:
  350. System.out.print("错误代码:21,没有动态库!\n");
  351. break;
  352. case 22:
  353. System.out.print("错误代码:22,动态库或驱动程序异常!\n");
  354. break;
  355. case 23:
  356. System.out.print("错误代码:23,驱动程序错误或尚未安装!\n");
  357. break;
  358. case 24:
  359. System.out.print("错误代码:24,操作超时,一般是动态库没有反映!\n");
  360. break;
  361. case 25:
  362. System.out.print("错误代码:25,发送字数不够!\n");
  363. break;
  364. case 26:
  365. System.out.print("错误代码:26,发送的CRC错!\n");
  366. break;
  367. case 27:
  368. System.out.print("错误代码:27,接收的字数不够!\n");
  369. break;
  370. case 28:
  371. System.out.print("错误代码:28,接收的CRC错!\n");
  372. break;
  373. default:
  374. System.out.print("未知错误,错误代码:"+Integer.toString(errcode)+"\n");
  375. break;
  376. }
  377. }
  378. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小舞很执着/article/detail/983683
推荐阅读
相关标签
  

闽ICP备14008679号