由于在互斥和同步等待队列上存在不能完全同步的问题,还有在内核里做应答重发比较复杂,最终没有采用此方式
把代码放到此做笔记,供下次开发参考
输入输出都是设备节点的版本
// 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");