📄 yxtf.c
字号:
/*
本代码仅作为学习研究之目的使用,请您于24小时内自觉将其删除,请勿应用于商业活动或其它赢利性活动中,
否则后果自负!
*/
/******************************************************
* 文件名:yxtf.c
* 功 能:处理TCA命令
* 作 者:
* 日 期:
*****************************************************/
#include "yxtf.h"
Yxtf_Info_t* pstYxtfInfo = NULL;
static Smart_ErrorCode_t yxtf_transfer(Smart_Handle_t Handle,
U8* ins,
U16 NumberToWrite,
U8* Response,
U16* Read,
U8* Status);//数据传输
static bool yxtf_readdata(Smart_Handle_t Handle,U8 len,U8 *outbuf);
static bool yxtf_begincmd(Smart_Handle_t Handle);
static bool yxtf_get_sn(Smart_Handle_t Handle);//读取智能卡号码
static bool yxtf_get_prov(Smart_Handle_t Handle);//获取运营商信息
static bool yxtf_check_pairing(Smart_Handle_t Handle);//检查机卡配对
/************************************************************************/
/* 初始化, 主要工作是读取卡内的基本信息,如卡号、运营商等信息
输入 handle -- smart card 句柄
输出 无
返回值 true -- 初始化成功 false -- 初始化失败
其他 */
/************************************************************************/
bool yxtf_init(Smart_Handle_t handle)
{
pstYxtfInfo = &yxtf;
memset(pstYxtfInfo,0,sizeof(Yxtf_Info_t));
if(!yxtf_begincmd(handle))
{
// return false;
}
#if 0
if(!yxtf_get_prov(handle))
{
printf("yxtf init : get prog info failed !!\n");
return false;
}
#endif
if(!yxtf_get_sn(handle))
{
printf("yxtf init : get sn failed !!\n");
// return false;
}
if(!yxtf_check_pairing(handle))
{
printf("yxtf init : get sn failed !!\n");
// return false;
}
printf("yxtf Init OK !!\n");
return true;
}
/************************************************************************/
/* 起始指令, 这个命令在智能卡 Reset 后必须首先执行,之后才可以执行其他的命令
输入 Handle -- smart card 句柄
输出 无
返回值 true -- 命令执行成功 false -- 命令执行失败
其他
通讯示例:
00 A4 04 00 05 A4 F9 5A 54 00 06
90 00
*/
/************************************************************************/
static bool yxtf_begincmd(Smart_Handle_t Handle)
{
U8 cmd[]={0x00,0xa4,0x04,0x00,0x05,0xf9,0x5a,0x54,0x00,0x06};
U8 response[10];
U8 pbword[2]={0};
U16 cmdlen=0;
U16 replen=0;
Smart_ErrorCode_t bresult=SMC_NO_ERROR;
cmdlen=10;
bresult=yxtf_transfer(Handle,cmd,cmdlen,response,&replen,pbword);
// if(bresult!=SMC_NO_ERROR)
// {
// return false;
// }
if((pbword[0]!=0x90)||(pbword[1]!=0x00))
{
return false;
}
return true;
}
/************************************************************************/
/* 读取运营商ID列表
输入 Handle -- smart card 句柄
输出 无
返回值 true -- 获取运营商信息成功 false -- 获取运营商信息失败
其他 得到的运营商信息存储于全局变量pstYxtfInfo中,可用于OSD显示
通讯示例:
80 44 00 00 08 44
xx xx 00 00 xx xx 00 00 90 00 //每两个字节就是一个运营商的ID? */
/************************************************************************/
static bool yxtf_get_prov(Smart_Handle_t Handle)
{
U8 cmd[5]={0x80,0x44,0x00,0x00,0x08};
U8 response[10];
U8 pbword[2]={0};
int cmdlen=0;
U16 replen=0;
Smart_ErrorCode_t bresult=SMC_NO_ERROR;
int provcount=0;
int i;
cmdlen = 5+cmd[4];
bresult = yxtf_transfer(Handle,cmd,cmdlen,response,&replen,pbword);
// if(bresult!=SMC_NO_ERROR)
// {
// return false;
// }
/*首先检查过程字节是否正确*/
if((pbword[0]!=0x90)||(pbword[1]!=0x00))
{
return false;
}
for(i=0;i<MAX_PROV_COUNT;i++)//好像是最多支持4个
{
if((response[i*2]!=0)||(response[i*2+1]!=0))
{
provcount++;
pstYxtfInfo->provID[i]=(response[i*2]<<8)|response[i*2+1];
printf("the provid[%d] =0x%04x\n",i,pstYxtfInfo->provID[i]);
}
}
}
/************************************************************************/
/* 读取智能卡号,就是tf卡片上显示的第三组数字,tf也拿来用做授权寻址
输入 Handle -- smart card 句柄
输出 无
返回值 true -- 获取卡号成功 false -- 获取卡号失败
其他 得到的卡号存储于全局变量pstYxtfInfo中,可用于OSD显示
通讯示例:
80 46 00 00 04 46 01 00 00 04
61 04
00 C0 00 00 04 C0
xx xx xx xx 90 00 //卡号 xx xx xx xx (十六进制) */
/************************************************************************/
bool yxtf_get_sn(Smart_Handle_t Handle)
{
U8 cmd[]={0x80,0x46,0x00,0x00,0x04,0x01,0x00,0x00,0x04};
U8 response[100];
U8 pbword[2]={0};
U16 cmdlen=0;
U16 replen=0;
Smart_ErrorCode_t bresult=SMC_NO_ERROR;
U8 nextreadsize=0;
cmdlen = 5+cmd[4];
bresult=yxtf_transfer(Handle,cmd,cmdlen,response,&replen,pbword);
// if(bresult!=SMC_NO_ERROR)
// {
// return false;
// }
if((pbword[0]&0xf0)!=0x60)
{
return false;
}
nextreadsize=pbword[1];
if(yxtf_readdata(Handle,nextreadsize,response)!=true)
{
return false;
}
pstYxtfInfo->uCardNumber=(response[0]<<24)+(response[1]<<16)\
+(response[2]<<8)+response[3];//卡号,卡片上显示的第三组数字,也是授权用的号码
return true;
}
/************************************************************************/
/* 检查机卡配对
输入 Handle -- smart card 句柄
输出 无
返回值 true -- 检查机卡配对成功 false -- 检查机卡配对失败
其他 得到的机卡配对状态存储于全局变量pstYxtfInfo中,可用于OSD显示
通讯示例:
80 4C 00 00 04 4C FF FF FF FF
94 B1 -- 该卡没有和任何机顶盒绑定
或者
94 B2 -- 该卡已经和机顶盒绑定(不一定是当前机顶盒哦!) */
/************************************************************************/
static bool yxtf_check_pairing(Smart_Handle_t Handle)
{
U8 cmd1[200]= {0x80,0x4c,0x00,0x00,0x04,0xFF,0xFF,0xFF,0xFF};
U8 reponse[100];
U16 writelen = 0;
U16 replen=0;
U8 status[2];
int i = 0;
writelen = cmd1[4]+5;
yxtf_transfer(Handle,cmd1,writelen,reponse,&replen,status);
if ((status[0] == 0x94)&&(status[1] == 0xB1) )
{
printf("该卡没有和任何机顶盒绑定!\n");
pstYxtfInfo->paringflag = 0;
return true;
}
else if ((status[0] == 0x94)&&(status[1] == 0xB2) )
{
pstYxtfInfo->paringflag = 1;
printf("该卡已经和机顶盒绑定!\n");
return true;
}
else
{
pstYxtfInfo->paringflag = 2;
return false;
}
}
/************************************************************************/
/* 机卡配对,一般情况没必要用的,在有些地方,tf在ECM中设置了要求智能卡配对
才能解出cw,这个时候想办法得到配对信息,执行下面这个命令,就可以完成智能卡和
你的机顶盒配对了。那些以为机卡配对了就无法共享的想法应该是天真的,至少对tf
来说是这样。
输入 Handle -- smart card 句柄 pairingcode -- 4字节的配对信息,卡和
对应的机器通讯过程中有,对应的机器flash中也存有一个,紧挨着卡号的信息
输出 无
返回值 true -- 机卡配对成功 false -- 机卡配对失败
其他
80 4C 00 00 04 4C xx xx xx xx
90 00 //当前机卡配对
或者
94 B2(?) //没仔细研究具体是什么,卡和其它机顶盒绑定 */
/************************************************************************/
bool yxtf_pairing(Smart_Handle_t Handle, U8* pairingcode)// pairingcode 4字节的配对信息,
{
U8 cmd1[200]= {0x80,0x4c,0x00,0x00,0x04,0xFF,0xFF,0xFF,0xFF};
U8 reponse[100];
U16 writelen = 0;
U16 replen=0;
U8 status[2];
int i = 0;
memcpy(cmd1+5, pairingcode, 4);
writelen = cmd1[4]+5;
yxtf_transfer(Handle,cmd1,writelen,reponse,&replen,status);
if((status[0]==0x90)||(status[1]==0x00))
{
printf("当前机卡绑定!\n");
}
else
{
// printf("************Status[0]=%02x Status[1]=%02x*********\n",status[0],status[1]);
printf("该卡已绑定其它机顶盒!\n");
return false;
}
return true;
}
/************************************************************************/
/* 处理解析ECM,得到CW,呵呵,得到它我们就可以看节目了!收取ECM的时候设置filter
的第一个字节0x80/0x81就ok了
输入 Handle -- smart card 句柄 buf -- ECM信息,从0x80/0x81开始
输出 pucCW -- 就是cw啦,16个字节,不是奇偶,就是奇偶,根据情况你自己试验
返回值 true -- 解析ECM成功 false --解析ECM失败
其他
*/
/************************************************************************/
bool yxtf_parse_ecm(Smart_Handle_t Handle,U8* buf,U8* pucCW)
{
U8 cmd1[200]={0x80,0x3a,0x00,0x01,0x53};
U8 cmd2[10]={0x00,0xc0,0x00,0x00};
U8 reponse[100];
U16 writelen = 0;
U16 replen=0;
U8 status[2];
U8* pbuf = buf;
int i = 0;
for (i=0; i<(buf[2]+3); i++)//找到真正要往卡里送的数据
{
if ((pbuf[0]==0x80)&&(pbuf[1]==0x3a))
{
break;
}
else
{
pbuf = buf+i+1;
}
}
writelen = pbuf[4]+5;
// printf("ecm write len = %d\n", writelen);
memcpy(cmd1,pbuf,writelen);
yxtf_transfer(Handle,cmd1,writelen,reponse,&replen,status);
if (replen >= 2)
{
cmd2[4] = reponse[1];
}
else
{
if((status[0]&0xf0)==0x60)
{
cmd2[4] = status[1];
}
else
{
return false;
}
}
yxtf_transfer(Handle,cmd2,5,reponse,&replen,status);
//printf("rsp len = %d\n", replen);
if (replen > 23)
{//很怀疑tf的做法,但是他们就是这么做的,很明显没有加密啊,hoho~ ~
if(buf[0]==0x80)
memcpy(pucCW, reponse+8,16);
else
{
memcpy(pucCW, reponse+16,8);
memcpy(pucCW+8,reponse+8,8);
}
}
else
{
return false;
}
return true;
}
/************************************************************************/
/* 处理EMM,主要就是完成对卡授权了。收取EMM的时候设置filter的第一个字节0x82,
5,6,7,8个字节就是卡号了。可以仅设置第一个字节,多收几个EMM研究研究哦!
输入 Handle -- smart card 句柄 data -- EMM信息,len -- 数据长度
输出 无
返回值 true -- 解析EMM成功 false --解析EMM失败
其他 */
/************************************************************************/
bool yxtf_parse_emm(Smart_Handle_t Handle,U8* data,U16 len)
{
U8 cmd1[100]={0};
U8 cmd2[10]={0x00,0xc0,0x00,0x00};
U8 reponse[100];
U16 writelen = 0;
U16 replen=0;
U8 status[2];
writelen = data[15]+5;
memcpy(cmd1,data+11,writelen);//找到真正要往卡里送的数据
yxtf_transfer(Handle,cmd1,writelen,reponse,&replen,status);
if (replen > 2)
{
return true;
}else
{
return false;
}
return true;
}
/************************************************************************/
/* 数据传输,机顶盒和智能卡通讯的接口
输入 Handle -- smart card 句柄,ins -- 要传送的数据,NumberToWrite --
要传送的数据长度
输出 Response -- 回应数据, Read -- 回应的数据长度,Status -- 状态字节
返回值 数据传输错误类型 SMC_NO_ERROR表示无错误
其他
*/
/************************************************************************/
static Smart_ErrorCode_t yxtf_transfer(Smart_Handle_t Handle,
U8* ins,
U16 NumberToWrite,
U8* Response,
U16* Read,
U8* Status)
{
Smart_ErrorCode_t error = SMC_NO_ERROR;
error = Smart_Transfer(Handle,ins,NumberToWrite,Response,0,Read,Status);
// printf("Status[0]=0x%02x Status[1]=0x%02x error = %d\n",Status[0],Status[1],error);
return error;
}
/************************************************************************/
/*从卡中读取指定长度的数据
输入 Handle -- smart card 句柄,len -- 要从智能卡中读取的数据长度
输出 outbuf -- 智能卡回应的数据
返回值 true -- 读取数据成功 false -- 读取数据失败
其他 */
/************************************************************************/
static bool yxtf_readdata(Smart_Handle_t Handle,U8 len,U8 *outbuf)
{
U8 cmd[]={0x00,0xc0,0x00,0x00,0xff};
U8 reponse[255];
U16 cmdlen=5;
U16 replen=0;
U8 pbword[2]={0};
Smart_ErrorCode_t bresult=SMC_NO_ERROR;
memset(reponse,0,255);
cmd[4] = len;
bresult=yxtf_transfer(Handle,cmd,cmdlen,reponse,&replen,pbword);
// if(bresult!=SMC_NO_ERROR)
// {
// return false;
// }
if((pbword[0]==0x90)&&(pbword[1]==0x00)&&(replen==len))
{
memcpy(outbuf,reponse,replen);
return true;
}
else
{
return false;
}
}
///////////---The end---------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -