⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 yxtf.c

📁 在原来基础上新添加了对ST、V、I、C卡的处理
💻 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 + -