📄 main.c
字号:
#include "can_hardware.h"
#include "can_ioctl.h"
#include <linux/poll.h>
#include "main.h"
unsigned char *DEVNAME[2]={"CAN0","CAN1"};
extern int change_frame_format(struct CAN_frame *,int);
extern void reset_base_addr(int);
extern void recv_bottom_half(void *);
unsigned long p(int n,int power)
{
int i,result=1;
for (i=0;i<n;i++)
result=power*result;
return result;
}
unsigned int CAN_poll(struct file * filp, struct poll_table_struct * wait)
{
struct CAN_device_struct *dev=filp->private_data;
unsigned int mask=0;
poll_wait(filp,&dev->recv_queue,wait);
if (!test_bit(0,&dev->rx_lock)&&
(dev->recv_head!=dev->recv_tail))
mask|=POLLIN|POLLRDNORM;
printk("in poll mask=0x%x\n",mask);
return mask;
}
static int CAN_fasync(int fd, struct file *filp, int on)
{
int retval;
struct CAN_device_struct *dev=filp->private_data;
retval = fasync_helper(fd, filp, on, &dev->async_queue);
if (retval < 0)
return retval;
return 0;
}
int CAN_open(struct inode *inode, struct file *filp)
{
int minor,major;
struct CAN_device_struct *dev;
int result; //10
minor=MINOR(inode->i_rdev);
major=MAJOR(inode->i_rdev);
minor%=2;
dev=CAN_device[minor];
dev->minor=minor;
if (!((filp->f_flags&O_ACCMODE)==O_WRONLY)) {
if (dev->ref_count==0) {
result = request_irq(dev->int_level, CAN_interrupt,
SA_SHIRQ|SA_INTERRUPT,dev->dev_name,dev);
if (result) {
printk(KERN_INFO "can't get assigned irq %i\n", dev->int_level);
return result;
}
printk("request irq=%d success,result=%d\n",dev->int_level,result);
}
dev->ref_count++;
} else
printk("no need to register irq\n");
filp->private_data=dev;
MOD_INC_USE_COUNT;
printk("succeed open\n");
return 0;
}
int CAN_release (struct inode *inode, struct file *filp)
{
struct CAN_device_struct *dev=filp->private_data;
if (!((filp->f_flags&O_ACCMODE)==O_WRONLY))
if (--dev->ref_count<=0) {
free_irq(dev->int_level,dev);
printk("free irq ok\n");
dev->timer_count=0;
del_timer(dev->CAN_timer);
}
if (dev->async_queue)
CAN_fasync(dev->async_queue->fa_fd,filp,0);
MOD_DEC_USE_COUNT;
printk("success close\n");
return 0;
}
ssize_t CAN_read(struct file *filp, char *buf, size_t count, loff_t *ppos)
{
int temp_count,double_count;
struct CAN_device_struct *dev=filp->private_data;
int SET=1;
int succ_count=0;
struct CAN_frame *temp_buf;
int complete=0;
unsigned long flags;
if (count<=0) return -1;
count=count/sizeof(struct CAN_frame);
succ_count=0;
temp_buf=(struct CAN_frame *)buf;
while (!complete) {
if (test_and_clear_bit(15,&dev->status)) {
printk("CAN RESET\n");
return -RESET;
}
if (test_and_clear_bit(6,&dev->status)) {
printk("receive and send error >96\n");
return -E96;
}
if (test_and_clear_bit(7,&dev->status)) {
printk("bus off\n");
return -BUSOFF;
}
save_flags(flags);
cli();
temp_count=dev->recv_tail-dev->recv_head;
temp_count=(temp_count+BUFSIZE)%BUFSIZE;
restore_flags(flags);
if ((temp_count>=count)&&!(SET=test_and_set_bit(0,&dev->rx_lock))) {
save_flags(flags);
cli();
if ((dev->recv_head+count)<=BUFSIZE) {
if (copy_to_user(temp_buf,dev->recv_data+dev->recv_head,
count*sizeof(struct CAN_frame))) {
printk("total copy\n");
goto free_lock_and_quit;
}
succ_count=count;
dev->recv_head=(dev->recv_head+count)%BUFSIZE;
}
else {
double_count=BUFSIZE-dev->recv_head;
if (copy_to_user(temp_buf,dev->recv_data+dev->recv_head,
double_count*sizeof(struct CAN_frame))) {
printk("first copy \n");
goto free_lock_and_quit;
}
dev->recv_head=0;
temp_buf+=double_count;
succ_count=double_count;
temp_count=count-double_count;
if (copy_to_user(temp_buf,dev->recv_data,
temp_count*sizeof(struct CAN_frame))) {
printk("second part copy\n");
goto free_lock_and_quit;
}
succ_count+=temp_count;
dev->recv_head=temp_count;
}
complete=1;
restore_flags(flags);
if (!(SET=test_and_clear_bit(0,&dev->rx_lock))) {
printk("rx is not lock ,and free lock again \n");
return -ELOCK;
}
}
else {
if (!SET)
clear_bit(0,&dev->rx_lock);
// printk("sleep no_block=%d\n",no_block);
if (filp->f_flags&O_NONBLOCK) {
if (!no_block) {
printk("you set O_NONBLOCK\n");
dev->CAN_timer->data=(unsigned long)dev;
dev->CAN_timer->expires=jiffies+noblock_delay;
if (!dev->timer_count) {
dev->timer_count++;
add_timer(dev->CAN_timer);
}
no_block=0;
}
else {
no_block=0;
succ_count=0;
printk("return for noblock jiffies=%ld\n",jiffies);
return 0;
}
}
interruptible_sleep_on(&dev->recv_queue);
#ifdef LINUX_24
if ((current->pending.signal.sig[0] & ~current->blocked.sig[0])
||( current->pending.signal.sig[1] & ~current->blocked.sig[1])) {
#else
if ((current->signal.sig[0] & ~current->blocked.sig[0])
||( current->signal.sig[1] & ~current->blocked.sig[1])) {
#endif
if (!SET){
clear_bit(0,&dev->rx_lock);
printk("clear rx_lock");
}
no_block=0;
wake_up_interruptible(&dev->recv_queue);
return -ERESTARTSYS;
}
}
}
return (ssize_t)succ_count;
free_lock_and_quit:
restore_flags(flags);
if (!(test_and_clear_bit(0,&dev->rx_lock))) {
printk("rx is not lock ,and free lock again \n");
return -ELOCK;
}
printk("copy_to_usr failed ,free_lock_and_quit\n");
return succ_count;
}
}
void timer_function(unsigned long ptr)
{
struct CAN_device_struct *dev=(struct CAN_device_struct *)ptr;
printk("enter timer\n");
no_block=1;
wake_up_interruptible(&dev->recv_queue);
dev->timer_count--;
}
ssize_t CAN_write(struct file *filp,const char *buf,size_t count, loff_t *ppos)
{
struct CAN_device_struct *dev=filp->private_data;
int temp;
int result;
static struct CAN_frame *ptr,send_buf[51];
int i;
count=count/sizeof(struct CAN_frame);
if ((count<=0)||(count>51)) return -ENUM;
//memset(send_buf,0,count*TXMESSAGE);
if (copy_from_user(send_buf,buf,count*TXMESSAGE)) return -EFAULT;
ptr=send_buf;
for (i=0;i<count;i++,ptr++) {
result=change_frame_format(ptr,BUFTOHARD);
if (result) {
printk("your frame format is invalid\n");
//print_frame(ptr,1,0);
return -EFRAME;
}
}
if (test_and_set_bit(0,&dev->tx_lock)) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -