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

📄 read.c

📁 HMS30C7202下的CAN驱动
💻 C
字号:
/** read.c * * Written by Sebastian Stolzenberg email:stolzi@sebastian-stolzenberg.de * Version 1.0  04 Feb 2003 */#ifndef __KERNEL__# define __KERNEL__#endif#ifndef MODULE# define MODULE#endif#define EXPORT_SYMTAB#include "../include/candrv.h"#include "../include/hms30c7202_can.h"#include "../include/c_can.h"////////////////////////////////////////////////////////////////////////////////* * can_read * * Read function called by user through device file. User gets the specified * number of messages from the fifo of the message object. */ssize_t can_read( struct file *filp,                  char *buffer,                  size_t length,                  loff_t *offset){        struct msgobj_t *pmsgobj;        struct canmsg_t read_msg;        int ret=0;        if ( offset != &filp->f_pos ) return -ESPIPE;        if ( length < sizeof( struct canmsg_t )) {                CANMSG("Trying to read less bytes than a CAN message,");                CANMSG("this will always return zero.");                return 0;        }        if ( NULL == ( pmsgobj = filp->private_data )) {                CANMSG("Device is not correctly configured.");                CANMSG("Please reload the driver.");                return -1;        }        if (!(pmsgobj->hostchip->flags & CHANNEL_CONFIGURED)) {                CANMSG("Device is not correctly configured, please reopen.");                return -1;        }        /* Copy one message from userspace, to find out if a RTR-Frame should be sent. */        copy_from_user( &read_msg, buffer, sizeof(struct canmsg_t) );        if ( read_msg.flags & MSG_RTR )                ret = can_rtr_read( pmsgobj, buffer);        else                ret = can_std_read( filp, pmsgobj, buffer, length );        return ret;}////////////////////////////////////////////////////////////////////////////////* * can_std_read * * This is the 'Normal' read handler for normal transmission messages */inline ssize_t can_std_read( struct file *filp,                             struct msgobj_t *pmsgobj,                             char *buffer,                             size_t length ){        int ret = 0;        int bytes_to_read = length;        unsigned long irqflags;        if ( NULL == pmsgobj ) return 0;        spin_lock_irqsave( &pmsgobj->hostchip->sprlock, irqflags );        /* Logic for Circular buffer           =========================           empty if rxrp == rxwp           full if abs( rxrp - rxwp ) == 1        */        while ( pmsgobj->fifo->rxrp == pmsgobj->fifo->rxwp ) {                /* Receive buffer is empty */                spin_unlock_irqrestore( &pmsgobj->hostchip->sprlock, irqflags );                if ( filp->f_flags & O_NONBLOCK ) {                        DEBUGMSG("Non Blocking read. Returning EAGAIN");                        return -EAGAIN;                }                pmsgobj->rv = 0;                /* Wait for messages. */                if ( wait_event_interruptible( pmsgobj->fifo->readq,                                              ( pmsgobj->fifo->rxrp !=                                                pmsgobj->fifo->rxwp ))) {                        return -ERESTARTSYS;                }                if ( pmsgobj->rv < 0 ) {                        return pmsgobj->rv;                }                spin_lock_irqsave( &pmsgobj->hostchip->sprlock, irqflags );        }        /* Calculate number of messages to be transfered */        /* write pointer behind read pointer */        if ( pmsgobj->fifo->rxwp > pmsgobj->fifo->rxrp ) {                bytes_to_read = min( bytes_to_read,                                     pmsgobj->fifo->rxwp - pmsgobj->fifo->rxrp );                /* Copy messages to userspace */                if ( copy_to_user( buffer, pmsgobj->fifo->rxrp, bytes_to_read )) {                        DEBUGMSG( "Failed to copy data to user space. b=%lx p=%lx %d",                                ( unsigned long )buffer,                                ( unsigned long )pmsgobj->fifo->rxrp,                                bytes_to_read);                        spin_unlock_irqrestore( &pmsgobj->hostchip->->sprlock, irqflags );                        return -EFAULT;                }                /* Remove messages from buffer */                pmsgobj->fifo->rxrp += bytes_to_read;                ret = bytes_to_read;                if ( pmsgobj->fifo->rxrp >= ( pmsgobj->fifo->prxbuf + pmsgobj->fifo->rxsize ) ) {                        pmsgobj->fifo->rxrp = pmsgobj->fifo->prxbuf;  /* wrapped */                }        /* write pointer before read pointer */        } else {                /* The write pointer has wrapped, return data up to end */                bytes_to_read = min( bytes_to_read,                                     pmsgobj->fifo->prxbuf +                                     pmsgobj->fifo->rxsize -                                     pmsgobj->fifo->rxrp );                /* Copy messages to userspace */                if ( copy_to_user( buffer, pmsgobj->fifo->rxrp, bytes_to_read )) {                        DEBUGMSG( "Failed to copy data to user space. b=%lx p=%lx %d",                                ( unsigned long )buffer,                                ( unsigned long )pmsgobj->fifo->rxrp,                                bytes_to_read);                        spin_unlock_irqrestore( &pmsgobj->hostchip->->sprlock, irqflags );                        return -EFAULT;                }                /* Remove messages from buffer */                pmsgobj->fifo->rxrp += bytes_to_read;                ret = bytes_to_read;                if ( pmsgobj->fifo->rxrp >= ( pmsgobj->fifo->prxbuf + pmsgobj->fifo->rxsize ) ) {                        pmsgobj->fifo->rxrp = pmsgobj->fifo->prxbuf;  /* wrapped */                }                /* all requested bytes read ? */                if ( length > bytes_to_read ) {                        /* move forward pointer to user buffer */                        buffer += bytes_to_read;                        /* calc new byte count */                        bytes_to_read = min( (int)length - bytes_to_read,                                     pmsgobj->fifo->rxwp - pmsgobj->fifo->prxbuf );                        /* Copy messages to userspace */                        if ( copy_to_user( buffer, pmsgobj->fifo->rxrp, bytes_to_read )) {                                DEBUGMSG( "Failed to copy data to user space. b=%lx p=%lx %d",                                        ( unsigned long )buffer,                                        ( unsigned long )pmsgobj->fifo->rxrp,                                        bytes_to_read);                                spin_unlock_irqrestore( &pmsgobj->hostchip->->sprlock, irqflags );                                return -EFAULT;                        }                        /* Remove messages from buffer */                        pmsgobj->fifo->rxrp += bytes_to_read;                        ret += bytes_to_read;                }        }        spin_unlock_irqrestore( &pmsgobj->sprlock, irqflags );        return ret;}////////////////////////////////////////////////////////////////////////////////* * can_rtr_read * * This is the 'RTR' read handler for remote transmission request messages */inline ssize_t can_rtr_read( struct msgobj_t *pmsgobj,                             char *buffer ){        unsigned long flags;        struct rtr_id *prtr_current = NULL, *pnew_rtr_entry = NULL;        struct canmsg_t read_msg;        return -ERESTARTSYS;        if ( NULL == pmsgobj ) return 0;        DEBUGMSG("Remote transmission request");        spin_lock_irqsave( &pmsgobj->hostchip->rtr_lock, flags);        // Add element to the RTR-Queue        if ( pmsgobj->hostchip->prtr_queue == NULL ) {                //No remote messages pending                pnew_rtr_entry = (struct rtr_id *)kmalloc( sizeof( struct rtr_id),                                                           GFP_ATOMIC);                if ( NULL == pnew_rtr_entry ) {                        spin_unlock_irqrestore( &pmsgobj->hostchip->rtr_lock, flags);                        return -ENOMEM;                }                pmsgobj->hostchip->prtr_queue = pnew_rtr_entry;        } else {                prtr_current = pmsgobj->hostchip->prtr_queue;                while ( prtr_current->next != NULL )                        prtr_current = prtr_current->next;                pnew_rtr_entry = (struct rtr_id *)kmalloc( sizeof( struct rtr_id ),                                                           GFP_ATOMIC);                prtr_current->next = pnew_rtr_entry;        }        init_waitqueue_head( &pnew_rtr_entry->rtr_wq );        pnew_rtr_entry->id = read_msg.id;        pnew_rtr_entry->rtr_message = &read_msg;        pnew_rtr_entry->next = NULL;        spin_unlock_irqrestore( &pmsgobj->hostchip->rtr_lock, flags );        // Send remote transmission request        pmsgobj->hostchip->remote_request( pmsgobj );        pmsgobj->rv = 0;        // Wait for reception of the answer        interruptible_sleep_on( &pnew_rtr_entry->rtr_wq );        // Copy answer into userspace        spin_lock_irqsave( &pmsgobj->hostchip->rtr_lock, flags );        copy_to_user( buffer, &read_msg, sizeof(struct canmsg_t) );        // Remove element from RTR-Queue        if ( pmsgobj->hostchip->prtr_queue == pnew_rtr_entry ) {                if ( pnew_rtr_entry->next != NULL )                        pmsgobj->hostchip->prtr_queue = pnew_rtr_entry->next;                else                        pmsgobj->hostchip->prtr_queue = NULL;        } else {                prtr_current = pmsgobj->hostchip->prtr_queue;                while ( prtr_current->next != pnew_rtr_entry )                        prtr_current = prtr_current->next;                if ( pnew_rtr_entry->next != NULL )                        prtr_current->next = pnew_rtr_entry->next;                else                        prtr_current->next = NULL;        }        spin_unlock_irqrestore( &pmsgobj->hostchip->rtr_lock, flags);        kfree( pnew_rtr_entry );        return pmsgobj->rv;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -