linux下的SPI/I2C驱动如何管理多个相同的设备,设备地址不同

问题

linux下的I2C驱动如何管理多个相同的设备,设备地址不同。

使用linux提供的I2C的框架,通过id来匹配设备。
如何管理多个相同的设备,设备地址不同。

一个驱动程序对应多个设备

原文链接:https://blog.csdn.net/qqliyunpeng/article/details/52387525

1. 对于驱动程序中有两个关键的结构体:

struct file *filp:
有一个关键的成员 -> void *private_data,用于存放用于私人的数据
inode:
有一个关键的成员 -> unsigned int i_flags

2. 一个驱动多个设备的程序思路:

1个驱动程序,
1个struct file_operations 结构体
2个用户结构体数据(包含 struct cdev 结构体)
在 struct file_operation 结构体的 open 方法中根据 inode 结构体中的 i_cdev 成员找到 包含 cdev 的整个结构体,从而能在read/write中能够操作这个结构体的其他成员,具体如下:
在 open 中 将得到的 cdev 通过 struct file 结构体中的private_data 传递给 read/write 方法:
filp->private_data = dev;
当然设备号和设备节点都是两个,通过访问不同的 /dev 下的设备,访问不同的用户数据

3. 程序:

char_multi_dev.c

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <asm/uaccess.h>
#include <linux/device.h>
 
MODULE_LICENSE ("GPL");
 
int hello_major       = 250;
int hello_minor       = 0;
int number_of_devices = 2;
struct class *my_class;
 
struct hello_device
{
    char data[128];
    struct cdev cdev;
 
} hello_device[2];
 
 
static int hello_open (struct inode *inode, struct file *filp)
{
    struct hello_device *dev = container_of(inode->i_cdev, struct hello_device, cdev); 
 
    filp->private_data = dev;
    printk (KERN_INFO "Hey! device opened\n");
 
    return 0;
}
 
static int hello_release (struct inode *inode, struct file *filp)
{
    printk (KERN_INFO "Hmmm... device closed\n");
 
    return 0;
}
 
ssize_t hello_read (struct file *filp, char *buff, size_t count, loff_t *offp)
{
    ssize_t result = 0;
    struct hello_device *dev = filp->private_data;
 
    if (count < 0) return -EINVAL;
    if (count > 127) count = 127;
    if (copy_to_user (buff, dev->data, count)) 
    {
        result = -EFAULT;
    }
    else
    {
        printk (KERN_INFO "wrote %d bytes\n", (int)count);
        result = count;
    }
 
    return result;
}
 
/*
 *ssize_t hello_write (struct file *filp, const char  *buf, size_t count,
 *        loff_t *f_pos)
 *{
 *    ssize_t ret = 0;
 *
 *    printk (KERN_INFO "Writing %d bytes\n", count);
 *    if (count > 127) return -ENOMEM;
 *    if (count < 0) return -EINVAL;
 *    if (copy_from_user (data, buf, count)) {
 *        ret = -EFAULT;
 *    }
 *    else {
 *        data[count] = '\0';
 *        printk (KERN_INFO"Received: %s\n", data);
 *        ret = count;
 *    }
 *
 *    return ret;
 *}
 */
 
 
struct file_operations hello_fops = {
    .owner = THIS_MODULE,
    .open  = hello_open,
    .release = hello_release,
    .read  = hello_read,
    /*  .write = hello_write */
};
 
static void char_reg_setup_cdev (struct cdev *cdev, dev_t devno)
{
    int error;
 
    cdev_init (cdev, &hello_fops);
    cdev->owner = THIS_MODULE;
    error = cdev_add (cdev, devno , 1);
    if (error)
        printk (KERN_NOTICE "Error %d adding char_reg_setup_cdev", error);
}
 
static int __init hello_2_init (void)
{
    int result;
    dev_t devno;
 
    devno = MKDEV (hello_major, hello_minor);
    result = register_chrdev_region (devno, number_of_devices, "hello_multi");
 
    if (result < 0) {
        printk (KERN_WARNING "hello: can't get major number %d\n", hello_major);
        return result;
    }
    my_class = class_create(THIS_MODULE,"multi_dev_class");
    if(IS_ERR(my_class)) 
    {
        printk("Err: failed in creating class.\n");
        return -1; 
    }
    device_create(my_class,NULL, devno, NULL, "multi_dev0");
    device_create(my_class,NULL, devno + 1, NULL, "multi_dev1");
 
    char_reg_setup_cdev (&hello_device[0].cdev, devno);
    char_reg_setup_cdev (&hello_device[1].cdev, devno+1);
    printk (KERN_INFO "char device registered\n");
    strcpy(hello_device[0].data, "0000000000000000000");
    strcpy(hello_device[1].data, "1111111111111111111");
 
    return 0;
}
 
static void __exit hello_2_exit (void)
{
    dev_t devno = MKDEV (hello_major, hello_minor);
 
    cdev_del (&hello_device[0].cdev);
    cdev_del (&hello_device[1].cdev);
 
    device_destroy(my_class, devno);         // delete device node under /dev//必须先删除设备,再删除class类
    device_destroy(my_class, devno + 1);     // delete device node under /dev//必须先删除设备,再删除class类
    class_destroy(my_class);                 // delete class created by us
    unregister_chrdev_region (devno, number_of_devices);
    printk("char device exited\n");
}
 
module_init (hello_2_init);
module_exit (hello_2_exit);

关键点是 96行 和 98行
对 container_of 函数的理解请看: http://blog.csdn.net/boygrass/article/details/9962161?locationNum=1

test.c

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
 
int main (void) 
{
    int fd1, fd2;
    char buf[64];
 
    if ((fd1 = open ("/dev/multi_dev0",O_RDONLY)) < 0)
    {
        perror("fail to open");
        return -1;
    }
    if ((fd2 = open ("/dev/multi_dev1",O_RDONLY)) < 0)
    {
        perror("fail to open");
        return -1;
    }
 
    read(fd1, buf, 64);
    printf("read from device0 : %s\n", buf);
    read(fd2, buf, 64);
    printf("read from device1 : %s\n", buf);
 
    return 0;
}

运行结果

> sudo insmod char_multi_dev.ko 
>sudo ./a.out 
read from device0 : 0000000000000000000
read from device1 : 1111111111111111111
>sudo rmmod char_multi_dev
>dmesg
[11074.012373] char device registered
[11087.349961] Hey! device opened
[11087.349965] Hey! device opened
[11087.349967] wrote 64 bytes
[11087.350021] wrote 64 bytes
[11087.350055] Hmmm... device closed
[11087.350057] Hmmm... device closed
[11115.543117] char device exited
  • 1
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值