2

我正在尝试为自定义硬件实现 SPI 驱动程序。我从 spidev 驱动程序的副本开始,它支持几乎所有我需要的东西。

我们使用的协议包含三个部分:命令位(读/写)、地址和任意数量的数据。

我曾假设简单地添加 lseek 功能将是做到这一点的最佳方式。“寻找”到所需的地址,然后读取或写入任意数量的字节。我在新驱动程序的 file_operations 中创建了一个自定义 .llseek,但我从未见过该函数被调用过。我尝试过使用 fseek()、lseek() 和 pread(),但这些函数似乎都没有调用新的 my_lseek() 函数。每个呼叫都报告“errno 29 ESPIPE Illegal Seek”

该设备在 board.c 文件中定义:

static struct spi_board_info my_spi_board_info[] __initdata = {
[0] = {
    .modalias      = "myspi",
    .bus_num        = 1,
    .chip_select    = 0,
    .max_speed_hz   = 3000000,
    .mode           = SPI_MODE_0,
    .controller_data = &spidev_mcspi_config,
}, ...

我怀疑开发文件的创建方式可能有些问题,主要是因为我找到的示例引用了 filp->f_pos

static int myspi_llseek(struct file *filp, loff_t off, int whence)
{
    ...
    newpos = filp->f_pos + off;
    ...
}

所以我的问题是:有没有办法让这个驱动程序(轻微修改的 spidev)支持“seek”调用?这在什么时候被定义为返回 errno 29?我是否必须从新驱动程序开始,并且不能依赖 spi_board_info() 和 spi_register_board_info() 设置?

/drivers/spi 目录 (spi-dw) 中只有一个驱动程序引用 lseek,它们使用 default_llseek 实现。我们想出了一些“技巧”来让一切正常运行,但我倾向于学习以正确的方式完成它。

任何建议都非常感谢!(PS,OMAP安卓系统内核版本为3.4.48)

4

1 回答 1

4

Spi 驱动程序不支持任何 llseek 或 fseek 功能。它有这么多的回调函数。

 struct spi_driver {
    const struct spi_device_id *id_table;
    int                     (*probe)(struct spi_device *spi);
    int                     (*remove)(struct spi_device *spi);
    void                    (*shutdown)(struct spi_device *spi);
    int                     (*suspend)(struct spi_device *spi, pm_message_t mesg);
    int                     (*resume)(struct spi_device *spi);
    struct device_driver    driver;

};

现在drivers/spi/spi-dw.c注册为charter-driver(debugfs_create_file("registers", S_IFREG | S_IRUGO, dws->debugfs, (void *)dws, &dw_spi_regs_ops);)。所以他们实现在 debugfs 文件系统中创建一个文件。他们实现了 lseek 回调函数。

static const struct file_operations dw_spi_regs_ops = {
    .owner          = THIS_MODULE,
    .open           = simple_open,
    .read           = dw_spi_show_regs,
    .llseek         = default_llseek,

}; file_operations 结构在 linux/fs.h 中定义,并保存指向由驱动程序定义的函数的指针,这些函数在设备上执行各种操作。结构的每个字段对应于驱动程序定义的一些函数的地址,用于处理请求的操作

lseek -: lseek 是一个系统调用,用于更改文件描述符的读/写指针的位置。

SPI -: “串行外围接口”(SPI) 是一种同步四线串行链路,用于将微控制器连接到传感器、存储器和外围设备。SPI 不能提供任何 lseek 和 fseek 功能。

有两种类型的 SPI 驱动程序 ( https://www.kernel.org/doc/Documentation/spi/spi-summary )

控制器驱动程序......控制器可以内置在片上系统处理器中,并且通常支持主从角色。这些驱动程序接触硬件寄存器并且可能使用 DMA。或者它们可以是 PIO bitbangers,只需要 GPIO 引脚。

协议驱动程序...它们通过控制器驱动程序传递消息,以与 SPI 链路另一端的从设备或主设备进行通信。

如果你想用户读、写和 llseek,那么你必须在 SPI 上注册一个宪章驱动程序。然后,您将能够实现您的成就。

于 2016-06-05T04:34:12.953 回答