模拟qnx pps结点在linux做了个畸类的设备结点

由于在互斥和同步等待队列上存在不能完全同步的问题,还有在内核里做应答重发比较复杂,最终没有采用此方式
把代码放到此做笔记,供下次开发参考

输入输出都是设备节点的版本

// uart_double_attr.c
#include <linux/module.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/init.h>
#include <linux/cdev.h>
#include <linux/slab.h>
#include <linux/kdev_t.h>
#include <linux/device.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <linux/delay.h>


#define TTYMSG_MAJOR 250

#define MAX_SIZE 0x1000    /* 全局内存最大4KB */
#define FRAME_MAX_SIZE 0x80    /* 帧最大长度128Bytes */
#define MSG_CLEAR 0x1      /* 清零全局内存 */

#define     MCU_SYNC1           0xFA
#define     MCU_SYNC2           0xAF
#define     MAX_BYTE_SIZE       0x400
#define     MAX_CACH_SIZE       (MAX_BYTE_SIZE *4)


static DEFINE_MUTEX(messages0_mutex);


static DECLARE_WAIT_QUEUE_HEAD(in_messages_waitq);
static volatile int in_messages_ready = 0;

typedef struct _messages_dev
{
    unsigned char sync;
    unsigned char frame_len;
    unsigned char frame[FRAME_MAX_SIZE];
    unsigned char mem[FRAME_MAX_SIZE];
} messages_dev;

static messages_dev *messages_devp;
static messages_dev in_messages_buff[2];

static struct class* messages0_class;
static struct class* messages1_class;
static struct class* messages16_class;
static struct class* messages17_class;

static int in_messages_major = 0;
static int out_messages_major = 0;
static int klog = 1;

typedef struct _msgdate {
    unsigned char g_data_buff[MAX_BYTE_SIZE];
    unsigned char g_data_cmd[MAX_BYTE_SIZE];
    unsigned char g_data_cache[MAX_BYTE_SIZE];
} msgdata;

static msgdata s_msgdate;
static int ifront = 0, irear = 0;

static unsigned int calc_check_sum(unsigned char* pBuf, int iLen)
{
    int i = 0;
    unsigned int check_sum = 0;

    check_sum = pBuf[0];
    for(i = 1; i < iLen; i++)
    {
        check_sum ^= pBuf[i];
    }

    return check_sum;
}

static void pick_data(messages_dev *messages, int len)
{
    int ii;
    unsigned char msleep_timeout = 0;
    unsigned char* pdata = messages->mem;


    if(klog)
    {
        printk("[uart] pick_data = %d/%d : ", len, MAX_BYTE_SIZE);
        for ( ii = 0; ii < len; ii++)
        {
            printk("0x%02x,", pdata[ii]);
        }
        printk("\n");
    }

    if (ifront + len <= MAX_CACH_SIZE)
    {
        memcpy(s_msgdate.g_data_cache + ifront, pdata, len);
    }
    else
    {
        int itrim = MAX_CACH_SIZE - ifront;
        memcpy(s_msgdate.g_data_cache + ifront, pdata, itrim);
        memcpy(s_msgdate.g_data_cache, pdata + itrim, len - itrim);
    }
    ifront += len;
    ifront %= MAX_CACH_SIZE;
    for (; irear != ifront; ++irear, irear %= MAX_CACH_SIZE)
    {
        static unsigned char prebyte=0;
        static bool be_picking_data = false;
        static int pick_index = 0;
        static unsigned char frame_len;
        enum 
        {
            en_pos_frame_length,
            en_pos_num_index,
        };
        if (!be_picking_data)
        {
            if (prebyte == MCU_SYNC1 && s_msgdate.g_data_cache[irear] == MCU_SYNC2)
            {
                be_picking_data = true;
                pick_index = 0;
                prebyte = 0;
            }
            prebyte = s_msgdate.g_data_cache[irear];
        }
        else
        {
            s_msgdate.g_data_cmd[pick_index] = s_msgdate.g_data_cache[irear];
            if (pick_index == en_pos_frame_length)
            {
                frame_len = s_msgdate.g_data_cmd[pick_index];
            }
            else
            if (pick_index == frame_len)
            {
                unsigned int fchk_sum = s_msgdate.g_data_cmd[pick_index];
                unsigned int cal_chk_sum = calc_check_sum(s_msgdate.g_data_cmd, frame_len);
                if (fchk_sum == cal_chk_sum)
                {
                    if(klog)
                    {
                        int i;
                        printk("[uart] processed frame = ");
                        for (i = 0; i < frame_len; ++i)
                        {
                            printk("0x%02x ", s_msgdate.g_data_cmd[i]);
                        }
                        printk("\n");
                    }

                    while(in_messages_ready == 1 && msleep_timeout < 100)
                    {
                        msleep_timeout++;
                        msleep(1);
                    }
                    msleep_timeout = 0;

                    printk("pick_data mutex_lock 1 \n");
                    mutex_lock(&messages0_mutex);
                    messages->frame_len = frame_len;
                    memcpy(messages->frame, s_msgdate.g_data_cmd, frame_len);
                    mutex_unlock(&messages0_mutex);

                    printk("pick_data mutex_lock 2, in_messages_ready = %d \n", in_messages_ready);

                    in_messages_ready = 1;
                    wake_up_interruptible(&in_messages_waitq);
                    printk("pick_data mutex_lock 3, in_messages_ready = %d \n", in_messages_ready);
                }
                else
                {
                    printk("fail to checksum1\n");
                    // s_messages_dev.errno++;
                    // memcpy(s_messages_dev.err_men, s_msgdate.g_data_cmd, frame_len);
                }
                be_picking_data = false;
            }
            pick_index++;
        }
    }   
}

static int in_messages_open(struct inode *inode, struct file *filp)
{
    // filp->private_data = messages_devp;

    dev_t major = MAJOR(inode->i_rdev);
    dev_t minor = MINOR(inode->i_rdev);


    printk("in_messages_open, major = %d, minor = %d \n", major, minor);
    return 0;
}

static int in_messages_release(struct inode *inode, struct file *filp)
{
    return 0;
}

static ssize_t in_messages_write(struct file *filp, const char *buf, size_t size, loff_t *ppos)
{
    unsigned long p = *ppos;
    int count = size;
    int ret = 0;

    struct inode *inode = filp->f_path.dentry->d_inode;
    dev_t major = MAJOR(inode->i_rdev);
    dev_t minor = MINOR(inode->i_rdev);
    
    if (in_messages_buff[minor].sync == 0)
        return 0;

    if(p >= MAX_SIZE)
        return 0;
    if(count > MAX_SIZE - p)
        count = MAX_SIZE - p;

    ret = copy_from_user(in_messages_buff[minor].mem + p, buf, count);

    if(ret)
    {
        ret = -EFAULT;
        printk("*** copy_from_user err, ret = %d\n", ret);
    }
    else
    {
        *ppos =+ (count - ret);
        ret = (count - ret);

        pick_data(&in_messages_buff[minor], ret);
    }
    return ret;
}

static ssize_t in_messages_read(struct file *filp, char *buf, size_t size, loff_t *ppos)
{
    unsigned long p = *ppos;
    unsigned int count = size;
    unsigned int len;
    int ret = 0;
    int i;

    struct inode *inode = filp->f_path.dentry->d_inode;
    dev_t major = MAJOR(inode->i_rdev);
    dev_t minor = MINOR(inode->i_rdev);
    printk("in_messages_read, major = %d, minor = %d \n", major, minor);


    return ret;
}

static long in_messages_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
    // messages_dev *dev = filp->private_data;
    switch(cmd)
    {
        case MSG_CLEAR:
            // memset(s_messages_dev.mem, 0, MAX_SIZE);
            // printk(KERN_INFO"globalmem is set to zero\n");
            break;
        default:
            return -EINVAL;
    }
    return 0;
}

static loff_t in_messages_llseek(struct file *filp, loff_t offset, int orig)
{
    loff_t ret = 0;

    return ret;
}

static const struct file_operations in_messages_fops = {
    .owner  = THIS_MODULE,
    .read       = in_messages_read,
    .write      = in_messages_write,
    .unlocked_ioctl = in_messages_ioctl,
    .open       = in_messages_open,
    .release    = in_messages_release,

};


static int out_messages_open(struct inode *inode, struct file *filp)
{
    dev_t major = MAJOR(inode->i_rdev);
    dev_t minor = MINOR(inode->i_rdev);
    in_messages_buff[minor].sync = 1;
    return 0;
}

