📄 mcucom.c
字号:
/* 包类型常数 */
const byte PACK_TYPE_CHECK = 0x01; /* 卡检测 */
const byte PACK_TYPE_INI = 0x02; /* 卡初始化 */
const byte PACK_TYPE_EMM = 0x03; /* EMM数据 */
const byte PACK_TYPE_ECM = 0x04; /* ECM数据 */
/* 错误码 */
const byte ERR_OK = 0x00;
const byte ERR_INVALID_ADDRESS = 0x01;
const byte ERR_CRC =0x02;
const byte ERR_NOT_INI = 0x03;
const byte ERR_INVALID_TYPE = 0x04;
const byte ERR_ECM = 0x05;
const byte ERR_UNKNOWN = 0x06;
const byte ERR_COMM = 128;
/* STB实现的函数 */
/* 串口初始化 */
extern void ini_comm(byte port);
/* 从串口读取数据,port为端口号, in为数据缓冲区,length为需要读取的长度, timeout为超时,单位ms ,返回值为读取的字节数*/
extern int read_comm(byte port, byte *in, byte length, int timeout);
/* 向串口写数据,port为端口号, out为数据缓冲区,length为需要数据长度*/
extern void write_comm(byte port, byte *out, byte length);
/* 过滤EMM数据,out 为数据缓存, 如果成功返回EMM的字节数,否则返回0*/
extern int get_emm(byte *out);
/* 过滤ECM数据,out 为数据缓存, 如果成功返回EMM的字节数,否则返回0*/
extern int get_ecm(byte *out);
/* 延时函数,单位为ms */
extern void delay(int ms);
static const unsigned short crc16tab[] = /* CRC lookup table */
{
0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040
};
unsigned short crc16ccitt(byte *pBuffer, unsigned long uBufSize)
{
unsigned short uCcitt16 = 0xFFFF;
unsigned long i = 0;
for(i = 0; i < uBufSize; i++)
{
uCcitt16 = (uCcitt16 >> 8) | (uCcitt16 << 8);
uCcitt16 ^= pBuffer[i];
uCcitt16 ^= (uCcitt16 & 0xFF) >> 4;
uCcitt16 ^= (uCcitt16 << 8) << 4;
uCcitt16 ^= ((uCcitt16 & 0xFF) << 4) << 1;
}
return ~uCcitt16;
}
/* 数据打包函数 ,输入包类型pkg_type, 数据指针data, 及数据长度*/
/* out指向的地址应分配足够的空间 */
byte pack_data(byte pkg_type, byte *data, byte data_len, byte *out)
{
out[0] = 0x68;
out[1] = data_len + 5;
out[2] = pkg_type;
int i;
for(i = 0; i < data_len; ++i){
out[i + 3] = data[i];
}
unsigned short crc = crc16ccitt(out, out[1] - 2);
out[out[1] - 2] = (byte)(crc >> 8);
out[out[1] - 1] = (byte)(crc & 0xff);
return data_len + 5;
}
/* 智能卡初始化 */
byte smartcard_ini(byte port_pc, byte port_card, const char *stb_sn, byte stb_sn_len)
{
ini_comm(port_pc);
ini_comm(port_card);
byte in[128];
byte out[128];
char *ini_command = "SMARTCARDINI";
char *ini_reply_pc = "CARDREADY";
char *ini_ok = "CARDINIOK";
char *ini_error = "CARDINIERROR";
const byte ini_pkg_len = 28;/* 卡初始化数据长度为28 */
const byte ini_reply_card = 6; /* 初始化应答包长度 */
/* 循环等待 */
while(TRUE){
/* 读取卡初始化命令"SMARTCARDINI" ,超时100ms,应该根据实验调节*/
byte byte_read = read_comm(port_pc, in, strlen(ini_command), 100);
if(byte_read == 0)continue; /* 未收到数据 */
if(byte_read != (byte)strlen(ini_command))return ERR_COMM; /* 通讯错误 */
in[strlen(ini_command)] = 0;
if(strcmp(in, ini_command) != 0)return ERR_COMM;
memcpy(out, ini_reply_pc, strlen(ini_reply_pc));
out[strlen(ini_reply_pc)] = stb_sn_len +2;
memcpy(&out[strlen(ini_reply_pc) + 1], stb_sn, stb_sn_len);
unsigned short crc = crc16ccitt((byte *)stb_sn, stb_sn_len);
out[strlen(ini_reply_pc) + 1 + stb_sn_len] = (byte)(crc >> 8);
out[strlen(ini_reply_pc) + 2 + stb_sn_len] = (byte)(crc & 0xff);
write_comm(port_pc, out, (byte)(strlen(ini_reply_pc) + 3 + stb_sn_len));
byte_read = read_comm(port_pc, in, ini_pkg_len, 100);
if(byte_read != ini_pkg_len)return ERR_COMM;
if(in[0] != 0xaa || in[1] != 0x55)return ERR_COMM;
byte byte_write = pack_data(PACK_TYPE_INI, in, ini_pkg_len, out);
write_comm(port_card, out, byte_write);
byte_read = read_comm(port_card, in, ini_reply_card, 500);
if(byte_read != ini_reply_card)return ERR_COMM;
crc = crc16ccitt(in, ini_reply_card - 2);
if(crc != (in[ini_reply_card - 2] << 8) + in[ini_reply_card - 1])return ERR_CRC;
if(in[3] == ERR_OK){
write_comm(port_pc, ini_ok, strlen(ini_ok));
return ERR_OK;
}
else{
write_comm(port_pc, ini_error, strlen(ini_error));
return in[3];
}
}
}
/* 上电握手,这里,机顶盒序列号必须为9字节 */
byte check_card(byte port_card, const char *stb_sn, byte stb_sn_len, byte *super_cas_id, byte *smartcard_id)
{
ini_comm(port_card);
byte in[128];
byte out[128];
const byte check_reply = 14; /* 应答包长度 */
byte byte_write = pack_data(PACK_TYPE_CHECK, stb_sn, stb_sn, out);
write_comm(port_card, out, byte_write);
byte byte_read = read_comm(port_card, in, check_reply, 300);
if(byte_read != check_reply)return ERR_COMM;
unsigned short crc = crc16ccitt(in, byte_read - 2);
if(crc != (in[byte_read - 2] << 8) + in[byte_read - 1])return ERR_CRC;
if(in[3] == ERR_OK)
{
memcpy(super_cas_id, &in[4], 4);
memcpy(smartcard_id, &in[8], 4);
return ERR_OK;
}
return ERR_NOT_INI;
}
byte process_emm(byte port_card, const byte *emm_data, byte emm_len)
{
ini_comm(port_card);
byte in[128];
byte out[128];
const byte emm_reply = 6;
byte byte_write = pack_data(PACK_TYPE_EMM, emm_data, emm_len, out);
write_comm(port_card, out, byte_write);
delay(300);
byte byte_read = read_comm(port_card, in, emm_reply, 300);
if(byte_read != emm_reply)return ERR_COMM;
unsigned short crc = crc16ccitt(in, byte_read - 2);
if(crc != (in[byte_read - 2] << 8) + in[byte_read - 1])return ERR_CRC;
if(in[3] == 0x00)return ERR_OK;
if(in[3] == 0x01)return ERR_CRC;
if(in[3] == 0x02)return ERR_INVALID_ADDRESS;
return ERR_UNKNOWN;
}
byte process_ecm(byte port_card, const byte *ecm_data, byte ecm_len, byte *cw)
{
ini_comm(port_card);
byte in[128];
byte out[128];
const byte ecm_reply = 22;
byte byte_write = pack_data(PACK_TYPE_ECM, ecm_data, ecm_len, out);
write_comm(port_card, out, byte_write);
delay(100);
byte byte_read = read_comm(port_card, in, ecm_reply, 200);
if(byte_read != ecm_reply)return ERR_COMM;
unsigned short crc = crc16ccitt(in, byte_read - 2);
if(crc != (in[byte_read - 2] << 8) + in[byte_read - 1])return ERR_CRC;
if(in[3] == 0x00){
memcpy(cw, &in[4], 16);
return ERR_OK;
}
return ERR_ECM;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -