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

📄 smsx.c

📁 在原来基础上新添加了对ST、V、I、C卡的处理
💻 C
字号:

/*
本代码仅作为学习研究的目的使用,请您于24小时内自觉将其删除,请勿应用于商业活动或其它赢利性活动中,
否则后果自负!
*/

/******************************************************
 * 文件名:smsx.c
 * 功  能:处理SCA命令
 * 作  者:
 * 日  期:
 *****************************************************/

#include "smsx.h"

Smsx_Info_t* pstSmsxInfo;

static Smart_ErrorCode_t smsx_transfer(
								   Smart_Handle_t Handle,
								   U8*			  ins,
								   U16			  NumberToWrite,
								   U8*			  Response,
								   U16*			  Read,
								   U8*            Status);//数据传输
bool smsx_readdata(Smart_Handle_t Handle,U8 len,U8 *outbuf);
static bool smsx_begincmd(Smart_Handle_t Handle);
static bool smsx_get_sn(Smart_Handle_t Handle);//读取智能卡号码

/************************************************************************/
/* 初始化, 主要工作是读取卡内的基本信息,如卡号、运营商等信息
   
   输入     handle -- smart card 句柄
   输出     无
   返回值   true -- 初始化成功 false -- 初始化失败
   其他                                                                 */
/************************************************************************/
bool smsx_init(Smart_Handle_t handle)
{
	pstSmsxInfo = &smsx;
	memset(pstSmsxInfo,0,sizeof(Smsx_Info_t));

	if(!smsx_begincmd(handle))
	{
		printf("smsx init : begin cmd failed !!\n");
//		return false;
	}

	if(!smsx_get_sn(handle))
	{
		printf("smsx init : get sn failed !!\n");
//		return false;
	}

	printf("SMSX Init OK !!\n");

	return true;
}


/************************************************************************/
/* 起始指令,  这个命令在智能卡 Reset 后必须首先执行,之后才可以执行其他的命令 

   输入     Handle -- smart card 句柄
   输出     无
   返回值   true -- 命令执行成功 false -- 命令执行失败
   其他                                    

通讯示例:

00 A4 04 00 02 A4 3F 00 
90 00 
00 A4 04 00 02 A4 4A 00 
90 00 
                                                                       */
