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

📄 main.c

📁 盛博can驱动程序功能很全
💻 C
📖 第 1 页 / 共 2 页
字号:
#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 + -