i2c驱动程序是否需要像其他任何字符设备驱动程序一样实现?

时间:2017-01-05 19:11:25

标签: linux linux-device-driver i2c

我是Linux设备驱动程序的菜鸟,所以请耐心等待。我试图实现i2c驱动程序(客户端)。它可以insmod.probe被调用(因为设备树条目),而在.probe中我可以读/写设备。大。

但是我需要能够启动从用户空间到驱动程序的读/写操作。为了做到这一点,i2c驱动程序是否应该像任何其他char设备驱动程序一样?意味着拥有file_operations结构,因此用户空间可以openclosereadwriteioctls

我问,因为在我见过的所有i2c客户端示例中,没有人实现过我提到过的这些事情。我想知道他们如何在没有设置file_operations结构的情况下从用户空间发起呼叫。也许这是显而易见的,没有人提到它,我不知道......我想知道它是否是因为i2c被称为平台设备驱动程序它不需要这个?如果有人能证实那可以帮助我猜测自己。

如果您了解我的要求,请忽略其余部分。如果你对我的问题感到困惑,这里是对我要问的更具体的解释:

我现在拥有的东西:

static int device_probe(struct i2c_client           *client,
                        const struct i2c_device_id  *id)
{
    struct device      *dev = &client->dev;
    struct device_data *data;

    /* Check the functionality of the i2c-adapter for smbus byte read/write */
    if (!i2c_check_functionality(client->adapter,
                                 I2C_FUNC_SMBUS_BYTE_DATA))
    {
        printk(KERN_ALERT "%s %d: device required i2c functionality is not supported\n", __func__, __LINE__);
        return -ENODEV;
    }

    /* Allocate memory to hold the device data
     * Using devm_kzalloc so do not have to worry about kfree */
    data = devm_kzalloc(dev, sizeof(struct device_data), GFP_KERNEL);
    if (dev == NULL)
    {
        printk(KERN_ALERT "%s %d: no memory\n", __func__, __LINE__);
        return -ENOMEM;
    }

    /* Record the pointer to current client */
    data->device_i2c_client = client;

    /* Set the client's data field to point to device-specific data struct */
    i2c_set_clientdata(client, data);

    /* Add the device-specific data struct to our collection of device client devices */
    device_data_tbl[id->driver_data] = data;

    /* Do a read, test the access */
    device_read();

    return 0;
}

static int device_remove(struct i2c_client *client)
{
    return 0;
}


int device_read(uint8_t             device_device_id,
                uint16_t const      dev_reg_addr,
                uint8_t *const      read_val)
{
    /* some read access */
}

static struct i2c_device_id device_idtable[] = {
    { "si5342",   0 },
    { },
};
MODULE_DEVICE_TABLE(i2c, device_idtable);

static struct i2c_driver device_driver = {
  .driver = {
    .name = device_DRIVER_NAME,
        .owner  = THIS_MODULE
  },
  .id_table = device_idtable,
    .probe      = device_probe,
    .remove     = device_remove,
};

static int __init device_driver_init(void)
{
    return i2c_add_driver(&device_driver);
}
module_init(device_driver_init);


static void __exit device_driver_exit(void)
{
    return i2c_del_driver(&device_driver);
}
module_exit(device_driver_exit);

想知道是否需要在

中添加以下元素
static struct file_operations oxdrv_fops =
{
    .owner   = THIS_MODULE,
    .release = device_release,
    .open    = device_open,
    .unlocked_ioctl = device_ioctl
};

/* Associated function definitions: device_open, device_ioctl, etc */

alloc_chrdev_region();
cdev_init();

1 个答案:

答案 0 :(得分:1)

我想我现在更了解设备驱动程序模型@Alexandre Belloni的评论并阅读这组演示幻灯片:http://free-electrons.com/doc/training/linux-kernel/linux-kernel-slides.pdf。相关幻灯片来自第221页至第236页。

有3种类型的设备驱动程序:

  1. 字符
  2. 网络
  3. 然而,有特定的"框架"作为字符设备驱动程序的子类存在,它实现了相同类型设备的驱动程序的公共部分。

    例如,用于硬件监控的主板上的温度传感器将在hwmon框架(https://www.kernel.org/doc/Documentation/hwmon/hwmon-kernel-api.txt)下注册。您将实现i2c probereadwrite功能,但不是将其整形为具有file_operations struct的字符设备,您只需将其注册为hwmon设备: hwmon_device_register_with_groups()。要向用户空间公开,您需要使用/sys/class/hwmon/hwmon*使用所需的公开读/写命令列表构建attributes目录(例如:从通道1读取临时值,写入限制临时寄存器)。

    构建内核时,请在make menuconfig中选择您的设备,以便使用内核构建它。有了这个,一旦启动内核,设备将显示在/sys/class/hwmon/hwmon*下,然后用户空间可以通过sysfs接口从设备openread。 在这里查看一个很好的例子:http://lxr.free-electrons.com/source/drivers/hwmon/tmp421.c。或者hwmon目录中的任何设备。

    这就是我的困惑所在。正如@Alexandre Belloni指出的那样,这些设备是在框架下注册的,因此不需要明确的字符设备驱动程序代码。对我来说情况并非如此,我不认为我正在做的设备(时钟PLL)有一个合适的框架。因此,我需要走一般路线并实施为角色设备。这也允许我作为模块加载/卸载,而不是在内核启动时自动加载。

    请随时纠正我所犯的任何错误。我希望这对于其他任何对编写i2c-clients感到困惑的人都有帮助。