static int out_messages_release(struct inode *inode, struct file *filp)
{
    dev_t major = MAJOR(inode->i_rdev);
    dev_t minor = MINOR(inode->i_rdev);
    in_messages_buff[minor].sync = 0;
    return 0;
}

static ssize_t out_messages_write(struct file *filp, const char *buf, size_t size, loff_t *ppos)
{
    unsigned long p = *ppos;
    int count = size;
    int ret = 0;

    if(p >= MAX_SIZE)
        return 0;
    if(count > MAX_SIZE - p)
        count = MAX_SIZE - p;

    return ret;
}

static ssize_t out_messages_read(struct file *filp, char *buf, size_t size, loff_t *ppos)
{
    unsigned long p = *ppos;
    unsigned int count = size;
    unsigned int len;
    int ret = 0;
    int i;

    struct inode *inode = filp->f_path.dentry->d_inode;
    dev_t major = MAJOR(inode->i_rdev);
    dev_t minor = MINOR(inode->i_rdev);
 
    printk("out_messages_read mutex_lock 1, sync = %d \n", in_messages_buff[minor].sync);

    wait_event_interruptible(in_messages_waitq, in_messages_ready);

    mutex_lock(&messages0_mutex);
    for (i = 0; i < in_messages_buff[minor].frame_len; ++i)
    {
        buf[i] = in_messages_buff[minor].frame[i];
    }
    printk("out_messages_read mutex_lock 2, in_messages_ready = %d \n", in_messages_ready);
    in_messages_ready = 0;
    mutex_unlock(&messages0_mutex);

    printk("out_messages_read mutex_lock 3, in_messages_ready = %d \n", in_messages_ready);

    return in_messages_buff[minor].frame_len;
}

static long out_messages_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
    switch(cmd)
    {
        case MSG_CLEAR:
            // memset(s_messages_dev.mem, 0, MAX_SIZE);
            // printk(KERN_INFO"globalmem is set to zero\n");
            break;
        default:
            return -EINVAL;
    }
    return 0;
}

static loff_t out_messages_llseek(struct file *filp, loff_t offset, int orig)
{
    loff_t ret = 0;

    return ret;
}


static const struct file_operations out_messages_fops = {
    .owner  = THIS_MODULE,
    .read       = out_messages_read,
    .write      = out_messages_write,
    .unlocked_ioctl = out_messages_ioctl,
    .open       = out_messages_open,
    .release    = out_messages_release,

};

static int messages_init(void)
{

    int err;

    in_messages_major = register_chrdev(0, "in_messages", &in_messages_fops);
    if (in_messages_major < 0) {
        return in_messages_major;
    }
    printk("in_messages_major = %d \n", in_messages_major);

    struct device *messages0_dev;
    messages0_class = class_create(THIS_MODULE, "messages0");
    messages0_dev = device_create(messages0_class, NULL, MKDEV(in_messages_major, 0), NULL, "messages0");
    if (IS_ERR(messages0_dev)) {
        err = PTR_ERR(messages0_dev);
        class_destroy(messages0_class);
        unregister_chrdev(in_messages_major, "messages0");
        return err;
    }

    // err = sysfs_create_group(&(messages0_dev->kobj), messages0_attribute_group);
    // if (err < 0) {
    //   dev_err((struct device *)&(messages0_dev->kobj), "Sysfs registration failed\n");
    // }

    struct device *messages1_dev;
    messages1_class = class_create(THIS_MODULE, "messages1");
    messages1_dev = device_create(messages1_class, NULL, MKDEV(in_messages_major, 1), NULL, "messages1");
    if (IS_ERR(messages1_dev)) {
        err = PTR_ERR(messages1_dev);
        class_destroy(messages1_class);
        unregister_chrdev(in_messages_major, "messages1");
        return err;
    }

    out_messages_major = register_chrdev(0, "out_messages", &out_messages_fops);
    if (out_messages_major < 0) {
        return out_messages_major;
    }
    printk("out_messages_major = %d \n", out_messages_major);

    struct device *messages16_dev;
    messages16_class = class_create(THIS_MODULE, "messages16");
    messages16_dev = device_create(messages16_class, NULL, MKDEV(out_messages_major, 0), NULL, "messages16");
    if (IS_ERR(messages16_dev)) {
        err = PTR_ERR(messages16_dev);
        class_destroy(messages16_class);
        unregister_chrdev(out_messages_major, "messages16");
        return err;
    }

    struct device *messages17_dev;
    messages17_class = class_create(THIS_MODULE, "messages17");
    messages17_dev = device_create(messages17_class, NULL, MKDEV(out_messages_major, 1), NULL, "messages17");
    if (IS_ERR(messages17_dev)) {
        err = PTR_ERR(messages17_dev);
        class_destroy(messages17_class);
        unregister_chrdev(out_messages_major, "messages17");
        return err;
    }

    return 0;
}

