📄 ph8550_sc.c
字号:
for(i = 0; i < sizeof(supported_baudrate)/sizeof(struct sc_baudrate); i ++) if( (supported_baudrate[i].fi == fi) && (supported_baudrate[i].di == di)) { find_baudrate = 1; break; } else find_baudrate = 0; if(!find_baudrate) return -1; if(supported_baudrate[i].psc == 32) UCR2 |= 0x01; else UCR2 &= (~0x01); PDR = supported_baudrate[i].pdr; smartcard_dev.fi = fi; smartcard_dev.di = di; smartcard_dev.etu = supported_baudrate[i].psc * supported_baudrate[i].pdr; return 0;}static int sc_SetReaderParameter(sc_parameter p){/////////here, set the baudrate////////////////////////////// if(sc_SetBaudRate(p.fi, p.di) == -1) return -2; //can't find the appropriate baudrate/////////here, set the guard time between of characters ////// GTR = p.gtr_time; smartcard_dev.gtr_time = p.gtr_time;/////////here, set the protocal ///////////////////////////// if(p.protocol) UCR1 |= 0x10; else UCR1 &=(~0x10); smartcard_dev.prot = p.protocol;/////////here, weather remove the parity bit //////////////// if(p.rm_parity) { CCR |= 0x40; smartcard_dev.remove_parity = 1; } else { CCR &= (~0x40); smartcard_dev.remove_parity = 0; }/////////here, set the clock card frequency /////////////////////// if((p.div_clock_multiple >=0) && (p.div_clock_multiple < 8)) sc_SetDivClock(p.div_clock_multiple); else smartcard_dev.clock = 54*1024/supported_div_Hz[CCR&0x07].multiple; // if this happens, there is someting wrong /* set reader baud rate and update dev->clock , so we can calcute etu */ return 0;}static int sc_PPS(unsigned char *pps_q, unsigned int n, unsigned char *pps_r, unsigned int i){ unsigned char F, D; int error = 0; AtrOrWr_flag = 1; memset(pps_r, 0 , 6); if((error = sc_RawWrite(pps_q,&n))>0) return error; if((error = sc_RawRead(pps_r,&i))>0) return error; if(pps_r[0]==0xff) { smartcard_dev.prot = pps_r[1]&0x0f; if(smartcard_dev.prot) UCR1 |= 0x10; else UCR1 &=(~0x10); if(pps_r[1]&0x10) { if(pps_r[2]==pps_q[2]) { smartcard_dev.fi = (pps_r[2]&0xf0)>>4; smartcard_dev.di = pps_r[2]&0x0f; if(sc_SetBaudRate(smartcard_dev.fi, smartcard_dev.di) == -1) return SC_ERROR_PPS_SET_BAUDRATE; } else return SC_ERROR_PPS_TREAT_BAUDRATE; } else { F = 1; D = 1; if(sc_SetBaudRate(smartcard_dev.fi, smartcard_dev.di) == -1) return SC_ERROR_PPS_DEFAULT_BAUDRATE; //can't find the appropriate baudrate } if(pps_r[1]&0x20) { if(pps_r[3]!=pps_q[3]) return SC_ERROR_PPS_GT_BAUDRATE; } if(pps_r[1]&0x40) { if(pps_r[4]!=pps_q[4]) return SC_ERROR_PPS_CHECK; } return 0; } else return SC_ERROR_PPS_PROTOCOL;}//ATR处理static int sc_AtrProc(void){ int i = smartcard_dev.atr_len; unsigned char T0,TA1,TB1,TC1,TD1,TA2,TB2,TC2,TD2,TA3,TB3,TC3,TD3,TA4,TB4,TC4,TD4; unsigned char K=0,F=1,D=1,P=5,I=50,N=0xff,wi=10,T=0; //参数缺省值 unsigned char idx=0,TCK=0; unsigned char TA1_flg=0,TB1_flg=0,TA2_flg=0,TB2_flg=0; int pps_error = 0; unsigned char PPS_Q[4] = {0xff,0x10,0x11,0xfe}; SCIF_INT_ENABLE &= (~0x01); //close tbe/rbf interrupt if((smartcard_dev.atr_buffer[0]!=0x3B) && (smartcard_dev.atr_buffer[0]!=0x3F)) //接收异常 return SC_ERROR_ATR_PROTOCOL; if((smartcard_dev.atr_buffer[0]==0x3B) || (smartcard_dev.atr_buffer[0]==0x3F)) //正常的起始字符 { idx = 1; T0 = smartcard_dev.atr_buffer[idx++]; K = T0 & 0x0f; if(T0&0x10) { TA1 = smartcard_dev.atr_buffer[idx++]; PPS_Q[2] = smartcard_dev.atr_buffer[2]; PPS_Q[3] = PPS_Q[0]^PPS_Q[1]^PPS_Q[2]; TA1_flg=1; } if(T0&0x20) { TB1 = smartcard_dev.atr_buffer[idx++]; TB1_flg=1; } if(T0&0x40) { TC1 = smartcard_dev.atr_buffer[idx++]; N = TC1; } if(T0&0x80) { TD1 = smartcard_dev.atr_buffer[idx++]; T = TD1&0x0f; if(TD1&0x10) { TA2 = smartcard_dev.atr_buffer[idx++]; TA2_flg=1; } if(TD1&0x20) { TB2 = smartcard_dev.atr_buffer[idx++]; TB2_flg=1; } if(TD1&0x40) { TC2 = smartcard_dev.atr_buffer[idx++]; wi = TC2; } if(TD1&0x80) { TD2 = smartcard_dev.atr_buffer[idx++]; T = TD2&0x0f; if(TD2&0x10) TA3 = smartcard_dev.atr_buffer[idx++]; if(TD2&0x20) TB3 = smartcard_dev.atr_buffer[idx++]; if(TD2&0x40) TC3 = smartcard_dev.atr_buffer[idx++]; if(TD2&0x80) { TD3 = smartcard_dev.atr_buffer[idx++]; T = TD3&0x0f; if(TD3&0x10) TA4 = smartcard_dev.atr_buffer[idx++]; if(TD3&0x20) TB4 = smartcard_dev.atr_buffer[idx++]; if(TD3&0x40) TC4 = smartcard_dev.atr_buffer[idx++]; if(TD3&0x80) { TD4 = smartcard_dev.atr_buffer[idx++]; T = TD4&0x0f; } } } } if(T) TCK = smartcard_dev.atr_buffer[i-1]; if(T==15 && TB1_flg) { P = TB1&0x3f; I = (TB1&0xc0)>>6; if(TB2_flg) P = TB2; } if(T>1) T = 1; if(TA1_flg && TA2_flg && !(TA2&0x10)) //F/D存在,且为专用模式,b5=0 { F = (TA1&0xf0)>>4; D = TA1&0x0f; } para.gtr_time = N; para.protocol = T; para.cwi = 960 * wi; if(TA1_flg && !TA2_flg) //F/D存在,且为协商模式 { F = 1; D = 1; sc_SetBaudRate(F, D); //PPS request pps_error = sc_PPS(PPS_Q,4,PPS_R,4); if(!pps_error) { #ifdef DEBUG printk(KERN_INFO"PPS success!!!\n"); #endif return 0; } else { #ifdef DEBUG printk(KERN_INFO"PPS failed!!!\n"); #endif return pps_error; } } } return 0;}static int sc_T0_APDU(unsigned char *pSnd, unsigned int slen, unsigned char *pRcv){ unsigned char ack, sw1, sw2;//, INS; unsigned int i=5, le=0, lc=0, readlen =0; char error = 0; if(slen == 5) // 情况1和2 le = pSnd[4]; if(slen > 5) // 情况3和4 { lc = pSnd[4]; if((5+lc) < slen) le = pSnd[slen-1]; } error = sc_RawWrite(pSnd, &i); // send apdu cmd if(error > 0) return error; while(1) { //receive one ack readlen = 1; error = sc_RawRead(&ack,&readlen); if(error > 0) return error; //analyse the ack if(ack == 0x60) // NULL continue; else if(((ack&0xF0) == 0x60) || ((ack&0xF0) == 0x90)) { sw1 = ack; readlen = 1; error = sc_RawRead(&sw2,&readlen); if(error > 0) return error; return ((sw1<<8)|sw2); } else { if(((ack^pSnd[1])== 0x00) || ((ack^pSnd[1]) == 0x01)) { if(lc > 0) { error = sc_RawWrite(&pSnd[5], &lc); if(error > 0) return error; } if(le > 0) { error = sc_RawRead(pRcv, &le); if(error > 0) return error; APDU_RESULT_MUN = le; } continue; } if(((ack^pSnd[1]) == 0xff) || ((ack^pSnd[1]) == 0xfe)) { if((i-5)<lc) { readlen = 1; error = sc_RawRead(&pSnd[i++],&readlen); if(error > 0) return error; } continue; } } }}static int sc_ioctl(struct inode *inode, struct file *flip, unsigned int cmd, unsigned long arg){ int error = 0; switch(cmd) { case SC_IOC_WARMACTIVATE: if(smartcard_dev.exist == 0) error = SC_ERROR_NOCARD; else warm_reset(); break; case SC_IOC_DEACTIVATE: Sc_DeactivateCard(); break; case SC_IOC_ATRPROC: if(smartcard_dev.exist == 0) error = SC_ERROR_NOCARD; else error = sc_AtrProc(); break; case SC_IOC_GETPPSRESULT: if(smartcard_dev.exist == 0) { error = SC_ERROR_NOCARD; break; } if(copy_to_user((void*)arg, (void*)PPS_R, 6)) error = SC_ERROR_KNTOUSER; break; case SC_IOC_GETAPDUSULT: if(smartcard_dev.exist == 0) { error = SC_ERROR_NOCARD; break; } if(copy_to_user((void*)arg, (void*)APDU_RESULT, APDU_RESULT_MUN)) error = SC_ERROR_KNTOUSER; else APDU_RESULT_MUN = 0; break; case SC_IOC_GETCARDEXIST: if(copy_to_user((void*)arg, (void*)&smartcard_dev.exist, sizeof(int))) error = SC_ERROR_KNTOUSER; break; case SC_IOC_SETAPDUCMD: if(smartcard_dev.exist == 0) { error = SC_ERROR_NOCARD; break; } if(APDU_CMD_NUM <= 0) { error = SC_ERROR_CTL_CMDMUN; break; } if(copy_from_user((void*)APDU_CMD, (void*)arg, APDU_CMD_NUM)) error = SC_ERROR_USERTOKN; break; case SC_IOC_SETAPDUCMDNUM: if(smartcard_dev.exist == 0) { error = SC_ERROR_NOCARD; break; } if(copy_from_user((void*)&APDU_CMD_NUM, (void*)arg, sizeof(int))) error = SC_ERROR_USERTOKN; break; case SC_IOC_SETPARAMETER: if(smartcard_dev.exist == 0) { error = SC_ERROR_NOCARD; break; } if(copy_from_user((void *)¶, (void *)arg, sizeof(sc_parameter))) { error = SC_ERROR_USERTOKN; break; } if(sc_SetReaderParameter(para)== -2) error = SC_ERROR_SET_READERPARA; break; case SC_IOC_GETATR: if(smartcard_dev.exist == 0) { error = SC_ERROR_NOCARD; break; } if(access_ok(VERIFY_WRITE,arg,smartcard_dev.atr_len)==-EFAULT) { #ifdef DEBUG printk(KERN_INFO"cann't write atrbuf\n"); #endif error = SC_ERROR_VERIFY_ATRBUF; break; } if(copy_to_user((void*)arg, (void*)smartcard_dev.atr_buffer, smartcard_dev.atr_len)) error = SC_ERROR_KNTOUSER; break; case SC_IOC_EXECUTECMD: if(smartcard_dev.exist == 0) { error = SC_ERROR_NOCARD; break; } error = sc_T0_APDU(APDU_CMD, APDU_CMD_NUM, APDU_RESULT); break; case SC_IOC_GETSTATUS: if(copy_to_user((void*)arg, (void*)&smartcard_dev, sizeof(SmartCard_Dev))) error = SC_ERROR_KNTOUSER; else error = 0; break; default: return -ENOTTY; } if(!error) return 0; else return error;} struct file_operations sc_fops = { owner: THIS_MODULE, open: sc_open, ioctl: sc_ioctl, //read: sc_read, //write: sc_write, release: sc_release,};//struct cdev *pnx8550_sc_cdev;static int __init smartcard_init(void){ if(register_chrdev(SMARTCARD_MAJOR,"smcard",&sc_fops) < 0) { printk(KERN_INFO"Register char dev error\n"); return -1; } devfs_mk_cdev(MKDEV(SMARTCARD_MAJOR,0),S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP,"smcard"); #ifdef DEBUG printk(KERN_INFO"Ph8550 SC Module ID = 0x%x\n", SCIF_MODULE_ID); #endif printk(KERN_INFO"SmartCard driver has been installed successfully!\n"); memset(&smartcard_dev,0,sizeof(SmartCard_Dev)); memset(¶,0,sizeof(sc_parameter)); return 0;}static void __exit smartcard_exit(void){ p_atr = NULL; devfs_remove("smcard"); unregister_chrdev(SMARTCARD_MAJOR, "smcard"); printk(KERN_INFO"SmartCard driver has been canceled successfully!\n");}module_init(smartcard_init);module_exit(smartcard_exit);MODULE_DESCRIPTION("PNX8950 Smart-Uart1 Driver, Just for T0 Card");MODULE_AUTHOR("FanJie Meng:Aero-Info Corp.");MODULE_LICENSE("Proprietary");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -