卡库的封装和调用,这是一个重头戏,完成了它,则就完整了所有的封装。至于网络通信,记录存储等,则可以

使用go本身的模块去做。后续做一版完整的go语言版B503应用。

截至目前,非接触式卡库的封装接近尾声,这部分花了不少精力。

package drivers/*#cgo CFLAGS: -Iinclude#cgo LDFLAGS: -Llib -lpicc
#include <stdlib.h>
#include "pcd_apis.h"
*/
import "C"
import "unsafe"import ("fmt""log"
)const (DEF_PCD_SeleTypeA int = 1DEF_PCD_SeleTypeB int = 2
)type __Pcd14443Cfg struct {PPS   int //AB  0:标准的支持PPS,非0:强制不支持PPSM1CPU int //AB  0:自动识别,1:强制M1,2:强制CPU
}
type __Pcd14443Info struct {ATQA []byte //A专用   REQA命令返回的ATQA值          固定有效2字节UID  []byte //A专用   卡片的UID,                   长度为4,7,10字节UID_Size byte //A专用   卡片的UID长度                   长度为4,7,10字节SAK      byte //A专用   卡片选卡成功返回的SAK值          固定有效1字节TypeAB   byte //A/B共用 当前是A卡还是B卡     DEF_PCD_SeleTypeA=A卡,DEF_PCD_SeleTypeB=B卡ATS_Size byte //A专用   接收到的ATS数据长度BActive  byte //B激活状态 0:非激活  非0:激活Rvs08bit byteRvs16bit byteATS []byte //A专用   ATS接收数据缓冲区 按中国金融规定 PICC回的数据最长为21字节ATQB []byte //B专用   卡片应答数据} //14443应用数据结构var (Pcd14443CfgMode int = DEF_PCD_SeleTypeA //PCD选择TypeA卡 操作PICC类型定义Pcd14443CfgA    __Pcd14443CfgPcd14443CfgB    __Pcd14443CfgPcd14443Info    __Pcd14443Info //14443协议层数据缓冲区PiccCid int
)func init() {Pcd14443Info.ATQA = make([]byte, 4)Pcd14443Info.UID = make([]byte, 16)Pcd14443Info.ATS = make([]byte, 40)Pcd14443Info.ATQB = make([]byte, 20)
}func ICC_PCD_SysCfg(mode, m1, pps int) {Pcd14443CfgMode = modeif DEF_PCD_SeleTypeA == Pcd14443CfgMode {Pcd14443CfgA.PPS = ppsPcd14443CfgA.M1CPU = m1} else if DEF_PCD_SeleTypeB == Pcd14443CfgMode {Pcd14443CfgB.PPS = ppsPcd14443CfgB.M1CPU = m1}}func ICC_PCD_Init() int {tpe := make([]byte, 4)para := make([]byte, 50)//var cardType *C.uchar = (*C.uchar)(unsafe.Pointer(&tpe[0]))//var rfPara *C.uchar = (*C.uchar)(unsafe.Pointer(&para[0]))cardType := (*C.uchar)(unsafe.Pointer(&tpe[0]))rfPara := (*C.uchar)(unsafe.Pointer(&para[0]))ret := C.PcdInit(cardType, rfPara)if ret != 0 {return 1}fmt.Println(tpe)fmt.Println(para)ret = C.PiccOpen()return int(ret)}func ICC_PCD_Open() int {ret := C.PiccOpen()return int(ret)
}func ICC_PCD_Close() {C.PiccClose()
}//ISO14443 A/B 使卡进入HALT状态
func ICC_PCD_Halt() int {//nc_iso14443_debug("%s","ICC_PCD_Halt\n");ret := C.PiccRemove('H', C.uchar(PiccCid))return int(ret)
}//ISO14443 A/B 使已经进入HALT状态的卡激活,并且进行冲突循环,选卡操作
func ICC_PCD_WakeUp() int {ret := ICC_PCD_Request(Pcd14443CfgMode)return int(ret)
}func ICC_PCD_Request(mode int) int {tpe := make([]byte, 4)sno := make([]byte, 100)oth := make([]byte, 100)pid := make([]byte, 1)lenth := 0ptr := 0ret := C.uchar(0)cardType := (*C.uchar)(unsafe.Pointer(&tpe[0]))serialNo := (*C.uchar)(unsafe.Pointer(&sno[0]))other := (*C.uchar)(unsafe.Pointer(&oth[0]))piccid := (*C.uchar)(unsafe.Pointer(&pid[0]))if DEF_PCD_SeleTypeA == Pcd14443CfgMode {if DEF_PCD_SeleTypeA == Pcd14443CfgA.M1CPU { //强制M1ret = C.PiccDetect('M', cardType, serialNo, piccid, other)} else if DEF_PCD_SeleTypeB == Pcd14443CfgA.M1CPU { //强制CPUAret = C.PiccDetect('A', cardType, serialNo, piccid, other)} else if 3 == Pcd14443CfgA.M1CPU { //自动检测A,B,无法检测到纯M1 操作一次28msret = C.PiccDetect(0x01, cardType, serialNo, piccid, other)} else { //自动CPUA/M1 操作一次18msret = C.PiccDetect('X', cardType, serialNo, piccid, other)}//        printf(">>>>>>>>>>>>PiccDetect, ret=%d   count=%d\n", ret, count++);} else if DEF_PCD_SeleTypeB == Pcd14443CfgMode { //强制CPUBret = C.PiccDetect('B', cardType, serialNo, piccid, other)} else {log.Fatal("err config!")}//fmt.Printf("ret = %d\n", int(ret))PiccCid = int(pid[0])if ret == 0 {//fmt.Printf("tpe:%x\n", tpe)//fmt.Printf("sno:%x\n", sno)//fmt.Printf("oth:%x\n", oth)if 'B' == tpe[0] {Pcd14443Info.TypeAB = byte(DEF_PCD_SeleTypeB) //TYPE B} else if 'M' == tpe[0] {Pcd14443Info.TypeAB = byte(DEF_PCD_SeleTypeA) //TYPE A} else {Pcd14443Info.TypeAB = byte(DEF_PCD_SeleTypeA) //TYPE A}if sno[0] > 10 { //序列号长度不能大于10return 1}Pcd14443Info.UID_Size = sno[0]copy(Pcd14443Info.UID, sno[1:1+Pcd14443Info.UID_Size])if oth[0] > 2 {ptr = 3lenth = int(oth[ptr])ptr += 1if ptr+lenth < len(oth) {copy(Pcd14443Info.ATQA, oth[ptr:ptr+2])//fmt.Printf("ATQA:%x\n", Pcd14443Info.ATQA)}ptr += lenthlenth = int(oth[ptr])ptr += 1if ptr+lenth < len(oth) {Pcd14443Info.SAK = oth[ptr]}ptr += lenthlenth = int(oth[ptr])if 'A' == tpe[0] && (ptr+lenth < len(oth)) {copy(Pcd14443Info.ATS, oth[ptr:ptr+lenth])Pcd14443Info.ATS_Size = byte(lenth)}//fmt.Println(Pcd14443Info)fmt.Printf("ATQA:%x\n", Pcd14443Info.ATQA)fmt.Printf("SAK:%x\n", Pcd14443Info.SAK)fmt.Printf("UID:%x\n", Pcd14443Info.UID)}} else {Pcd14443Info.ATQA[0] = 0Pcd14443Info.ATQA[1] = 0Pcd14443Info.ATQA[2] = 0Pcd14443Info.ATQA[3] = 0}return int(ret)
}//ISO14443 A/B 检测卡片是否存在,卡片激活状态后调用
func ICC_PCD_CheckPICCRounge() int {ret := C.PiccRemove('C', C.uchar(PiccCid))//nc_iso14443_debug("PiccRemove('C').ret=%d\n", ret);if 0x06 == ret { //卡片仍在感应区//nc_iso14443_debug( "%s", "Card exist\n" ); //PiccRemove('C')停活卡片,需要重新寻卡以激活卡片return 0 //返回卡片仍在} else {//nc_iso14443_debug( "%s", "Card removed\n" );return 1 //返回卡片离开}}//ISO14443 A/B 检测PICC是否移出工作场
func ICC_PCD_CheckPICCrf() int {ret := C.PiccRemove('R', C.uchar(PiccCid))//nc_iso14443_debug("PiccRemove('C').ret=%d\n", ret);if 0x06 == ret { //卡片仍在感应区//nc_iso14443_debug( "%s", "Card exist\n" ); //PiccRemove('C')停活卡片,需要重新寻卡以激活卡片return 0 //返回卡片仍在} else {//nc_iso14443_debug( "%s", "Card removed\n" );return 1 //返回卡片离开}
}//ISO14443 A/B 等待PICC移出工作场
func ICC_PCD_WaitPICCrf() int {for true {ret := C.PiccRemove('C', C.uchar(PiccCid))//nc_iso14443_debug("PiccRemove('C').ret=%d\n", ret);if 0x06 == ret {//nc_iso14443_debug( "%s", "Card exist\n" );continue //返回卡片仍在} else {//nc_iso14443_debug( "%s", "Card removed\n" );break //卡片移出}}return 0
}//ISO14443 A/B 复位工作场
func ICC_PCD_ResetPCDrf() int {C.PiccClose()ret := C.PiccOpen()//nc_iso14443_debug("ICC_PCD_ResetPCDrf. ret = %d\n", ret);return int(ret)
}func ICC_PCD_APDUCommand(in []byte, inlen int, out []byte, outlen *int, maxsize int, lc, le byte) int {var ApduSend C.APDU_SENDvar ApduResp C.APDU_RESPApduSend.Command[0] = C.uchar(in[0])ApduSend.Command[1] = C.uchar(in[1])ApduSend.Command[2] = C.uchar(in[2])ApduSend.Command[3] = C.uchar(in[3])ApduSend.Lc = C.ushort(lc)for i := 0; i < int(lc); i++ {ApduSend.DataIn[i] = C.uchar(in[5+i])}if le != 0 { //此处须填非0值,若le非0则填实际值,否则固定填256ApduSend.Le = C.ushort(le)} else {ApduSend.Le = 256}fmt.Printf("->APDU:%x\n", in[0:inlen])ret := C.PiccIsoCommand(C.uchar(PiccCid), &ApduSend, &ApduResp)if ret != 0 {return int(ret)}if (le != 0) && (byte(ApduResp.LenOut) != le) {}if int(ApduResp.LenOut+2) < maxsize { //还有两个字节的状态字节 SWA/SWB//memcpy( out, &ApduResp.DataOut[0], ApduResp.LenOut );for i := 0; i < int(ApduResp.LenOut); i++ {out[i] = byte(ApduResp.DataOut[i])}out[ApduResp.LenOut] = byte(ApduResp.SWA)out[ApduResp.LenOut+1] = byte(ApduResp.SWB)} else {//memcpy( out, &ApduResp.DataOut[0], maxsize-2 );for i := 0; i < maxsize-2; i++ {out[i] = byte(ApduResp.DataOut[i])}out[ApduResp.LenOut] = byte(ApduResp.SWA)out[ApduResp.LenOut+1] = byte(ApduResp.SWB)}*outlen = int(ApduResp.LenOut + 2)fmt.Printf("<-APDU:%x\n", out[0:ApduResp.LenOut+2])return 0
}
func main() {fmt.Println("Hello Go")ret := ICC_PCD_Init()if ret == 0 {fmt.Println("ICC PCD init ok!")ICC_PCD_SysCfg(DEF_PCD_SeleTypeA, 0, 1)for i := 0; i < 100; i++ {ret = ICC_PCD_Request(DEF_PCD_SeleTypeA)if ret == 0 {fmt.Println("find card ok!")} else {fmt.Println("not find card!")}}} else {fmt.Printf("ICC PCD init err!,code=%d\n", ret)}name := ""fmt.Println("over!press any key to continue: ")fmt.Scanln(&name)
}
package cardimport ("encoding/hex""fmt""go8583/drivers""math/rand""time"
)func ICF_GetChallenge8B(Rnd []byte, ich int) int {CmdBuffer[0] = 0x00 //CLACmdBuffer[1] = 0x84 //INSCmdBuffer[2] = 0x00 //P1CmdBuffer[3] = 0x00 //P2CmdBuffer[4] = 0x08 //Lercode := drivers.ICC_APDU_Exchange(ich, CmdBuffer, 5, RcvBuffer, &Grcv_Len, 260, 0, CmdBuffer[4])if rcode != 0 {fmt.Printf("ICC_APDU_Exchange err,code=%d\n", rcode)return rcode}if Grcv_Len < 2 {return 2}rcode = ((int(RcvBuffer[Grcv_Len-2]) << 8) | int(RcvBuffer[Grcv_Len-1]))if rcode != 0x9000 {return rcode}copy(Rnd, RcvBuffer[0:8])return rcode}func ICF_SelectAID(AID []byte, ilen int, ich int) int {CmdBuffer[0] = 0x00       //CLACmdBuffer[1] = 0xA4       //INSCmdBuffer[2] = 0x04       //P1CmdBuffer[3] = 0x00       //P2CmdBuffer[4] = byte(ilen) //Lccopy(CmdBuffer[5:], AID[0:ilen])rcode := drivers.ICC_APDU_Exchange(ich, CmdBuffer, ilen+5, RcvBuffer, &Grcv_Len, 260, CmdBuffer[4], 0)if rcode != 0 {fmt.Printf("ICC_APDU_Exchange err,code=%d\n", rcode)return rcode}if Grcv_Len < 2 {return 2}rcode = ((int(RcvBuffer[Grcv_Len-2]) << 8) | int(RcvBuffer[Grcv_Len-1]))if rcode != 0x9000 {return rcode}return rcode}//{9f38 18 9f66049f02069f03069f1a0295055f2a029a039c019f3704}
func UP_GPO(pdoc []byte, lenth byte, ich int) int {CmdBuffer[0] = 0x80      //CLACmdBuffer[1] = 0xA8      //INSCmdBuffer[2] = 0x00      //P1CmdBuffer[3] = 0x00      //P2   ‘01’用于ED(电子存折,需要个人密码PIN ‘02’用于EP(电子钱包)CmdBuffer[4] = lenth + 2 //LcCmdBuffer[5] = 0x83CmdBuffer[6] = lenthcopy(CmdBuffer[7:], pdoc[0:lenth])rcode := drivers.ICC_APDU_Exchange(ich, CmdBuffer, int(lenth+8), RcvBuffer, &Grcv_Len, 260, CmdBuffer[4], 0)if rcode != 0 {fmt.Printf("ICC_APDU_Exchange err,code=%d\n", rcode)return rcode}if Grcv_Len < 2 {return 2}rcode = ((int(RcvBuffer[Grcv_Len-2]) << 8) | int(RcvBuffer[Grcv_Len-1]))if rcode != 0x9000 {return rcode}return rcode}/*
*双免GPO组包*/
//{9f38 18 9f66049f02069f03069f1a0295055f2a029a039c019f3704}
func UP_qUICS(money int, opdt string, ich int) int {t9F66 := "........"                  //交易属性t9F02 := fmt.Sprintf("%012d", money) //授权金额t9F03 := "000000000000"t9F1A := "0156"t95 := "0000000000"t5F2A := "0156"t9A := opdtt9C := "00"rand.Seed(time.Now().Unix())t9F37 := fmt.Sprintf("%08x", rand.Int31())pdoc := t9F66 + t9F02 + t9F03 + t9F1A + t95 + t5F2A + t9A + t9C + t9F37fmt.Printf("pdoc:%s\n", pdoc)bpdoc, err := hex.DecodeString(pdoc)if err != nil {fmt.Printf("DecodeString error:%s\n", err.Error())}fmt.Printf("bpdoc:%x\n", bpdoc)return UP_GPO(bpdoc, byte(len(bpdoc)), ich)}

root@b503_lcd:/app/city_app/opt# ./cardlib
Hello Go
ATQA:08000000
SAK:20
UID:5deaa62a000000000000000000000000
find card ok!

ATQA:04000000
SAK:28
UID:2f7bb136000000000000000000000000
find card ok!
->APDU:00a404000e325041592e5359532e4444463031
<-APDU:6f30840e325041592e5359532e4444463031a51ebf0c1b61194f08a000000333010101500a50424f432044454249548701019000
ICF_SelectAID ok!
[{6f 30 840e325041592e5359532e4444463031a51ebf0c1b61194f08a000000333010101500a50424f43204445424954870101} {84 0e 325041592e5359532e4444463031} {a5 1e bf0c1b61194f08a000000333010101500a50424f43204445424954870101} {bf0c 1b 61194f08a000000333010101500a50424f43204445424954870101} {61 19 4f08a000000333010101500a50424f43204445424954870101} {4f 08 a000000333010101} {50 0a 50424f43204445424954} {87 01 01}]

嵌入式linux之go语言开发(三)卡库的封装相关推荐

  1. 嵌入式 linux 应用 go 语言开发(开篇,缘起)

    go语言被称作互联网时代的c语言,用来开发嵌入式linux是一种享受. 希望能否带来开发工作效率的提升,产品质量稳定性方面的提升,产品功能上的增强. 物联网时代,就是要有所"变革" ...

  2. 嵌入式linux之go语言开发(六)几行代码实现终端的远程日志诊断

    日志是应用的镜子,可以发现应用中的问题,重要性不言而喻. 以往设备有问题了,是如何诊断的?我们是现场人员到现场,又是配合抓包,又是配合提供机器日志,效率极其低下. 如今都物联网时代了,能让数据跑路的还 ...

  3. 嵌入式linux之go语言开发(九)关于嵌入式GUI

    go语言没有官方的GUI. 其实怎么说呢,这一块儿的需求也不怎么迫切.毕竟每个语言都有自己擅长的领域. 在电脑上开发界面还是C#或QT或java的swing来的快.没必要非用go吧,更多的是在电脑上基 ...

  4. 《嵌入式Linux与物联网软件开发——C语言内核深度解析》一第1章 C语言与内存1.1 引言...

    本节书摘来自异步社区<嵌入式Linux与物联网软件开发--C语言内核深度解析>一书中的第1章,第1.1节,作者朱有鹏 , 张先凤,更多章节内容可以访问云栖社区"华章计算机&quo ...

  5. 《嵌入式Linux与物联网软件开发——C语言内核深度解析》一2.4 位运算构建特定二进制数...

    本节书摘来自异步社区<嵌入式Linux与物联网软件开发--C语言内核深度解析>一书中的第2章,第2.4节,作者朱有鹏 , 张先凤,更多章节内容可以访问云栖社区"异步社区" ...

  6. 嵌入式 Linux 入门 环境篇(三、开发板和 PC 的网络互通)

    嵌入式 Linux入门 环境篇第三课,开发板与PC的网络配置, 我们要实现 windows.ubuntu 和开发板三者的互通. ...... by 矜辰所致 前言 在环境篇前面的文章我们通过终端工具使 ...

  7. 嵌入式Linux与物联网软件开发:C语言内核深度解析

    嵌入式Linux与物联网软件开发:C语言内核深度解析     1.C语言与内存         1.引言         2.计算机程序运行的目的         3.位.半字.字的概念和内存位宽   ...

  8. 嵌入式 Linux 与物联网软件开发 ——C 语言内核深度解析

    C 语言是嵌入式 Linux 领域的主要开发语言. 对于学习嵌入式.单片机.Linux 驱动开发等技术来说,C 语言是必须要过的一关.C 语言学习的特点是入门容易.深入理解难.精通更是难上加难.很多用 ...

  9. 关于Linux下C语言开发基础的实验内容。

    Linux下C语言开发基础实验内容 目录 1.Linux下C语言开发流程 2.vi,vim编辑器的使用 3.Gcc编译器的使用 总体选项: 警告选项: 4.GDB 基本命令的使用 5.Make 工程管 ...

最新文章

  1. 5.C#-if-else分支语句结构
  2. httpclient通过POST来上传文件,而不是通过流的形式,并在服务端进行解析(通过htt......
  3. ASP.NET MVC扩展库
  4. MySQL排序优化(两次排序和单次排序)
  5. win10浏览器_Win10系统中ie浏览器的证书错误应该如何解决?
  6. php str_replace 字符串替换
  7. 库卡机器人是s7编程_「西门子1200PLC教程」19.S7-1200入门实例
  8. ios 应用商店_如何在预算范围内制作值得应用商店使用的iOS应用预览
  9. python3 mysql库_Python3.7 MySQL 数据库连接
  10. ajax传值给python_ajax向python脚本传递参数
  11. 32muduo_net库源码分析(八)
  12. centos7 firewalld
  13. php调试利器之phpdbg
  14. 分享一款WIFI抓包工具,支持Mac和Windows
  15. Ubuntu14下安装使用SVN RabbitVCS客户端
  16. 树莓派的蓝牙通讯(bluez、gattlib)
  17. 获取iOS设备唯一标示
  18. 手把手教你做出数据可视化项目(三)3D地球旋转
  19. 常见通信协议与通讯协议梳理- 通讯协议
  20. Downward paths

热门文章

  1. 嘚瑟一下,我的书上电视了!
  2. java调用飞信接口免费短信发送到对方手机
  3. 懒癌必备-dplyr和data.table让你的数据分析事半功倍
  4. 多个电商平台聚合关键字搜索接口
  5. 【图文并茂】U盘启动盘制作 U盘启动盘重装系统教程
  6. springboot根据request.getSession().getServletContext().getRealPath(“/“); 访问项目静态资源问题
  7. wifi的sta + ap模式
  8. gs_fs0文件是什么_“ FS” /“ GS”寄存器的用途是什么?
  9. jsp 和 servlet 有什么区别?
  10. 转:Processing 编程学习指南