4,441
社区成员
发帖
与我相关
我的任务
分享
#define DATA_SIZE 1024
static struct i2c_client *myi2cdrv_client;
static int myi2cdrv_major = 0;
static char myi2cdrv_buf[DATA_SIZE] ;
static struct class * myi2cdrv_class = NULL;
static struct class_device *myi2cdrv_class_dev = NULL;
#define SET_OFFSET 0
//偏移量
static char myi2cdrv_offset = 0 ;
static unsigned short ignore[] = { I2C_CLIENT_END };
static unsigned short normal_addr[] = { 0x50, I2C_CLIENT_END };
static struct i2c_client_address_data myi2cdrv_addr_data = {
.normal_i2c = normal_addr,
.probe = ignore,
.ignore = ignore,
};
static int myi2cdrv_attach_adapter(struct i2c_adapter *adapter);
static int myi2cdrv_detach_client(struct i2c_client *client);
static struct i2c_driver my_i2c_driver ={
.driver = {
.name = "my_i2c_driver",
},
.attach_adapter = myi2cdrv_attach_adapter,
.detach_client = myi2cdrv_detach_client,
};
static int myi2cdrv_open(struct inode *inode, struct file *file)
{
//myi2cdrv_offset = 0 ;
return 0;
}
static ssize_t myi2cdrv_read(struct file *file, char __user *buf, size_t size, loff_t *opps)
{
struct i2c_msg i2cmsg[2];
char addr = myi2cdrv_offset;
int ret;
printk("read offset = %d \n",addr);
i2cmsg[0].addr =myi2cdrv_client->addr;
i2cmsg[0].flags =0;
i2cmsg[0].len =1;
i2cmsg[0].buf =&addr;
i2cmsg[1].addr = myi2cdrv_client->addr;
i2cmsg[1].flags = 1;
i2cmsg[1].len = size;
i2cmsg[1].buf = myi2cdrv_buf;
ret = i2c_transfer(myi2cdrv_client->adapter, i2cmsg, 2);
if(ret == 2){
ret = copy_to_user(buf, myi2cdrv_buf, size);
if(!ret)
return size;
else
return size-ret;
}else{
return -1;
}
}
static ssize_t myi2cdrv_write(struct file *file, const char __user *buf, size_t size, loff_t *opps)
{
struct i2c_msg i2cmsg[1];
char addr = myi2cdrv_offset;
int ret;
ret = copy_from_user(&myi2cdrv_buf[1], buf, size);
if(ret){
size -=ret;
}
myi2cdrv_buf[0] = addr;
printk("write offset = %d \n",myi2cdrv_buf[0]);
i2cmsg[0].addr =myi2cdrv_client->addr;
i2cmsg[0].flags =0;
i2cmsg[0].len =size + 1;
i2cmsg[0].buf =myi2cdrv_buf;
ret = i2c_transfer(myi2cdrv_client->adapter, i2cmsg, 1);
if(ret == 1)
return size;
else
return -1;
}
static int myi2cdrv_close(struct inode *inode, struct file *file)
{
return 0;
}
static int myi2cdrv_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
int ret;
switch (cmd) {
case SET_OFFSET:
ret = copy_from_user(&myi2cdrv_offset ,(char *)arg ,1);
printk("ioctl offset = %d \n",myi2cdrv_offset);
break;
default:
printk("ioctl nothing to do \n");
}
return 0;
}
static struct file_operations myi2cdrv_dev_fops = {
.owner = THIS_MODULE,
.open = myi2cdrv_open,
.read = myi2cdrv_read,
.write = myi2cdrv_write,
.release = myi2cdrv_close,
.ioctl = myi2cdrv_ioctl,
};
static int myi2cdrv_client_detect(struct i2c_adapter *adapter, int addr, int kind)
{
myi2cdrv_client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
myi2cdrv_client->addr = addr;
myi2cdrv_client->adapter = adapter;
myi2cdrv_client->driver = &my_i2c_driver;
myi2cdrv_client->flags = 0;
i2c_attach_client(myi2cdrv_client);
myi2cdrv_major = register_chrdev(0, "myi2cdrv_dev",&myi2cdrv_dev_fops);
myi2cdrv_class = class_create(THIS_MODULE, "myclass");
myi2cdrv_class_dev = class_device_create(myi2cdrv_class, NULL, MKDEV(myi2cdrv_major,0), NULL, "myi2cdrv");
return 0;
}
static int myi2cdrv_attach_adapter(struct i2c_adapter *adapter)
{
return i2c_probe(adapter, &myi2cdrv_addr_data, myi2cdrv_client_detect);
}
static int myi2cdrv_detach_client(struct i2c_client *client)
{
return 0;
}
static int __init myi2cdrv_init(void)
{
i2c_add_driver(&my_i2c_driver);
return 0;
}
static void __exit myi2cdrv_exit(void)
{
unregister_chrdev(myi2cdrv_major, "myi2cdrv_dev");
class_device_unregister(myi2cdrv_class_dev);
class_unregister(myi2cdrv_class);
i2c_del_driver(&my_i2c_driver);
}
module_init(myi2cdrv_init);
module_exit(myi2cdrv_exit);
MODULE_LICENSE("GPL");