/*调用ic_request_irqs注册中断处理程序
*配置引脚*/intic_open (structinode*inode,structfile*filp)
{intnum;intret=0;
unsignedlongflags;
ICDEBUG(KERN_ALERT"open ic card\n");//获取次设备号num=MINOR(inode->i_rdev);
ICDEBUG(KERN_ALERT"MINOR:%d\n",num);if(num>=ICCARD_NR_DEVS)return-ENODEV;
spin_lock_irqsave(&lock,flags);
filp->private_data=&ic_dev_info[num];//检测IC卡是否已插入设备s3c2410_gpio_cfgpin(S3C2410_GPG6,S3C2410_GPG6_INP);//ICCARD_INTEREPTif((__raw_readw(S3C2410_GPGDAT)&(1<<6))==0<<6)
{
ic_dev_info[num].ic_state=1;//代表卡已插入ic_dev_info[num].r_press=1;//设备可读ic_dev_info[num].w_press=1;//设备可写ICDEBUG(KERN_ALERT"has ic card device\n");
}else{
ic_dev_info[num].ic_state=0;//代表卡已插入ic_dev_info[num].r_press=0;//设备可读ic_dev_info[num].w_press=0;//设备可写ICDEBUG(KERN_ALERT"no found ic card device\n");
}
spin_unlock_irqrestore(&lock,flags);//初始化输入输出引脚init_gpio();
ICDEBUG(KERN_ALERT"open ic card success\n");returnret;
}intic_release(structinode*inode,structfile*filp)
{//ic_free_irqs();return0;
}/**从ic卡中读出一个字节的数据*/intic_card_read_byte(char*ch)
{intret=0;intii;for(ii=8; ii>0; ii--)
{
CLR_CARD_CLK();
udelay(5);*ch=(*ch)>>1;//从低位读起//if((__raw_readw(S3C2410_GPGDAT)&0x0008)==0x0008)if((__raw_readw(S3C2410_GPGDAT)&(1<<3))==1<<3)
{*ch|=0x80;
ICDEBUG(KERN_ALERT"\n");
}else{
ICDEBUG(KERN_ALERT"\n");
}
udelay(5);
SETB_CARD_CLK();
}
ICDEBUG(KERN_ALERT"ic_card_read_byte:ch is>>>>>(%c)\n",*ch);returnret;
}intic_card_write_byte(char*ch)
{intret=0;intii;
ICDEBUG(KERN_ALERT"enter ic_card_write_byte,ch is %c\n",*ch);for(ii=0; ii<8; ii++)
{
CLR_CARD_CLK();
udelay(5);if(*ch&0x01)
{
ICDEBUG(KERN_ALERT"[+++++$++++++++]\n");
SETB_CARD_IO();//输入1}else{
ICDEBUG(KERN_ALERT"[-----$--------]\n");
CLR_CARD_IO();//输入0}
udelay(5);
SETB_CARD_CLK();
udelay(10);*ch=*ch>>1;
}returnret;
}/**复位和复位应答*/staticintic_card_reset(void)
{
unsignedchartemp_ch;inttemp_i=4;
s3c2410_gpio_cfgpin(S3C2410_GPG3,S3C2410_GPG3_OUTP);//OUTudelay(5);
CLR_CARD_RESRT();
CLR_CARD_CLK();
SETB_CARD_IO();
udelay(5);
SETB_CARD_RESRT();
udelay(5);
SETB_CARD_CLK();
udelay(30);
CLR_CARD_CLK();
udelay(5);
CLR_CARD_RESRT();
s3c2410_gpio_cfgpin(S3C2410_GPG3,S3C2410_GPG3_INP);//INudelay(10);do{//temp_ch = ic_card_read_byte();ic_card_read_byte(&temp_ch);
ICDEBUG(KERN_ALERT"ic_card_reset:temp_ch is(%c)\n",temp_ch);
}while(--temp_i>0);
CLR_CARD_CLK();
s3c2410_gpio_cfgpin(S3C2410_GPG3,S3C2410_GPG3_OUTP);//INudelay(5);
SETB_CARD_IO();
udelay(5);
CLR_CARD_CLK();
udelay(5);return0;
}/**命令开始条件*/voidic_card_start_cmd(void)
{
s3c2410_gpio_cfgpin(S3C2410_GPG3,S3C2410_GPG3_OUTP);//outCLR_CARD_CLK();
SETB_CARD_IO();
udelay(5);
SETB_CARD_CLK();
udelay(5);
CLR_CARD_IO();
udelay(5);
}/**命令结束条件*/voidic_card_end_cmd(void)
{
s3c2410_gpio_cfgpin(S3C2410_GPG3,S3C2410_GPG3_OUTP);
CLR_CARD_CLK();
CLR_CARD_IO();
udelay(5);
SETB_CARD_CLK();
udelay(5);
SETB_CARD_IO();
udelay(5);
}/*发送命令*/voidic_card_send_cmd(constcharcmd,constcharaddr,constcharcount)
{
ICDEBUG(KERN_ALERT"enter ic_card_read:cmd is %c,addr is %c,count is %c\n",cmd,addr,count);
ic_card_start_cmd();
ic_card_write_byte(&cmd);
ic_card_write_byte(&addr);
ic_card_write_byte(&count);
ic_card_end_cmd();
}voidic_card_breakoperator(void)
{
s3c2410_gpio_cfgpin(S3C2410_GPG3,S3C2410_GPG3_OUTP);
CLR_CARD_CLK();
CLR_CARD_RESRT();
CLR_CARD_IO();
udelay(5);
SETB_CARD_RESRT();
SETB_CARD_IO();
udelay(5);
CLR_CARD_RESRT();
udelay(5);
}/*从设备中读取指定长度的数据*/ssize_t ic_dev_read(structfile*filep,constchar*buf, size_t count, loff_t*offset)
{intret=0;//wait_event_interruptible();//char *kbuf;intistate;intsizetmp;char*pbuf;//unsigned char ch=0;ic_card_dev*icdev=(ic_card_dev*)filep->private_data;
ICDEBUG(KERN_ALERT"enter ic_dev_read\n");
istate=icdev->ic_state;
ICDEBUG(KERN_ALERT"ic_dev_istate:%d\n",istate);
pbuf=buf;if(!istate)
{return-ENODEV;
}if(!pbuf)
{return-1;
}
sizetmp=count;
s3c2410_gpio_cfgpin(S3C2410_GPG3,S3C2410_GPG3_INP);//将GPG3配置成输入引脚CLR_CARD_CLK();
udelay(5);do{
ic_card_read_byte(pbuf++);//*buf++ = ic_card_read_byte();ret++;
ICDEBUG(KERN_ALERT"[ic_card_read:buf is (%c) ret:%d]\n",*(pbuf-1),ret);
}while(--sizetmp);returnret;
}/*往设备中写入数据*/ssize_t ic_dev_wrtie(structfile*filep,char*buf, size_t count, loff_t*offset)
{intret=0;intistate;
unsignedlongflags;intsizetmp;
ICDEBUG(KERN_ALERT"enter ic_dev_wrtie\n");
spin_lock_irqsave(&lock,flags);
istate=((ic_card_dev*)(filep->private_data))->ic_state;
spin_unlock_irqrestore(&lock,flags);if(!istate)
{return-ENODEV;
}if(!buf)return-1;//wait_event_interruptible();s3c2410_gpio_cfgpin(S3C2410_GPG3, S3C2410_GPG3_OUTP);//将GPG3配置成输出引脚sizetmp=count;do{
ic_card_write_byte(buf++);//按字节发送至ic卡}while(--sizetmp);returnret;
}/*file_operations read*/ssize_t ic_card_read(structfile*filep,char__user*buf, size_t count, loff_t*offset)
{//int ii;intret;char*kbuf;
unsignedlongflags;intr_press;
ICDEBUG(KERN_ALERT"enter ic_card_read\n");
spin_lock_irqsave(&lock,flags);
r_press=((ic_card_dev*)filep->private_data)->r_press;
spin_unlock_irqrestore(&lock,flags);
ICDEBUG(KERN_ALERT"ic_card_read:r_press is:%d\n",r_press);
wait_event_interruptible(r_wait, r_press!=0);
kbuf=kmalloc(count,GFP_KERNEL);if(!kbuf)
{return-ENOMEM;
}
spin_lock_irqsave(&lock,flags);
((ic_card_dev*)filep->private_data)->w_press=0;
spin_unlock_irqrestore(&lock,flags);
ic_card_reset();
ic_card_send_cmd((constchar)IC_RMM_CMD,(constchar)((ic_card_dev*)(filep->private_data))->readbufstart,0xff);
ret=ic_dev_read(filep, kbuf, count, offset);
ICDEBUG(KERN_ALERT"[ic_card_read kbuf is:%s]\n",kbuf);if(ret>=0)
{
ret=copy_to_user(buf,kbuf,count);
}
ICDEBUG(KERN_ALERT"\n",kbuf,buf,ret,count);
ic_card_breakoperator();
spin_lock_irqsave(&lock,flags);
((ic_card_dev*)filep->private_data)->w_press=1;
spin_unlock_irqrestore(&lock,flags);
kfree(kbuf);returnret;
}/*file_operations write*/ssize_t ic_card_wrtie(structfile*filep,char__user*buf, size_t count, loff_t*offset)
{intret;char*kbuf;
unsignedlongflags;intw_press;
ICDEBUG(KERN_ALERT"enter ic_card_wrtie\n");
spin_lock_irqsave(&lock,flags);
w_press=((ic_card_dev*)filep->private_data)->w_press;
spin_unlock_irqrestore(&lock,flags);
kbuf=kmalloc(count,GFP_KERNEL);if(!kbuf)
{return-ENOMEM;
}
wait_event_interruptible(r_wait, w_press!=0);//if(w_press)//{spin_lock_irqsave(&lock,flags);
((ic_card_dev*)filep->private_data)->r_press=0;
spin_unlock_irqrestore(&lock,flags);
ic_card_reset();
ic_card_send_cmd((constchar)IC_WMM_CMD,(constchar)((ic_card_dev*)(filep->private_data))->writebufstart,count);if(copy_from_user(kbuf, buf, count))
{
kfree(kbuf);return-EFAULT;
}
ICDEBUG(KERN_ALERT"copy_from_user kbuf------------->:%s\n",kbuf);
ret=ic_dev_wrtie(filep, kbuf, count, offset);
printk(KERN_ALERT"ic_dev_wrtie ret : %d\n",ret);
ic_card_breakoperator();
spin_lock_irqsave(&lock,flags);
((ic_card_dev*)filep->private_data)->w_press=1;
spin_unlock_irqrestore(&lock,flags);
kfree(kbuf);
ICDEBUG(KERN_ALERT"ic_card_wrtie success\n");returnret;
}intic_ioctl(structinode*inode,structfile*filep, unsignedintcmd, unsignedlongarg)
{
unsignedinticount;
unsignedlongflags;
spin_lock_irqsave(&lock,flags);switch(cmd)
{caseCFG_RD_COUNT:
icount=(unsignedint)arg;
((ic_card_dev*)filep->private_data)->readcount=icount;break;caseCFG_WR_COUNT:
icount=(unsignedint)arg;
((ic_card_dev*)filep->private_data)->writecount=icount;break;default:break;
}
spin_unlock_irqrestore(&lock,flags);return0;
}/*#define POLLIN 0x0001 //有数据可以读入,read不会阻塞,注意:select的请情况下,即使到EOF也是ready的.
#define POLLPRI 0x0002 //紧急数据,比如TCP,或者packet模式的peseudo-terminal发现slave的状态有变化.
#define POLLOUT 0x0004 //写入不会阻塞.
#define POLLERR 0x0008 //输出出错
#define POLLHUP 0x0010 //Hang up (output only).
#define POLLNVAL 0x0020 //Invalid request: fd not open (output only).
The rest seem to be more-or-less nonstandard. Check them!
#define POLLRDNORM 0x0040 //POLLIN.
#define POLLRDBAND 0x0080 //高优先级的数据read for read (generally unused on Linux).
#define POLLWRNORM 0x0100 //Equivalent to POLLOUT.
#define POLLWRBAND 0x0200 //Priority data may be written.
#define POLLMSG 0x0400
#define POLLREMOVE 0x1000*/unsignedintic_poll (structfile*filep,structpoll_table_struct*wait)
{intic_num=0;//testunsignedintmask=0;
unsignedlongflags;//加入这句话是为了在读写状态发生变化的时候,通知核心层,让核心层重新调用poll函数查询信息。