【发布时间】:2014-03-12 23:26:07
【问题描述】:
我正在为具有三种不同读/写操作(闪存、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;
}
【问题讨论】:
标签: c linux usb linux-device-driver ioctl