Android Linux RFID读写器NFC发卡器WEB可编程NDEF文本/智能海报/-淘宝网 (taobao.com)
IC卡的特性
1、分为16个扇区,每个扇区为4块,每块16个字节,以块为存取单位;
2、每个扇区有独立的一组密码及访问控制;
3、每张卡有唯一序列号,为32位;
4、具有防冲突机制,支持多卡操作;
5、无电源,自带天线,内含加密控制逻辑和通讯逻辑电路;
6、数据保存期为10年,可改写10万次,读无限次;
7、工作温度:-20℃~50℃(湿度为90%);
8、工作频率:13.56MHZ;
9、通信速率:106 KBPS;
10、读写距离:10 cm以内。
IC卡的存储结构
1、M1卡分为16个扇区,每个扇区由4块(块0、块1、块2、块3)组成,(我们也将16个扇区的64个块按绝对地址编号为0~63,存贮结构如下图所示:
2、第0扇区的块0(即绝对地址0块),它用于存放厂商代码,已经固化,不可更改。
3、每个扇区的块0、块1、块2为数据块,可用于存贮数据。
4、每个扇区的块3为控制块,包括了密码A、存取控制、密码B;
5、每个扇区的密码和存取控制都是独立的,可以根据实际需要设定各自的密码及存取控制。存取控制为4个字节,共32位,扇区中的每个块(包括数据块和控制块)的存取条件是由密码和存取控制共同决定的,在存取控制中每个块都有相应的三个控制位。
#include "mainwindow.h"
#include "./ui_mainwindow.h"
#include <QDebug>
#include "QLibrary"
#include "QMessageBox"
#define BLOCK0_EN 0x01 //读写块0
#define BLOCK1_EN 0x02 //读写块1
#define BLOCK2_EN 0x04 //读写块2
#define NEEDSERIAL 0x08 //写指定序列号的卡
#define EXTERNKEY 0x10 //需要每次指定密码
#define NEEDHALT 0x20 //写卡后是否休眠卡
unsigned char oldblock[16]; //记录读取的块数据
//让读写器发出声音
typedef unsigned char (*pcdbeep)(unsigned long xms);
#ifdef Q_OS_WIN
pcdbeep mypcdbeep = (pcdbeep)QLibrary("OUR_MIFARE.dll").resolve("pcdbeep");
#else
pcdbeep mypcdbeep = (pcdbeep)QLibrary("./libOURIDR.so").resolve("pcdbeep");
#endif
//返回本读写器独一无二的设备编号
typedef unsigned char (*pcdgetdevicenumber)(unsigned char *devicenumber);
#ifdef Q_OS_WIN
pcdgetdevicenumber mypcdgetdevicenumber = (pcdgetdevicenumber)QLibrary("OUR_MIFARE.dll").resolve("pcdgetdevicenumber");
#else
pcdgetdevicenumber mypcdgetdevicenumber = (pcdgetdevicenumber)QLibrary("./libOURMIFARE.so").resolve("pcdgetdevicenumber");
#endif
//寻卡获取卡号
typedef unsigned char (*piccrequest)(unsigned char *serial);
#ifdef Q_OS_WIN
piccrequest mypiccrequest = (piccrequest)QLibrary("OUR_MIFARE.dll").resolve("piccrequest");
#else
piccrequest mypiccrequest = (piccrequest)QLibrary("./libOURIDR.so").resolve("piccrequest");
#endif
//轻松读卡
typedef unsigned char (*piccreadex)(unsigned char ctrlword,unsigned char *serial,unsigned char area,unsigned char keyA1B0,unsigned char *picckey,unsigned char *piccdata0_2);
#ifdef Q_OS_WIN
piccreadex mypiccreadex = (piccreadex)QLibrary("OUR_MIFARE.dll").resolve("piccreadex");
#else
piccreadex mypiccreadex = (piccreadex)QLibrary("./libOURIDR.so").resolve("piccreadex");
#endif
//轻松写卡
typedef unsigned char (*piccwriteex)(unsigned char ctrlword,unsigned char *serial,unsigned char area, unsigned char keyA1B0,unsigned char *picckey,unsigned char *piccdata0_2);
#ifdef Q_OS_WIN
piccwriteex mypiccwriteex = (piccwriteex)QLibrary("OUR_MIFARE.dll").resolve("piccwriteex");
#else
piccwriteex mypiccwriteex = (piccwriteex)QLibrary("./libOURIDR.so").resolve("piccwriteex");
#endif
//校验卡片扇区密码piccauthkey1
typedef unsigned char (*piccauthkey1)(unsigned char *serial,unsigned char area, unsigned char keyA1B0,unsigned char *picckey);
#ifdef Q_OS_WIN
piccauthkey1 mypiccauthkey1 = (piccauthkey1)QLibrary("OUR_MIFARE.dll").resolve("piccauthkey1");
#else
piccauthkey1 mypiccauthkey1 = (piccauthkey1)QLibrary("./libOURIDR.so").resolve("piccauthkey1");
#endif
//改单区密码
typedef unsigned char (*piccchangesinglekeyex)(unsigned char ctrlword,unsigned char *serial,unsigned char area,unsigned char keyA1B0,unsigned char *piccoldkey,unsigned char *piccdata);
#ifdef Q_OS_WIN
piccchangesinglekeyex mypiccchangesinglekeyex = (piccchangesinglekeyex)QLibrary("OUR_MIFARE.dll").resolve("piccchangesinglekeyex");
#else
piccchangesinglekeyex mypiccchangesinglekeyex = (piccchangesinglekeyex)QLibrary("./libOURIDR.so").resolve("piccchangesinglekeyex");
#endif
//读出一块的数据,也就是16个字节
typedef unsigned char (*piccread)(unsigned char block,unsigned char *piccdata);
#ifdef Q_OS_WIN
piccread mypiccread = (piccread)QLibrary("OUR_MIFARE.dll").resolve("piccread");
#else
piccread mypiccread = (piccread)QLibrary("./libOURIDR.so").resolve("piccread");
#endif
//写一块数据16字节 piccwrite
typedef unsigned char (*piccwrite)(unsigned char block,unsigned char *piccdata);
#ifdef Q_OS_WIN
piccwrite mypiccwrite = (piccwrite)QLibrary("OUR_MIFARE.dll").resolve("piccwrite");
#else
piccwrite mypiccwrite = (piccwrite)QLibrary("./libOURIDR.so").resolve("piccwrite");
#endif
//写0区0块 piccwriteserial
typedef unsigned char (*piccwriteserial)(unsigned char ctrlword,unsigned char *serial,unsigned char keyA1B0,unsigned char *picckey,unsigned char *piccdata0_2);
#ifdef Q_OS_WIN
piccwriteserial mypiccwriteserial = (piccwriteserial)QLibrary("OUR_MIFARE.dll").resolve("piccwriteserial");
#else
piccwriteserial mypiccwriteserial = (piccwriteserial)QLibrary("./libOURIDR.so").resolve("piccwriteserial");
#endif
//检测输入数据是否为16进制数
static bool checkinput(QString inputstr){
QString inputyes="0123456789abcdefABCDEF";
for(int i=0;i<inputstr.length();i++){
if(inputyes.contains(inputstr.mid(i,1),Qt::CaseSensitive)){
}else{return false;}
}
return true;
}
//检测动态库文件是否在运行目录内
static bool checkdllos(){
#ifdef Q_OS_WIN
QLibrary mylib("OUR_MIFARE.dll");
if (!mylib.load()){ //判断windows系统下,OUR_MIFARE.dll是否在运行目录内
QMessageBox::information(NULL, "提示", "请将OUR_MIFARE.dll文件拷贝到生成exe文件相同目录下!");
return false;
}else{return true;}
#else
QLibrary mylib("./libOURIDR.so");
if (!mylib.load()){ //判断linux系统下,libOURIDR.so是否正运行目录内
QMessageBox::information(NULL, "提示", "请将libOURIDR.so文件拷贝到生成的运行文件相同目录下!");
return false;
}else{return true;}
#endif
}
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
ui->comboBox_2->setCurrentIndex(1);
}
MainWindow::~MainWindow()
{
delete ui;
}
static QString DecimalToHex(long long decimal)
{
QString hex = "";
while (decimal > 0)
{
int remainder = decimal % 16;
if (remainder < 10)
hex = (char)(remainder + '0') + hex;
else
hex = (char)(remainder + 'A' - 10) + hex;
decimal /= 16;
}
return hex;
}
//显示返回的错误代码信息
static void disperrinf(unsigned char result){
switch (result) {
case 1:
QMessageBox::critical(NULL, "提示", QString::asprintf("错误代码:%d", result)+",0~2块都没读出来,可能刷卡太块。但卡序列号已被读出来!");
break;
case 2:
QMessageBox::critical(NULL, "提示", QString::asprintf("错误代码:%d", result)+",第0块已被读出,但1~2块读取失败。卡序列号已被读出来!");
break;
case 3:
QMessageBox::critical(NULL, "提示", QString::asprintf("错误代码:%d", result)+",第0、1块已被读出,但2块读取失败。卡序列号已被读出来!");
break;
case 8:
QMessageBox::critical(NULL, "提示", QString::asprintf("错误代码:%d", result)+",未寻到卡,请重新拿开卡后再放到感应区!");
break;
case 9:
QMessageBox::critical(NULL, "提示", QString::asprintf("错误代码:%d", result)+",有多张卡在感应区,寻卡过程中防冲突失败,读序列吗错误!");
break;
case 10:
QMessageBox::critical(NULL, "提示", QString::asprintf("错误代码:%d", result)+",该卡可能已被休眠,无法选中卡片!");
break;
case 11:
QMessageBox::critical(NULL, "提示", QString::asprintf("错误代码:%d", result)+",密码装载失败!");
break;
case 12:
QMessageBox::critical(NULL, "提示", QString::asprintf("错误代码:%d", result)+",卡片密码认证失败!");
break;
case 13:
QMessageBox::critical(NULL, "提示", QString::asprintf("错误代码:%d", result)+",读指定块失败,原因是刷卡太快或本块所对应的区还没通过密码认证!");
break;
case 14:
QMessageBox::critical(NULL, "提示", QString::asprintf("错误代码:%d", result)+",写指定块失败,原因是刷卡太快或本块所对应的区还没通过密码认证!");
break;
case 18:
QMessageBox::critical(NULL, "提示", QString::asprintf("错误代码:%d", result)+",写UID失败,此卡可能不是UID卡!");
break;
case 22:
QMessageBox::critical(NULL, "提示", QString::asprintf("错误代码:%d", result)+",动态库或驱动程序异常!");
break;
case 23:
QMessageBox::critical(NULL, "提示", QString::asprintf("错误代码:%d", result)+",驱动程序错误或发卡器尚未安装!");
break;
case 24:
QMessageBox::critical(NULL, "提示", QString::asprintf("错误代码:%d", result)+",操作超时,一般是动态库没有反应!");
break;
case 25:
QMessageBox::critical(NULL, "提示", QString::asprintf("错误代码:%d", result)+",发送字数不够!");
break;
case 26:
QMessageBox::critical(NULL, "提示", QString::asprintf("错误代码:%d", result)+",驱动程序错误或发卡器尚未安装!");
break;
case 27:
QMessageBox::critical(NULL, "提示", QString::asprintf("错误代码:%d", result)+",操作超时,一般是动态库没有反应!");
break;
case 28:
QMessageBox::critical(NULL, "提示", QString::asprintf("错误代码:%d", result)+",发送字数不够!");
break;
default:
QMessageBox::critical(NULL, "提示", QString::asprintf("错误代码:%d", result)+",未知的错误信息!");
break;
}
}
void MainWindow::on_pushButton_beep_clicked()
{
if(!checkdllos()){return;}
unsigned char status;
status = mypcdbeep(30);
if(status==0){
ui->listWidget->addItem("发卡器已响应响声指令!");
}
else
{
disperrinf(status);
}
}
void MainWindow::on_pushButton_getdevicenum_clicked()
{
if(!checkdllos()){return;} //判断运行目录内动态库文件是否存在
unsigned char devicenumber[4]; //设备编号缓冲
unsigned char status; //函数返回状态
if (mypcdgetdevicenumber != NULL){ //是否成功连接上 pcdgetdevicenumber()函数
status = mypcdgetdevicenumber(devicenumber);
if(status==0){
mypcdbeep(30);
ui->listWidget->addItem( QString::asprintf("设备编号:%03d-%03d-%03d-%03d", devicenumber[0],devicenumber[1],devicenumber[2],devicenumber[3]));
}
else
{
disperrinf(status);
}
}else{
QMessageBox::critical(NULL, "提示", "函数‘pcdgetdevicenumber’未正确载入,请查询DLL文件版本是否正确!");
}
}
void MainWindow::on_pushButton_clearlist_clicked()
{
ui->listWidget->clear();
}
void MainWindow::on_pushButton_piccreadex_clicked()
{
if(!checkdllos()){return;}
unsigned char ctrlword; //控制字
unsigned char serial[4]; //可写数组,存放4字节卡UID
unsigned char area; //读出的区号
unsigned char keyA1B0; //AB密码认证
unsigned char picckey[6]; //存放卡密码的数组
unsigned char piccdata0_2[48]; //下标0~15存放作为读出的块0的数据,下标16~31存放作为读出的块1的数据,下标32~47存放作为读出的块2的数据
unsigned char status; //返回
unsigned char piccdata[16]; //卡数据缓冲
//以下控制字含义:读块0、块1、块2,仅读指定序列号的卡,需要每次指定密码
if (ui->radioButton->isChecked()){
ctrlword = BLOCK0_EN + BLOCK1_EN + BLOCK2_EN + EXTERNKEY; //外部密码
}else{
ctrlword = BLOCK0_EN + BLOCK1_EN + BLOCK2_EN; //内部密码
}
area = ui->comboBox->currentIndex(); //操作扇区号
keyA1B0 = ui->comboBox_2->currentIndex(); //密码认证类型,;大于0用A密码 ,等于0用B密码
QString Key_str = ui->textEdit_oldkey->toPlainText().trimmed();
if(Key_str.length()==12 and checkinput(Key_str)){
for(int i=0;i<6;i++){
bool ok;
picckey[i]=QString(Key_str.mid(i*2,2)).toInt(&ok,16);
}
status = mypiccreadex(ctrlword,serial,area,keyA1B0,picckey,piccdata0_2); //读取选定扇区的0、1、2块
if(status == 0){
unsigned int card10=serial[0]*256*256*256+serial[1]*256*256+serial[2]*256+serial[3]; //8H10D正码
QString cardstr=QString::asprintf("%010d",card10);
QString CardnoHex="";
for(int i=0;i<4;i++){
CardnoHex=CardnoHex+QString::asprintf("%02X", serial[i]);
}
QString blockdata="";
for(int i=0;i<16;i++){
blockdata=blockdata+QString::asprintf("%02X ", piccdata0_2[i]);
}
ui->textEdit_block0->setText(blockdata);
blockdata="";
for(int i=16;i<32;i++){
blockdata=blockdata+QString::asprintf("%02X ", piccdata0_2[i]);
}
ui->textEdit_block1->setText(blockdata);
blockdata="";
for(int i=32;i<48;i++){
blockdata=blockdata+QString::asprintf("%02X ", piccdata0_2[i]);
}
ui->textEdit_block2->setText(blockdata);
status = mypiccread(area * 4 + 3,piccdata); //读取选定扇区的第3块 A密码、控制位、B密码,无法读取的信息返回 00
if(status == 0){
blockdata="";
for(int i=0;i<16;i++){
blockdata=blockdata+QString::asprintf("%02X ", piccdata[i]);
}
ui->textEdit_newkey->setText(blockdata);
mypcdbeep(30);
ui->listWidget->addItem("读取扇区数据成功,16进制卡号:"+CardnoHex+",转10进制卡号:"+cardstr);
}else{
ui->textEdit_newkey->clear();
disperrinf(status);
}
}else{
ui->textEdit_block0->clear();
ui->textEdit_block1->clear();
ui->textEdit_block2->clear();
ui->textEdit_newkey->clear();
disperrinf(status);
}
}else{
QMessageBox::critical(NULL, "提示","请输入12位16进制卡片认证密码!");
}
}
void MainWindow::on_pushButton_piccwriteex_clicked()
{
if(!checkdllos()){return;}
unsigned char ctrlword; //控制字
unsigned char serial[4]; //可写数组
unsigned char area; //操作扇区区号
unsigned char keyA1B0; //AB密码认证
unsigned char picckey[6]; //存放卡密码的数组
unsigned char piccdata0_2[48]; //下标0~15存放作为读出的块0的数据,下标16~31存放作为读出的块1的数据,下标32~47存放作为读出的块2的数据
unsigned char status; //返回
char s;
//以下控制字含义:读块0、块1、块2,仅读指定序列号的卡,需要每次指定密码
if (ui->radioButton->isChecked()){
ctrlword = BLOCK0_EN + BLOCK1_EN + BLOCK2_EN + EXTERNKEY; //外部密码
}else{
ctrlword = BLOCK0_EN + BLOCK1_EN + BLOCK2_EN; //内部密码
}
area = ui->comboBox->currentIndex(); //操作扇区号
keyA1B0 = ui->comboBox_2->currentIndex(); //密码认证类型,;大于0用A密码 ,等于0用B密码
QString Key_str = ui->textEdit_oldkey->toPlainText().trimmed();
if(Key_str.length()==12 and checkinput(Key_str)){
for(int i=0;i<6;i++){
bool ok;
picckey[i]=QString(Key_str.mid(i*2,2)).toInt(&ok,16);
}
}else{
QMessageBox::critical(NULL, "提示","请输入12位16进制卡片认证密码!");
return;
}
//检测写卡数据
QChar ch;
QString writinf = ui->textEdit_block0->toPlainText().trimmed()+ui->textEdit_block1->toPlainText().trimmed()+ui->textEdit_block2->toPlainText().trimmed();
QString writinf1 = "";
int m = 0;
int n = 0;
ch = writinf.at(0);
s = writinf.at(0).toLatin1();
for(int i=0; i<writinf.length() ; i++)
{
ch = writinf.at(i);
s = writinf.at(i).toLatin1();
if((('0' <= s) && (s <= '9')) || (('A' <= s) && (s <= 'F')) || (('a' <= s) && (s <= 'f')))
{
writinf1 += ch;
n++;
if(n==2){
bool ok;
piccdata0_2[m++] = writinf1.toInt(&ok,16);
writinf1 = "";
n = 0;
if(m>=48){
break;
}
}
}
else if(s == ' '){
}
else
{
if(m>=0 && m<16){
QMessageBox::critical(NULL, "提示", "第0块写卡数据错误,请输入正确的16进制数据!");
//ui->textEdit_block0->setExtraSelections((m%16*3,2);
ui->textEdit_block0->setFocus();
}else if(m>=16 && m<32){
QMessageBox::critical(NULL, "提示", "第1块写卡数据错误,请输入正确的16进制数据!");
//ui->textEdit_block1.->setSelection(m%16*3,2);
ui->textEdit_block1->setFocus();
}else if(m>=32 && m<48){
QMessageBox::critical(NULL, "提示", "第2块写卡数据错误,请输入正确的16进制数据!");
//ui->textEdit_block2->setSelection(m%16*3,2);
ui->textEdit_block2->setFocus();
}
return;
}
}
status = mypiccwriteex(ctrlword,serial,area,keyA1B0,picckey,piccdata0_2);
if(status == 0)
{
mypcdbeep(30);
unsigned int card10=serial[0]*256*256*256+serial[1]*256*256+serial[2]*256+serial[3]; //8H10D正码
QString cardstr=QString::asprintf("%010d",card10);
QString CardnoHex="";
for(int i=0;i<4;i++){
CardnoHex=CardnoHex+QString::asprintf("%02X", serial[i]);
}
ui->listWidget->addItem("写数据到扇区成功,16进制卡号:"+CardnoHex+",转10进制卡号:"+cardstr);
}else{
disperrinf(status);
}
}
void MainWindow::on_pushButton_piccchangesinglekey_clicked()
{
if(!checkdllos()){return;}
unsigned char ctrlword; //控制字
unsigned char serial[4]; //可写数组
unsigned char area; //操作扇区号
unsigned char keyA1B0; //AB密码认证方式
unsigned char piccoldkey[6];//存放卡原始密码的数组
unsigned char piccdata[17]; //存放卡新A密码(也就是准备改成的密码)、密码权限访问字、新B密码的数组、指定更改项目的标志
unsigned char status; //返回
//以下控制字含义:读块0、块1、块2,仅读指定序列号的卡,需要每次指定密码
if (ui->radioButton->isChecked()){
ctrlword = BLOCK0_EN + BLOCK1_EN + BLOCK2_EN + EXTERNKEY; //外部密码
}else{
ctrlword = BLOCK0_EN + BLOCK1_EN + BLOCK2_EN; //内部密码
}
area = ui->comboBox->currentIndex(); //操作扇区号
keyA1B0 = ui->comboBox_2->currentIndex(); //密码认证类型,;大于0用A密码 ,等于0用B密码
QString Key_str = ui->textEdit_oldkey->toPlainText().trimmed();
if(Key_str.length()==12 and checkinput(Key_str)){
for(int i=0;i<6;i++){
bool ok;
piccoldkey[i]=QString(Key_str.mid(i*2,2)).toInt(&ok,16);
}
}else{
QMessageBox::critical(NULL, "提示","请输入12位16进制卡片认证密码!");
return;
}
QChar ch;
QString writinf = ui->textEdit_newkey->toPlainText().trimmed();
QString writinf4 = "";
int m = 0;
int n = 0;
char s;
for(int i=0; i<writinf.length() ; i++)
{
ch = writinf.at(i);
s = writinf.at(i).toLatin1();
if((('0' <= s) && (s <= '9')) || (('A' <= s) && (s <= 'F')) || (('a' <= s) && (s <= 'f')))
{
writinf4 += ch;
n++;
if(n==2){
bool ok;
piccdata[m++] = writinf4.toInt(&ok,16);
writinf4 = "";
n = 0;
if(m>=16){
break;
}
}
}
else if(s == ' ') {
}
else
{
QMessageBox::critical(NULL, "提示", "新A、B密码及控制位输入错误,请输入正确的16进制数据!");
//ui->textEdit_newkey->setSelection(i,1);
ui->textEdit_newkey->setFocus();
return;
}
}
if(m<16)
{
QMessageBox::critical(NULL, "提示", "新A、B密码及控制位输入错误,请输入正确的16进制数据!");
ui->textEdit_newkey->setFocus();
return;
}
piccdata[16]=ui->comboBox_3->currentIndex(); //取值0表示只改A密码,2表示改A、B密码,3表示修改A、B及控制位
if(piccdata[16]>0){piccdata[16]=piccdata[16]+1;}
int answ=QMessageBox::question (this, "警告", "你确定修改密码控制块的数据吗 ?此数据块如果改写错误,数据卡将会被限制!", QMessageBox::Ok, QMessageBox::Cancel);
if (answ ==1024){
status = mypiccchangesinglekeyex(ctrlword,serial,area,keyA1B0,piccoldkey,piccdata);
if(status == 0){
mypcdbeep(30);
unsigned int card10=serial[0]*256*256*256+serial[1]*256*256+serial[2]*256+serial[3]; //8H10D正码
QString cardstr=QString::asprintf("%010d",card10);
QString CardnoHex="";
for(int i=0;i<4;i++){
CardnoHex=CardnoHex+QString::asprintf("%02X", serial[i]);
}
ui->listWidget->addItem("修改扇区密码成功,16进制卡号:"+CardnoHex+",转10进制卡号:"+cardstr);
}else {
disperrinf(status);
}
}
}
void MainWindow::on_pushButton_piccread_clicked()
{
if(!checkdllos()){return;}
unsigned char serial[4]; //可写数组
unsigned char area; //操作扇区号
unsigned char keyA1B0; //AB密码认证方式
unsigned char piccoldkey[6];//存放卡原始密码的数组
unsigned char piccdata[16]; //存放块数据
unsigned char status; //返回
int myblock=ui->spinBox->value();
area=myblock/4;
QString Key_str = ui->textEdit_oldkey->toPlainText().trimmed();
if(Key_str.length()==12 and checkinput(Key_str)){
for(int i=0;i<6;i++){
bool ok;
piccoldkey[i]=QString(Key_str.mid(i*2,2)).toInt(&ok,16);
}
}else{
QMessageBox::critical(NULL, "提示","请输入12位16进制卡片认证密码!");
return;
}
status = mypiccrequest(serial); //寻卡获取到卡号
if(status == 0){
unsigned int card10=serial[0]*256*256*256+serial[1]*256*256+serial[2]*256+serial[3]; //8H10D正码
QString cardstr=QString::asprintf("%010d",card10);
QString CardnoHex="";
for(int i=0;i<4;i++){
CardnoHex=CardnoHex+QString::asprintf("%02X", serial[i]);
}
status = mypiccauthkey1(serial,area,keyA1B0,piccoldkey);
if(status == 0){
status = mypiccread(myblock,piccdata);
if(status == 0){
mypcdbeep(30);
QString blockdata="";
for(int i=0;i<16;i++){
blockdata=blockdata+QString::asprintf("%02X ", piccdata[i]);
oldblock[i]=piccdata[i]; //保存读取的块数据,用于复制uid
}
ui->textEdit_thisblock->setText(blockdata);
ui->listWidget->addItem("读取块内数据成功,16进制卡号:"+CardnoHex+",转10进制卡号:"+cardstr);
}else{disperrinf(status);}
}else{disperrinf(status);}
}else{disperrinf(status);}
}
void MainWindow::on_pushButton_piccwrite_clicked()
{
if(!checkdllos()){return;}
unsigned char serial[4]; //可写数组
unsigned char area; //操作扇区号
unsigned char keyA1B0; //AB密码认证方式
unsigned char piccoldkey[6];//存放卡原始密码的数组
unsigned char piccdata[16]; //存放块数据
unsigned char status; //返回
int myblock=ui->spinBox->value();
area=myblock/4;
QString Key_str = ui->textEdit_oldkey->toPlainText().trimmed();
if(Key_str.length()==12 and checkinput(Key_str)){
for(int i=0;i<6;i++){
bool ok;
piccoldkey[i]=QString(Key_str.mid(i*2,2)).toInt(&ok,16);
}
}else{
QMessageBox::critical(NULL, "提示","请输入12位16进制卡片认证密码!");
return;
}
QChar ch;
QString writinf = ui->textEdit_thisblock->toPlainText().trimmed();
QString writinf4 = "";
int m = 0;
int n = 0;
char s;
for(int i=0; i<writinf.length() ; i++)
{
ch = writinf.at(i);
s = writinf.at(i).toLatin1();
if((('0' <= s) && (s <= '9')) || (('A' <= s) && (s <= 'F')) || (('a' <= s) && (s <= 'f')))
{
writinf4 += ch;
n++;
if(n==2){
bool ok;
piccdata[m++] = writinf4.toInt(&ok,16);
writinf4 = "";
n = 0;
if(m>=16){
break;
}
}
}
else if(s == ' ') {
}
else
{
QMessageBox::critical(NULL, "提示", "写块数据输入错误,请输入正确的16进制数据!");
//ui->textEdit_thisblock->setSelection(i,1);
ui->textEdit_thisblock->setFocus();
return;
}
}
if(m<16)
{
QMessageBox::critical(NULL, "提示", "写块数据输入错误,请输入正确的16进制数据!");
ui->textEdit_thisblock->setFocus();
return;
}
status = mypiccrequest(serial); //寻卡获取到卡号
if(status == 0){
unsigned int card10=serial[0]*256*256*256+serial[1]*256*256+serial[2]*256+serial[3]; //8H10D正码
QString cardstr=QString::asprintf("%010d",card10);
QString CardnoHex="";
for(int i=0;i<4;i++){
CardnoHex=CardnoHex+QString::asprintf("%02X", serial[i]);
}
status = mypiccauthkey1(serial,area,keyA1B0,piccoldkey);
if(status == 0){
status = mypiccwrite(myblock,piccdata);
if(status == 0){
mypcdbeep(30);
ui->listWidget->addItem("写数据到块内成功,16进制卡号:"+CardnoHex+",转10进制卡号:"+cardstr);
}else{disperrinf(status);}
}else{disperrinf(status);}
}else{disperrinf(status);}
}
void MainWindow::on_pushButton_piccwriteserial_clicked()
{
if(!checkdllos()){return;}
unsigned char serial[4]; //可写数组
unsigned char area; //操作扇区号
unsigned char keyA1B0; //AB密码认证方式
unsigned char piccoldkey[6];//存放卡原始密码的数组
unsigned char piccdata[16]; //存放块数据
unsigned char status; //返回
unsigned char ctrlword = BLOCK0_EN ; //读写控制字
keyA1B0 = ui->comboBox_2->currentIndex(); //密码认证类型,;大于0用A密码 ,等于0用B密码
QString Key_str = ui->textEdit_oldkey->toPlainText().trimmed();
if(Key_str.length()==12 and checkinput(Key_str)){
for(int i=0;i<6;i++){
bool ok;
piccoldkey[i]=QString(Key_str.mid(i*2,2)).toInt(&ok,16);
}
}else{
QMessageBox::critical(NULL, "提示","请输入12位16进制卡片认证密码!");
return;
}
bool ok;
unsigned int Cardno=ui->textEdit_uidno->toPlainText().toInt(&ok);
if(ok){
if(Cardno>4294967295){
QMessageBox::critical(NULL, "提示", "UID号不可以>4294967295");
return;
}
QString Cardnohex=("00000000"+DecimalToHex(Cardno)).right(8);
unsigned char crc=0;
for(int i=0;i<4;i++){
bool ok;
piccdata[i]=QString(Cardnohex.mid(i*2,2)).toInt(&ok,16);
crc=crc ^piccdata[i];
}
piccdata[4]=crc; //第4字节是校验位
for(int i=5;i<16;i++){
piccdata[i]=oldblock[i];
}
status = mypiccwriteserial(ctrlword,serial,keyA1B0,piccoldkey,piccdata);
if(status == 0){
mypcdbeep(30);
ui->listWidget->addItem("UID卡号写入成功!");
}else{disperrinf(status);}
}else{
QMessageBox::critical(NULL, "提示", "请输入10进制的UID号!");
return;
}
}