gpt4 book ai didi

c - 具有多个读取操作、ioctl 或 fops 的 Linux USB 驱动程序?

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:59:08 24 4
gpt4 key购买 nike

我正在为具有三种不同读/写操作(闪存、EEPROM 和 I2C)的 USB 设备编写驱动程序,每种操作都有不同的实现。我一直在摸不着头脑,因为我是整个 linux 内核开发世界的新手。我读过我应该不惜一切代价避免使用 ioctl,但我不知道如何实现它。由于 linux 中的所有内容都是一个文件,我可以为每个位置创建多个端点来写入吗?我什至会怎么做呢?我会定义多个 usb_class_driver 结构吗?

另一方面,我是否应该在单个端点中包含所有功能并使用 ioctl?将同一个驱动程序的工作分开还是将所有功能整合到一个地方更好?

我不能使用 libusb,因为它对等时传输的限制和对 dma 传输缺乏直接控制(两者都需要产品最终产品)。

更新:在尝试对每个端点使用多个通用文件操作并获得 -98 的响应代码(已注册)之后,我想我将不得不使用带有 ioctl 的单个端点。无效的代码如下:

在adriver.h中

static struct usb_class_driver adriver_eeprom_class = {
.name = "usb/adriver_eeprom%d",
.fops = &adriver_eeprom_fops,
.minor_base = USB_SKEL_MINOR_BASE,
};
static struct usb_class_driver adriver_flash_class = {
.name = "usb/adriver_flash%d",
.fops = &adriver_flash_fops,
.minor_base = USB_SKEL_MINOR_BASE,
};
static struct usb_class_driver adriver_i2c_class = {
.name = "usb/adriver_i2c%d",
.fops = &adriver_i2c_fops,
.minor_base = USB_SKEL_MINOR_BASE,
};
static struct usb_class_driver driver_fifo_class = {
.name = "usb/driver_fifo%d",
.fops = &driver_fifo_fops,
.minor_base = USB_SKEL_MINOR_BASE,
};
static struct usb_class_driver adriver_class = {
.name = "usb/adriver%d",
.fops = &adriver_fops,
.minor_base = USB_SKEL_MINOR_BASE,
};

在adriver.c

static int adriver_probe(struct usb_interface *interface, const struct usb_device_id *id) {
struct usb_device *udev = interface_to_usbdev(interface);
struct usb_adriver *gdev;
int retval = -ENOMEM;
gdev = kmalloc(sizeof(struct usb_adriver), GFP_KERNEL);
if(gdev == NULL)
{
dev_err(&interface->dev, "Out of memory\n");
goto error;
}
memset(gdev, 0x00, sizeof(*gdev));

kref_init(&gdev->kref);

gdev->udev = usb_get_dev(udev);

usb_set_intfdata(interface,gdev);

retval = usb_register_dev(interface, &adriver_eeprom_class);
if (retval) {
/* something prevented us from registering this driver */
pr_err("Not able to get a minor for this device.");
usb_set_intfdata(interface, NULL);
goto error;
}
retval = usb_register_dev(interface, &adriver_flash_class);
if (retval) {
/* something prevented us from registering this driver */
pr_err("Not able to get a minor for this device.");
usb_set_intfdata(interface, NULL);
goto error;
}
retval = usb_register_dev(interface, &adriver_i2c_class);
if (retval) {
/* something prevented us from registering this driver */
pr_err("Not able to get a minor for this device.");
usb_set_intfdata(interface, NULL);
goto error;
}
retval = usb_register_dev(interface, &adriver_fifo_class);
if (retval) {
/* something prevented us from registering this driver */
pr_err("Not able to get a minor for this device.");
usb_set_intfdata(interface, NULL);
goto error;
}
retval = usb_register_dev(interface, &adriver_class);
if (retval) {
/* something prevented us from registering this driver */
pr_err("Not able to get a minor for this device.");
usb_set_intfdata(interface, NULL);
goto error;
}

dev_info(&interface->dev, "USB adriver device now attached\n");
return 0;

error:
if (gdev)
kref_put(&gdev->kref, adriver_delete);
return retval;
}

最佳答案

设备驱动程序可以按照您最初的建议创建 3 个设备。如果设备上只有一个 IRQ,这个模型就更合适了。

凭借一点运气和技巧(可能更多的是后者),驱动程序的读写例程只需要实现为一个用于读取的函数和一个用于传递额外参数的写入函数,或者读/写例程推断通过检查它的 struct file * 参数(如果命名为 f,则 MINOR(f -> f_dentry -> d_inode -> i_rdev ) 给出设备的次要设备 ID。由于您使用 device_create()probe() 函数中控制次要设备分配,因此您可以利用它来关联有用的类型信息。

通过这种方式,很容易避免 ioctl,对于简单的读写操作,确实应该避免。这使得通过 bash 脚本、命令行等方式使用该设备变得很容易。如果涉及 ioctl,则意味着需要一种编程语言才能使用它。
ioctl() 的手册页说

The [ioctl] call is used as a catch-all for operations that don't cleanly fit the UNIX stream I/O model.

关于c - 具有多个读取操作、ioctl 或 fops 的 Linux USB 驱动程序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22365997/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com