/************************************************************************/
static bool smsx_begincmd(Smart_Handle_t Handle)
{
	U8	cmd[16]={0x00,0xa4,0x04,0x00,0x02,0x3F,0x00};
	U8	response[10];
	U8	pbword[2]={0};
	U16	cmdlen=0;
	U16	replen=0;
	Smart_ErrorCode_t bresult=SMC_NO_ERROR;
	
	cmd[5] = 0x3F;
	cmd[6] = 0x00;
	cmdlen=cmd[4]+5;
	bresult=smsx_transfer(Handle,cmd,cmdlen,response,&replen,pbword);

//	if(bresult!=SMC_NO_ERROR)
//	{
//		return false;
//	}

	if((pbword[0]!=0x90)||(pbword[1]!=0x00))
	{
		return false;
	}


	cmd[5] = 0x4A;
	cmd[6] = 0x00;
	cmdlen=cmd[4]+5;
    bresult=smsx_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,卡号是授权需要用到的,ID就是卡片上显示的一串数字了

   输入     Handle -- smart card 句柄
   输出     无
   返回值   true -- 获取卡号成功 false -- 获取卡号失败
   其他     得到的卡号存储于全局变量pstYxtfInfo中,可用于OSD显示                               

通讯示例:


00 B2 00 05 06 B2 00 01 FF 00 01 FF 
61 67 
00 C0 00 00 67 C0 
00 00 00 xx xx xx xx yy yy yy yy yy yy yy yy 00 //卡号 xx xx xx xx (十六进制) ID yy yy yy yy yy yy yy yy(字符串) 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 90 00                        */
/************************************************************************/
bool smsx_get_sn(Smart_Handle_t Handle)
{
	U8	cmd[]={0x00,0xB2,0x00,0x05,0x06,0x00,0x01,0xFF,0x00,0x01,0xFF};
	U8	response[200];
	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=smsx_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(smsx_readdata(Handle,nextreadsize,response)!=true)
	{
		return false;
	}

	memcpy(pstSmsxInfo->uCardUA, response+7, 8);//卡片上显示的一串号码
    pstSmsxInfo->uCardNumber=(response[3]<<24)+(response[4]<<16)+(response[5]<<8)+response[6];//这才是授权用的号码!
	return true;
}

/************************************************************************/
/* 处理解析ECM,得到CW,呵呵,得到它我们就可以看节目了!收取ECM的时候设置filter
的第一个字节0x80/0x81就ok了

   输入     Handle -- smart card 句柄  buf -- ECM信息,从0x80/0x81开始
   输出     pucCW  -- 就是cw啦,16个字节,不是奇偶,就是奇偶,根据情况你自己试验
   返回值   true -- 解析ECM成功 false --解析ECM失败
   其他       
                                                                        */
/************************************************************************/

bool smsx_parse_ecm(Smart_Handle_t Handle,U8* buf,U8* pucCW)
{
	U8  cmd1[200]={0x80,0x32,0x00,0x00,0x3C};
	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;

	writelen = pbuf[2]+3+5;
//	printf("ecm write len = %d\n", writelen);
	cmd1[4] = pbuf[2]+3;
	memcpy(cmd1+5,pbuf,writelen-5);//要对ECM数据加个命令头再传给智能卡
	smsx_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;
		}		
	}


	pbuf = reponse;
	if (replen > 18)
	{
		for (i=0; i<replen; i++)
		{
			if ((pbuf[0]==0x83)&&(pbuf[1]==0x16))
			{
				break;
			}
			else
			{
				pbuf = reponse+i+1;
			}
		}

		if (i >= replen)
		{
		    return false;
		}

		if(buf[0]==0x80)//这个地方很有意思,如果不这样处理一下,一个字节之差,节目可能也放不出来
		{
			memcpy(pucCW, pbuf+6,4);
			memcpy(pucCW+4, pbuf+6+4+1,4);
			memcpy(pucCW+8, pbuf+6+8+1,4);
			memcpy(pucCW+12, pbuf+6+8+1+4+1,4);
		}
		else
		{
			memcpy(pucCW, pbuf+6+8+1,4);
			memcpy(pucCW+4, pbuf+6+8+1+4+1,4);
	 		memcpy(pucCW+8, pbuf+6,4);
			memcpy(pucCW+12, pbuf+6+4+1,4);
		}
	}
	return true;
}

/************************************************************************/
/* 处理EMM,主要就是完成对卡授权了。收取EMM的时候设置filter的第一个字节0x82,
5,6,7,8个字节就是卡号了,注意不是ID啊。可以仅设置第一个字节,多收几个EMM
研究研究哦! 

   输入     Handle -- smart card 句柄  data -- EMM信息,len -- 数据长度
   输出     无
   返回值   true -- 解析EMM成功 false --解析EMM失败
   其他                                                                   */
/************************************************************************/

bool smsx_parse_emm(Smart_Handle_t Handle,U8* buf,U16 len)
{
	U8  cmd1[100]={0x80,0x30,0x00,0x00,0x4C};
	U8  cmd2[10]={0x00,0xc0,0x00,0x00};
	U8	reponse[100];
	U16 writelen = 0;
	U16	replen=0;
	U8  status[2];

	writelen = buf[2]+3+5;
	cmd1[4] = buf[2]+3;
	memcpy(cmd1+5,buf,writelen-5);//要对EMM数据加个命令头再传给智能卡
	smsx_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 smsx_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 -- 读取数据失败
   其他                                                                 */
/************************************************************************/
bool smsx_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=smsx_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 + -