static void messages_exit(void)
{
    device_destroy(messages0_class, MKDEV(in_messages_major, 0));
    device_destroy(messages1_class, MKDEV(in_messages_major, 1));
    class_destroy(messages0_class);
    class_destroy(messages1_class);
    unregister_chrdev(in_messages_major, "in_messages");

    device_destroy(messages16_class, MKDEV(out_messages_major, 0));
    device_destroy(messages17_class, MKDEV(out_messages_major, 1));
    class_destroy(messages16_class);
    class_destroy(messages17_class);
    unregister_chrdev(out_messages_major, "out_messages");
}

module_param(in_messages_major, int, S_IRUGO);
module_init(messages_init);
module_exit(messages_exit);
MODULE_LICENSE("GPL");
// uart_app_w.c
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>

main()
{
	int fd, size;
	int i;
	char s1[] = {0xFA, 0xAF ,0x06, 0x04, 0x00, 0x81, 0x04, 0x00, 0x87, 0xFA, 0xAF, 0x07, 0x05, 0x00, 0x09, 0x13, 0x03, 0xAA, 0xB1};
	// char s1[] = {0x01, 0x02 ,0x06, 0x04, 0x00, 0x71, 0x04, 0x00, 0x77, 0x10, 0x20, 0x07, 0x05};
	char s2[] = {0x00, 0x09, 0x13, 0x03, 0xAA, 0xB1, 0xFA, 0xAF, 0x09, 0x06, 0x00, 0x09, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10};
	
	unsigned char buffer[20];
	
	fd = open("/dev/messages0", O_RDWR | O_SYNC);
	printf("fd = %d \n", fd);
	size = write(fd, s1, sizeof(s1));
	close(fd);

	// fd = open("/sys/class/ttyark/message/frame", O_RDWR);
	// printf("fd = %d \n", fd);
	// size = read(fd, buffer, sizeof(buffer));
	
	close(fd);
}
// attr_app_r.c
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>

main()
{
	int fd, size;
	int i, j;
	char s1[] = {0xFA, 0xAF ,0x06, 0x04, 0x00, 0x81, 0x04, 0x00, 0x87, 0xFA, 0xAF, 0x07, 0x05, 0x00, 0x09, 0x13, 0x03, 0xAA, 0xB1, 0xFA, 0xAF, 0x09, 0x06, 0x00};
	// char s1[] = {0x01, 0x02 ,0x06, 0x04, 0x00, 0x71, 0x04, 0x00, 0x77, 0x10, 0x20, 0x07, 0x05};
	char s2[] = {0x00, 0x09, 0x13, 0x03, 0xAA, 0xB1, 0xFA, 0xAF, 0x09, 0x06, 0x00, 0x09, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10};
	unsigned char buffer[20];
	
	// fd = open("/dev/message", O_RDWR);
	// printf("fd = %d \n", fd);
	// size = write(fd, s1, sizeof(s1));
	// close(fd);
	fd = open("/dev/messages16", O_RDWR);
	printf("fd = %d \n", fd);

	for (j = 0; j < 10; ++j)
	{
		size = read(fd, buffer, sizeof(buffer));
		for (i = 0; i < size; ++i)
		{
			printf("0x%02x ", buffer[i]);
		}
		printf("size = %d\n", size);
	}
	close(fd);
}

输入是设备节点,输入是属性结点的版本

// drv_attr.c
#include <linux/module.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/poll.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/wait.h>
#include <linux/sched.h>

#define MAX_SIZE 0x1000    /* 全局内存最大4KB */
#define FRAME_MAX_SIZE 0x80    /* 帧最大长度128Bytes */
#define MSG_CLEAR 0x1      /* 清零全局内存 */

#define     MCU_SYNC1           0xFA
#define     MCU_SYNC2           0xAF
#define     MAX_BYTE_SIZE       0x400
#define     MAX_CACH_SIZE       (MAX_BYTE_SIZE * 4)

static char ttybuf2[MAX_SIZE] = {0x00, 0x09, 0x13, 0x03, 0xAA, 0xB1, 0xFA, 0xAF, 0x09, 0x06, 0x00, 0x09, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10};
static char ttybuf1[MAX_SIZE] = {0xFA, 0xAF ,0x06, 0x04, 0x00, 0x81, 0x04, 0x00, 0x87, 0xFA, 0xAF, 0x07, 0x05};

static DECLARE_WAIT_QUEUE_HEAD(messages_waitq);
static volatile int messages_ready = 0;

static DECLARE_WAIT_QUEUE_HEAD(messages2m_waitq);
static volatile int messages2m_ready = 0;

static int klog = 1;

static int major;
static struct class *ttyark_class;


typedef struct _messages_dev
{
    unsigned int  errno;
    unsigned char err_men[FRAME_MAX_SIZE];
    unsigned char frame_len;
    unsigned char frame[FRAME_MAX_SIZE];
    unsigned char mem[FRAME_MAX_SIZE];
} messages_dev;

// static messages_dev *messages_devp;
static messages_dev s_messages_dev, s_messages2m_dev;


static int messages_open(struct inode *inode, struct file *filp);
static int messages_release(struct inode *inode, struct file *filp);
static long messages_ioctl(struct file *filp,  unsigned int cmd, unsigned long arg);
static ssize_t messages_write(struct file *filp, const char *buf,  size_t size, loff_t *ppos);
static ssize_t messages_read(struct file *filp, char *buf,  size_t size, loff_t *ppos);
static loff_t messages_llseek(struct file *filp, loff_t offset, int orig);


typedef struct _msgdate {
    unsigned char g_data_buff[MAX_BYTE_SIZE];
    unsigned char g_data_cmd[MAX_BYTE_SIZE];
    unsigned char g_data_cache[MAX_BYTE_SIZE];
} msgdata;

static msgdata s_msgdate;
static int ifront = 0, irear = 0;


static unsigned int calc_check_sum(unsigned char* pBuf, int iLen)
{
    int i = 0;
    unsigned int check_sum = 0;

    check_sum = pBuf[0];
    for(i = 1; i < iLen; i++)
    {
        check_sum ^= pBuf[i];
    }

    return check_sum;
}


static void pick_data(unsigned char* pdata, int len)
{
    int ii;

    if(klog)
    {
        printk("[uart] pick_data = %d/%d : ", len, MAX_BYTE_SIZE);
        for ( ii = 0; ii < len; ii++)
        {
            printk("0x%02x,", pdata[ii]);
        }
        printk("\n");
    }

    if (ifront + len <= MAX_CACH_SIZE)
    {
        memcpy(s_msgdate.g_data_cache + ifront, pdata, len);
    }
    else
    {
        int itrim = MAX_CACH_SIZE - ifront;
        memcpy(s_msgdate.g_data_cache + ifront, pdata, itrim);
        memcpy(s_msgdate.g_data_cache, pdata + itrim, len - itrim);
    }
    ifront += len;
    ifront %= MAX_CACH_SIZE;
    for (; irear != ifront; ++irear, irear %= MAX_CACH_SIZE)
    {
        static unsigned char prebyte=0;
        static bool be_picking_data = false;
        static int pick_index = 0;
        static unsigned char frame_len;
        enum 
        {
            en_pos_frame_length,
            en_pos_num_index,
        };
        if (!be_picking_data)
        {
            if (prebyte == MCU_SYNC1 && s_msgdate.g_data_cache[irear] == MCU_SYNC2)
            {
                be_picking_data = true;
                pick_index = 0;
                prebyte = 0;
            }
            prebyte = s_msgdate.g_data_cache[irear];
        }
        else
        {
            s_msgdate.g_data_cmd[pick_index] = s_msgdate.g_data_cache[irear];
            if (pick_index == en_pos_frame_length)
            {
                frame_len = s_msgdate.g_data_cmd[pick_index];
            }
            else
            if (pick_index == frame_len)
            {
                unsigned int fchk_sum = s_msgdate.g_data_cmd[pick_index];
                unsigned int cal_chk_sum = calc_check_sum(s_msgdate.g_data_cmd, frame_len);
                if (fchk_sum == cal_chk_sum)
                {
                    if(klog)
                    {
                        int i;
                        printk("[uart] processed frame = ");
                        for (i = 0; i < frame_len; ++i)
                        {
                            printk("0x%02x ", s_msgdate.g_data_cmd[i]);
                        }
                        printk("\n");
                    }

                    s_messages_dev.frame_len = frame_len;
                    memcpy(s_messages_dev.frame, s_msgdate.g_data_cmd, frame_len);

                    messages_ready = 1;
                    wake_up_interruptible(&messages_waitq);
                    // RmtAdpter::GetInstance()->interpretCommand(s_msgdate.g_data_cmd + 3, frame_len - 3);
                }
                else
                {
                    printk("fail to checksum1\n");
                    s_messages_dev.errno++;
                    memcpy(s_messages_dev.err_men, s_msgdate.g_data_cmd, frame_len);
                }
                be_picking_data = false;
            }
            pick_index++;
        }
    }   
}

static ssize_t show_frame(struct device *dev,
                  struct device_attribute *attr, char *buf)        
{
    int i;

    wait_event_interruptible(messages_waitq, messages_ready);
    messages_ready = 0;

    for (i = 0; i < s_messages_dev.frame_len; ++i)
    {
        buf[i] = s_messages_dev.frame[i];
    }

    return s_messages_dev.frame_len;
}

static ssize_t store_frame(struct device *dev,
                 struct device_attribute *attr,
                 const char *buf, size_t len)        
{

    if (len > FRAME_MAX_SIZE)
        return -EFAULT;


    char buffer1[6] = {0x06, 0x04, 0x00, 0x81, 0x04, 0x00};


    int i;
    for (i = 0; i < len; ++i)
    {
        // s_messages2m_dev.frame[i] = buf[i];
        s_messages2m_dev.frame[i] = buffer1[i];
        printk("%d ", s_messages2m_dev.frame[i]);
    }
    s_messages2m_dev.frame_len = len;

    // memcpy(s_messages2m_dev.frame, buf, len);
    printk("store_frame, len = %d\n", len);


    messages2m_ready = 1;
    wake_up_interruptible(&messages2m_waitq);

    return len;
}

static ssize_t show_frame2string(struct device *dev,
                  struct device_attribute *attr, char *buf)        
{
    return 0;
}

static ssize_t store_frame2string(struct device *dev,
                 struct device_attribute *attr,
                 const char *buf, size_t len)        
{
    // printk("store_primitive_frame len = %d\n", len);

    pick_data(ttybuf1, 13);
    pick_data(ttybuf2, 18);

    return len;
}


static ssize_t show_err(struct device *dev,
                  struct device_attribute *attr, char *buf)        
{
    return 0;
}

static DEVICE_ATTR(frame, S_IWUSR | S_IRUSR, show_frame, store_frame);
static DEVICE_ATTR(frame2string, S_IWUSR | S_IRUSR, show_frame2string, store_frame2string);
static DEVICE_ATTR(err, S_IWUSR | S_IRUSR, show_err, NULL);

static struct attribute *sysfs_attrs_ctrl[] = {
  &dev_attr_frame.attr,
  &dev_attr_frame2string.attr,
  &dev_attr_err.attr,
  NULL
};

static struct attribute_group ttyark_attribute_group[] = {
  {.attrs = sysfs_attrs_ctrl },
};

struct file_operations ttyark_ops = {
    .owner  = THIS_MODULE,
    .write    = messages_write,
    .read   = messages_read,
    .open   = messages_open,
    .release  = messages_release,
    .unlocked_ioctl = messages_ioctl,
    .llseek = messages_llseek,
};

static int messages_open(struct inode *inode, struct file *filp)
{
    // filp->private_data = messages_devp;
    return 0;
}

static int messages_release(struct inode *inode, struct file *filp)
{
    return 0;
}

static ssize_t messages_write(struct file *filp, const char *buf, size_t size, loff_t *ppos)
{
    unsigned long p = *ppos;
    int count = size;
    int ret = 0;

    if(p >= MAX_SIZE)
        return 0;
    if(count > MAX_SIZE - p)
        count = MAX_SIZE - p;

    ret = copy_from_user(s_messages_dev.mem + p, buf, count);

    if(ret)
    {
        ret = -EFAULT;
        printk("*** copy_from_user err, ret = %d\n", ret);
    }
    else
    {
        *ppos =+ (count - ret);
        ret = (count - ret);

        pick_data(s_messages_dev.mem, ret);
    }
    return ret;
}

static ssize_t messages_read(struct file *filp, char *buf, size_t size, loff_t *ppos)
{
    unsigned long p = *ppos;
    unsigned int count = size;
    unsigned int len;
    int ret = 0;
    int i;

    wait_event_interruptible(messages2m_waitq, messages2m_ready);
    messages2m_ready = 0;

    len = s_messages2m_dev.frame[0];
    printk("messages_read, len = %d\n", len);

    if(p >= MAX_SIZE)
        return 0;
    if(count > MAX_SIZE - p)
        count = MAX_SIZE - p;

    printk("messages_read 1 \n");

    if (len < 6)
        return 0;

    printk("messages_read 2 \n");

    for (i = 0; i < len -1; i++)
    {
       s_messages2m_dev.mem[i +2] = s_messages2m_dev.frame[i];
    }

    printk("messages_read 3 \n");

    s_messages2m_dev.mem[0] = 0xfa;
    s_messages2m_dev.mem[1] = 0xaf;
    s_messages2m_dev.mem[len +3 -1] = calc_check_sum(&s_messages2m_dev.mem[2], len);

    printk("messages_read 4, check_sum = 0x%02x \n");

    for (i = 0; i < len +3; ++i)
    {
        printk("0x%02x ", s_messages2m_dev.mem[i]);
    }

    printk("\n");

    ret = copy_to_user(buf, s_messages2m_dev.mem +p, len +3);
    if(ret)
    {
        ret = -EFAULT;
        printk("*** copy_to_user err, ret = %d\n", ret);
    }
    else
    {
        // *ppos += (count - ret);
        // ret = (count -ret);
        *ppos += (len +3 -ret);
        ret = (len +3 -ret);
         
    }
    return ret;
}

static long messages_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
    // messages_dev *dev = filp->private_data;
    switch(cmd)
    {
        case MSG_CLEAR:
            memset(s_messages_dev.mem, 0, MAX_SIZE);
            printk(KERN_INFO"globalmem is set to zero\n");
            break;
        default:
            return -EINVAL;
    }
    return 0;
}

static loff_t messages_llseek(struct file *filp, loff_t offset, int orig)
{
    loff_t ret = 0;
    switch(orig)
    {
        case 0:
            if(offset < 0)
            {
                ret = -EINVAL;
                break;
            }

            if((unsigned int )offset > MAX_SIZE)
            {
                ret = -EINVAL;
                break;
            }
            filp->f_pos = (unsigned int)offset;
            ret = filp->f_pos;
            break;

        case 1:   //相对文件当前位置偏移
            if((filp->f_pos + offset) > MAX_SIZE)
            {
                ret = -EINVAL;
                break;
            }
            if((filp->f_pos + offset) < 0)
            {
                ret = -EINVAL;
                break;
            }
            filp->f_pos += offset;
            ret = filp->f_pos;
            break;
        default:
            ret = -EINVAL;
            break;
    }
    return ret;
}

static int ttyark_init(void)
{
    int err;
    struct device *ttyarkdev;
    major = register_chrdev(0, "ttyark", &ttyark_ops);
    if (major < 0) {
        return major;
    }

    printk("register_chrdev = %d \n", major);

    ttyark_class = class_create(THIS_MODULE, "ttyark");
    ttyarkdev = device_create(ttyark_class, NULL, MKDEV(major, 0), NULL, "message");
    if (IS_ERR(ttyarkdev)) {
        err = PTR_ERR(ttyarkdev);
        class_destroy(ttyark_class);
        unregister_chrdev(major, "ttyark");
        return err;
    }

    err = sysfs_create_group(&(ttyarkdev->kobj), ttyark_attribute_group);
    if (err < 0) {
      dev_err((struct device *)&(ttyarkdev->kobj), "Sysfs registration failed\n");
    }

    return 0;
}

static void ttyark_exit(void)
{
    device_destroy(ttyark_class, MKDEV(major,0));
    class_destroy(ttyark_class);
    unregister_chrdev(major, "ttyark");
}

module_init(ttyark_init);
module_exit(ttyark_exit);
MODULE_LICENSE("GPL");

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值